Source:SLASH'EM 0.0.7E7F2/sp lev.c

Below is the full text to sp_lev.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/sp_lev.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

1.   /*	SCCS Id: @(#)sp_lev.c	3.4	2001/09/06	*/ 2.   /*	Copyright (c) 1989 by Jean-Christophe Collet */ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.     5.    /*  6.     * This file contains the various functions that are related to the special 7.    * levels. 8.    * It contains also the special level loader. 9.    *  10.    */  11.    12.   #include "hack.h"  13. #include "dlb.h" 14. /* #define DEBUG */	/* uncomment to enable code debugging */ 15.   16.   #ifdef DEBUG 17.  # ifdef WIZARD 18.  #define debugpline	if (wizard) pline 19.  # else 20.  #define debugpline	pline 21.  # endif 22.  #endif 23.   24.   #include "sp_lev.h"  25. #include "rect.h" 26. 27.  extern void FDECL(mkmap, (lev_init *)); 28.   29.   STATIC_DCL void FDECL(get_room_loc, (schar *, schar *, struct mkroom *)); 30.  STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *)); 31.  STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *)); 32.  STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P)); 33.  STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *)); 34.  STATIC_DCL void FDECL(create_object, (object *, struct mkroom *)); 35.  STATIC_DCL void FDECL(create_engraving, (engraving *,struct mkroom *)); 36.  STATIC_DCL void FDECL(create_stairs, (stair *, struct mkroom *)); 37.  STATIC_DCL void FDECL(create_altar, (altar *, struct mkroom *)); 38.  STATIC_DCL void FDECL(create_gold, (gold *, struct mkroom *)); 39.  STATIC_DCL void FDECL(create_feature, (int,int,struct mkroom *,int)); 40.  STATIC_DCL boolean FDECL(search_door, (struct mkroom *, xchar *, xchar *, 41.  					XCHAR_P, int)); 42.  STATIC_DCL void NDECL(fix_stair_rooms); 43.  STATIC_DCL void FDECL(create_corridor, (corridor *)); 44.   45.   STATIC_DCL boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P, 46.  					XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); 47.   48.   #define LEFT	1 49.  #define H_LEFT	2 50.  #define CENTER	3 51.  #define H_RIGHT	4 52.  #define RIGHT	5 53.   54.   #define TOP	1 55.  #define BOTTOM	5 56.   57.   #define sq(x) ((x)*(x)) 58.   59.   #define XLIM	4 60.  #define YLIM	3 61.   62.   #define Fread	(void)dlb_fread 63.  #define Fgetc	(schar)dlb_fgetc 64.  #define New(type)		(type *) alloc(sizeof(type)) 65.  #define NewTab(type, size)	(type **) alloc(sizeof(type *) * (unsigned)size) 66.  #define Free(ptr)		if(ptr) free((genericptr_t) (ptr)) 67.   68.   static NEARDATA walk walklist[50]; 69.  extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */ 70.   71.   static char Map[COLNO][ROWNO]; 72.  static char robjects[10], rloc_x[10][10], rloc_y[10][10], rmonst[10]; 73.  static aligntyp	ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL }; 74.  static NEARDATA xchar xstart, ystart; 75.  static NEARDATA char xsize, ysize; 76.  static lev_region rarea[10]; 77.   78.   STATIC_DCL void FDECL(set_wall_property, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,int)); 79.  STATIC_DCL int NDECL(rnddoor); 80.  STATIC_DCL int NDECL(rndtrap); 81.  STATIC_DCL boolean FDECL(get_location, (schar *,schar *,int)); 82.  STATIC_DCL void FDECL(sp_lev_shuffle, (char *,char *,int)); 83.  STATIC_DCL void FDECL(light_region, (region *)); 84.  STATIC_DCL void FDECL(load_common_data, (dlb *,int)); 85.  STATIC_DCL void FDECL(load_one_monster, (dlb *,monster *)); 86.  STATIC_DCL void FDECL(load_one_object, (dlb *,object *)); 87.  STATIC_DCL void FDECL(load_one_engraving, (dlb *,engraving *)); 88.  STATIC_DCL boolean FDECL(load_rooms, (dlb *)); 89.  STATIC_DCL void FDECL(maze1xy, (coord *,int)); 90.  STATIC_DCL boolean FDECL(load_maze, (dlb *)); 91.  STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *)); 92.  STATIC_DCL void FDECL(free_rooms,(room **, int)); 93.  STATIC_DCL void FDECL(build_room, (room *, room*)); 94.   95.   char *lev_message = 0; 96.  lev_region *lregions = 0; 97.  int num_lregions = 0; 98.  lev_init init_lev; 99.   100.  /*  101.   * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able 102.  */  103.   104.  STATIC_OVL void 105. set_wall_property(x1,y1,x2,y2, prop) 106. xchar x1, y1, x2, y2; 107. int prop; 108. {  109.  	register xchar x, y;  110. 111. 	for(y = y1; y <= y2; y++) 112. 	    for(x = x1; x <= x2; x++) 113. 		if(IS_STWALL(levl[x][y].typ)) 114. 		    levl[x][y].wall_info |= prop; 115. }  116.   117.  /*  118.   * Choose randomly the state (nodoor, open, closed or locked) for a door 119.  */  120.  STATIC_OVL int 121. rnddoor 122. {  123.  	int i = 1 << rn2(5); 124. 	i >>= 1; 125. 	return i;  126. } 127.   128.  /*  129.   * Select a random trap 130.  */  131.  STATIC_OVL int 132. rndtrap 133. {  134.  	int rtrap; 135.  136.  	do { 137. 	    rtrap = rnd(TRAPNUM-1); 138. 	    switch (rtrap) { 139. 	     case HOLE:		/* no random holes on special levels */ 140. 	     case MAGIC_PORTAL:	rtrap = NO_TRAP; 141. 				break; 142. 	     case TRAPDOOR:	if (!Can_dig_down(&u.uz)) rtrap = NO_TRAP; 143. 				break; 144. 	     case LEVEL_TELEP: 145. 	     case TELEP_TRAP:	if (level.flags.noteleport) rtrap = NO_TRAP; 146. 				break; 147. 	     case ROLLING_BOULDER_TRAP: 148. 	     case ROCKTRAP:	if (In_endgame(&u.uz)) rtrap = NO_TRAP; 149. 				break; 150. 	    }  151.  	} while (rtrap == NO_TRAP); 152. 	return rtrap; 153. }  154.   155.  /*  156.   * Coordinates in special level files are handled specially: 157.  *  158.   *	if x or y is -11, we generate a random coordinate. 159.  *	if x or y is between -1 and -10, we read one from the corresponding 160.  *	register (x0, x1, ... x9). 161.  *	if x or y is nonnegative, we convert it from relative to the local map 162.  *	to global coordinates. 163.  *	The "humidity" flag is used to insure that engravings aren't  164. *	created underwater, or eels on dry land. 165.  */  166.  #define DRY	0x1 167. #define WET	0x2 168. #define MOLTEN	0x4 169.  170.  STATIC_DCL boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int)); 171.  172.  STATIC_OVL boolean 173. get_location(x, y, humidity) 174. schar *x, *y; 175. int humidity; 176. {  177.  	int cpt = 0; 178.  179.  	if (*x >= 0) {			/* normal locations */ 180. 		*x += xstart; 181. 		*y += ystart; 182. 	} else if (*x > -11) {		/* special locations */ 183. 	    char ry = rloc_y[ - *x - 1][ - *y - 1]; 184. 	    char rx = rloc_x[ - *x - 1][ - *y - 1]; 185. 	    if (ry == (char)-1 || rx == (char)-1) 186. 		return FALSE;		/* nowhere */ 187. 	    else { 188. 		*y = ystart + ry; 189. 		*x = xstart + rx; 190. 	    }  191.  	} else if (*x > -12) {		/* within random region */ 192. 	    schar t = - *y - 1; 193.  194.  	    do { 195. 		*x = rn2(rarea[t].inarea.x2 - rarea[t].inarea.x1 + 1) + 196. 		     rarea[t].inarea.x1; 197. 		*y = rn2(rarea[t].inarea.y2 - rarea[t].inarea.y1 + 1) + 198. 		     rarea[t].inarea.y1; 199. 		if (!rarea[t].in_islev) { 200. 		    *x += xstart; 201. 		    *y += ystart; 202. 		}  203.  		if (is_ok_location(*x,*y,humidity)) { 204. 		    int x1 = rarea[t].delarea.x1; 205. 		    int x2 = rarea[t].delarea.x2; 206. 		    int y1 = rarea[t].delarea.y1; 207. 		    int y2 = rarea[t].delarea.y2; 208. 		    if (!rarea[t].del_islev) { 209. 			x1 += xstart; 210. 			x2 += xstart; 211. 			y1 += ystart; 212. 			y2 += ystart; 213. 		    }  214.  		    if (!within_bounded_area(*x,*y,x1,y1,x2,y2)) break; 215. 		}  216.  	    } while (++cpt < 100); 217. 	    if (cpt >= 100) { 218. 		register int xx, yy; 219. 		for (xx = rarea[t].inarea.x1; xx < rarea[t].inarea.x2; xx++) 220. 		    for (yy = rarea[t].inarea.y1; yy < rarea[t].inarea.y2; yy++) { 221. 			*x = xx; 222. 			*y = yy; 223. 			if (!rarea[t].in_islev) { 224. 			    *x += xstart; 225. 			    *y += ystart; 226. 			}  227.  			if (is_ok_location(*x,*y,humidity)) { 228. 			    int x1 = rarea[t].delarea.x1; 229. 			    int x2 = rarea[t].delarea.x2; 230. 			    int y1 = rarea[t].delarea.y1; 231. 			    int y2 = rarea[t].delarea.y2; 232. 			    if (!rarea[t].del_islev) { 233. 				x1 += xstart; 234. 				x2 += xstart; 235. 				y1 += ystart; 236. 				y2 += ystart; 237. 			    }  238.  			    if (!within_bounded_area(*x,*y,x1,y1,x2,y2)) 239. 				goto found_it; 240. 			}  241.  		    }  242.  		panic("get_location:  can't find a place!"); 243. 	    }  244.  	} else {			/* random location */ 245. 	    do { 246. 		*x = xstart + rn2((int)xsize); 247. 		*y = ystart + rn2((int)ysize); 248. 		if (is_ok_location(*x,*y,humidity)) break; 249. 	    } while (++cpt < 100); 250. 	    if (cpt >= 100) { 251. 		register int xx, yy; 252. 		/* last try */ 253. 		for (xx = 0; xx < xsize; xx++) 254. 		    for (yy = 0; yy < ysize; yy++) { 255. 			*x = xstart + xx; 256. 			*y = ystart + yy; 257. 			if (is_ok_location(*x,*y,humidity)) goto found_it; 258. 		    }  259.  		panic("get_location:  can't find a place!"); 260. 	    }  261.  	}  262.  found_it:; 263.  264.  	if (!isok(*x,*y)) { 265. 	    impossible("get_location:  (%d,%d) out of bounds", *x, *y); 266. 	    *x = x_maze_max; *y = y_maze_max; 267. 	}  268.  	return TRUE; 269. }  270.   271.  STATIC_OVL boolean 272. is_ok_location(x, y, humidity) 273. register schar x, y;  274. register int humidity; 275. {  276.  	register int typ; 277.  278.  	if (Is_waterlevel(&u.uz)) return TRUE;	/* accept any spot */ 279.  280.  	if (humidity & DRY) { 281. 	    typ = levl[x][y].typ; 282. 	    if (typ == ROOM || typ == AIR ||  283.  		    typ == CLOUD || typ == ICE || typ == CORR) 284. 		return TRUE; 285. 	}  286.  	if (humidity & WET) { 287. 	    if (is_pool(x,y)) 288. 		return TRUE; 289. 	}  290.  	if (humidity & MOLTEN) { 291. 	    if (is_lava(x,y)) 292. 		return TRUE; 293. 	}  294.  	return FALSE; 295. }  296.   297.  /*  298.   * Shuffle the registers for locations, objects or monsters 299.  */  300.   301.  STATIC_OVL void 302. sp_lev_shuffle(list1, list2, n)  303. char list1[], list2[]; 304. int n;  305. { 306.  	register int i, j;  307. register char k; 308. 309. 	for (i = n - 1; i > 0; i--) { 310. 		if ((j = rn2(i + 1)) == i) continue; 311. 		k = list1[j]; 312. 		list1[j] = list1[i]; 313. 		list1[i] = k;  314. if (list2) { 315. 			k = list2[j]; 316. 			list2[j] = list2[i]; 317. 			list2[i] = k;  318. } 319.  	}  320.  }  321.   322.  /*  323.   * Get a relative position inside a room. 324.  * negative values for x or y means RANDOM! 325.  */  326.   327.  STATIC_OVL void 328. get_room_loc(x,y, croom) 329. schar		*x, *y; 330. struct mkroom	*croom; 331. {  332.  	coord c;  333. 334. 	if (*x <0 && *y <0) { 335. 		if (somexy(croom, &c)) { 336. 			*x = c.x;  337. *y = c.y; 338. } else 339. 		    panic("get_room_loc : can't find a place!"); 340. 	} else { 341. 		if (*x < 0) 342. 		    *x = rn2(croom->hx - croom->lx + 1); 343. 		if (*y < 0) 344. 		    *y = rn2(croom->hy - croom->ly + 1); 345. 		*x += croom->lx; 346. 		*y += croom->ly; 347. 	}  348.  }  349.   350.  /*  351.   * Get a relative position inside a room. 352.  * negative values for x or y means RANDOM! 353.  */  354.   355.  STATIC_OVL void 356. get_free_room_loc(x,y, croom) 357. schar		*x, *y; 358. struct mkroom	*croom; 359. {  360.  	schar try_x, try_y; 361. 	register int trycnt = 0; 362.  363.  	do { 364. 	    try_x = *x,  try_y = *y; 365. 	    get_room_loc(&try_x, &try_y, croom); 366. 	} while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100); 367.  368.  	if (trycnt > 100) 369. 	    panic("get_free_room_loc:  can't find a place!"); 370. 	*x = try_x,  *y = try_y; 371. }  372.   373.  boolean 374. check_room(lowx, ddx, lowy, ddy, vault) 375. xchar *lowx, *ddx, *lowy, *ddy; 376. boolean vault; 377. {  378.  	register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy; 379. 	register struct rm *lev; 380. 	int xlim, ylim, ymax; 381.  382.  	xlim = XLIM + (vault ? 1 : 0); 383. 	ylim = YLIM + (vault ? 1 : 0); 384.  385.  	if (*lowx < 3)		*lowx = 3; 386. 	if (*lowy < 2)		*lowy = 2; 387. 	if (hix > COLNO-3)	hix = COLNO-3; 388. 	if (hiy > ROWNO-3)	hiy = ROWNO-3; 389. chk: 390. 	if (hix <= *lowx || hiy <= *lowy)	return FALSE; 391.  392.  	/* check area around room (and make room smaller if necessary) */ 393. 	for (x = *lowx - xlim; x<= hix + xlim; x++) { 394. 		if(x <= 0 || x >= COLNO) continue; 395. 		y = *lowy - ylim;	ymax = hiy + ylim; 396. 		if(y < 0) y = 0; 397. 		if(ymax >= ROWNO) ymax = (ROWNO-1); 398. 		lev = &levl[x][y]; 399. 		for (y <= ymax; y++) { 400. 			if (lev++->typ) { 401. #ifdef DEBUG 402. 				if(!vault) 403. 				    debugpline("strange area [%d,%d] in check_room.",x,y); 404. #endif 405. 				if (!rn2(3))	return FALSE; 406. 				if (x < *lowx) 407. 				    *lowx = x + xlim + 1; 408. 				else 409. 				    hix = x - xlim - 1; 410. 				if (y < *lowy) 411. 				    *lowy = y + ylim + 1; 412. 				else 413. 				    hiy = y - ylim - 1; 414. 				goto chk; 415. 			}  416.  		}  417.  	}  418.  	*ddx = hix - *lowx; 419. 	*ddy = hiy - *lowy; 420. 	return TRUE; 421. }  422.   423.  /*  424.   * Create a new room. 425.  * This is still very incomplete...  426. */ 427.   428.  boolean 429. create_room(x,y,w,h,xal,yal,rtype,rlit) 430. xchar	x,y; 431. xchar	w,h; 432. xchar	xal,yal; 433. xchar	rtype, rlit; 434. {  435.  	xchar	xabs, yabs; 436. 	int	wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp; 437. 	NhRect	*r1 = 0, r2; 438. 	int	trycnt = 0; 439. 	boolean	vault = FALSE; 440. 	int	xlim = XLIM, ylim = YLIM; 441.  442.  	if (rtype == -1)	/* Is the type random ? */ 443.  	    rtype = OROOM; 444.  445.  	if (rtype == VAULT) { 446. 		vault = TRUE; 447. 		xlim++; 448. 		ylim++; 449. 	}  450.   451.  	/* on low levels the room is lit (usually) */ 452. 	/* some other rooms may require lighting */ 453.  454.  	/* is light state random ? */ 455.  	if (rlit == -1) 456. 	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE; 457.  458.  	/*  459.  	 * Here we will try to create a room. If some parameters are 460. 	 * random we are willing to make several try before we give 461. 	 * it up. 462. 	 */  463.  	do { 464. 		xchar xborder, yborder; 465. 		wtmp = w; htmp = h;  466. xtmp = x; ytmp = y; 467. xaltmp = xal; yaltmp = yal; 468.  469.  		/* First case : a totaly random room */ 470.  471.  		if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 && 472. 		   yaltmp < 0) || vault) { 473. 			xchar hx, hy, lx, ly, dx, dy; 474. 			r1 = rnd_rect; /* Get a random rectangle */ 475.  476.  			if (!r1) { /* No more free rectangles ! */ 477.  #ifdef DEBUG 478. 				debugpline("No more rects..."); 479. #endif 480. 				return FALSE; 481. 			}  482.  			hx = r1->hx; 483. 			hy = r1->hy; 484. 			lx = r1->lx; 485. 			ly = r1->ly; 486. 			if (vault) 487. 			    dx = dy = 1; 488. 			else { 489. 				dx = 2 + rn2((hx-lx > 28) ? 12 : 8); 490. 				dy = 2 + rn2(4); 491. 				if(dx*dy > 50) 492. 				    dy = 50/dx; 493. 			}  494.  			xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1; 495. 			yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1; 496. 			if(hx-lx < dx + 3 + xborder ||  497.  			   hy-ly < dy + 3 + yborder) { 498. 				r1 = 0; 499. 				continue; 500. 			}  501.  			xabs = lx + (lx > 0 ? xlim : 3) 502. 			    + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1); 503. 			yabs = ly + (ly > 0 ? ylim : 2) 504. 			    + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1); 505. 			if (ly == 0 && hy >= (ROWNO-1) &&  506.  			    (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) { 507. 			    yabs = rn1(3, 2); 508. 			    if(nroom < 4 && dy>1) dy--; 509. 		        }  510.  			if (!check_room(&xabs, &dx, &yabs, &dy, vault)) { 511. 				r1 = 0; 512. 				continue; 513. 			}  514.  			wtmp = dx+1; 515. 			htmp = dy+1; 516. 			r2.lx = xabs-1; r2.ly = yabs-1; 517. 			r2.hx = xabs + wtmp; 518. 			r2.hy = yabs + htmp; 519. 		} else {	/* Only some parameters are random */ 520. 			int rndpos = 0; 521. 			if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */ 522. 				xtmp = rnd(5); 523. 				ytmp = rnd(5); 524. 				rndpos = 1; 525. 			}  526.  			if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */ 527. 				wtmp = rn1(15, 3); 528. 				htmp = rn1(8, 2); 529. 			}  530.  			if (xaltmp == -1) /* Horizontal alignment is RANDOM */ 531. 			    xaltmp = rnd(3); 532. 			if (yaltmp == -1) /* Vertical alignment is RANDOM */ 533. 			    yaltmp = rnd(3); 534.  535.  			/* Try to generate real (absolute) coordinates here! */ 536.   537.  			xabs = (((xtmp-1) * COLNO) / 5) + 1; 538. 			yabs = (((ytmp-1) * ROWNO) / 5) + 1; 539. 			switch (xaltmp) { 540. 			      case LEFT: 541. 				break; 542. 			      case RIGHT: 543. 				xabs += (COLNO / 5) - wtmp; 544. 				break; 545. 			      case CENTER: 546. 				xabs += ((COLNO / 5) - wtmp) / 2; 547. 				break; 548. 			}  549.  			switch (yaltmp) { 550. 			      case TOP: 551. 				break; 552. 			      case BOTTOM: 553. 				yabs += (ROWNO / 5) - htmp; 554. 				break; 555. 			      case CENTER: 556. 				yabs += ((ROWNO / 5) - htmp) / 2; 557. 				break; 558. 			}  559.   560.  			if (xabs + wtmp - 1 > COLNO - 2) 561. 			    xabs = COLNO - wtmp - 3; 562. 			if (xabs < 2) 563. 			    xabs = 2; 564. 			if (yabs + htmp - 1> ROWNO - 2) 565. 			    yabs = ROWNO - htmp - 3; 566. 			if (yabs < 2) 567. 			    yabs = 2; 568.  569.  			/* Try to find a rectangle that fit our room ! */ 570.   571.  			r2.lx = xabs-1; r2.ly = yabs-1; 572. 			r2.hx = xabs + wtmp + rndpos; 573. 			r2.hy = yabs + htmp + rndpos; 574. 			r1 = get_rect(&r2); 575. 		}  576.  	} while (++trycnt <= 100 && !r1); 577. 	if (!r1) {	/* creation of room failed ? */ 578.  		return FALSE; 579. 	}  580.  	split_rects(r1, &r2); 581.  582.  	if (!vault) { 583. 		smeq[nroom] = nroom; 584. 		add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1,  585.  			 rlit, rtype, FALSE); 586. 	} else { 587. 		rooms[nroom].lx = xabs; 588. 		rooms[nroom].ly = yabs; 589. 	}  590.  	return TRUE; 591. }  592.   593.  /*  594.   * Create a subroom in room proom at pos x,y with width w & height h.  595. * x & y are relative to the parent room. 596.  */  597.   598.  STATIC_OVL boolean 599. create_subroom(proom, x, y, w,  h, rtype, rlit) 600. struct mkroom *proom; 601. xchar x,y; 602. xchar w,h; 603. xchar rtype, rlit; 604. {  605.  	xchar width, height; 606.  607.  	width = proom->hx - proom->lx + 1; 608. 	height = proom->hy - proom->ly + 1; 609.  610.  	/* There is a minimum size for the parent room */ 611. 	if (width < 4 || height < 4) 612. 	    return FALSE; 613.  614.  	/* Check for random position, size, etc... */ 615.   616.  	if (w == -1) 617. 	    w = rnd(width - 3); 618. 	if (h == -1) 619. 	    h = rnd(height - 3); 620. 	if (x == -1) 621. 	    x = rnd(width - w - 1) - 1; 622. 	if (y == -1) 623. 	    y = rnd(height - h - 1) - 1; 624. 	if (x == 1) 625. 	    x = 0; 626. 	if (y == 1) 627. 	    y = 0; 628. 	if ((x + w + 1) == width) 629. 	    x++; 630. 	if ((y + h + 1) == height) 631. 	    y++; 632. 	if (rtype == -1) 633. 	    rtype = OROOM; 634. 	if (rlit == -1) 635. 	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE; 636. 	add_subroom(proom, proom->lx + x, proom->ly + y,  637.  		    proom->lx + x + w - 1, proom->ly + y + h - 1,  638.  		    rlit, rtype, FALSE); 639. 	return TRUE; 640. }  641.   642.  /*  643.   * Create a new door in a room. 644.  * It's placed on a wall (north, south, east or west). 645.  */  646.   647.  STATIC_OVL void 648. create_door(dd, broom) 649. room_door *dd; 650. struct mkroom *broom; 651. {  652.  	int	x, y;  653. int	trycnt = 0; 654. 	int	i; 655.  656.  	if (dd->secret == -1) 657. 	    dd->secret = rn2(2); 658.  659.  	if (dd->mask == -1) { 660. 		/* is it a locked door, closed, or a doorway? */ 661.  		if (!dd->secret) { 662. 			if(!rn2(3)) { 663. 				if(!rn2(5)) 664. 				    dd->mask = D_ISOPEN; 665. 				else if(!rn2(6)) 666. 				    dd->mask = D_LOCKED; 667. 				else 668. 				    dd->mask = D_CLOSED; 669. 				if (dd->mask != D_ISOPEN && !rn2(25)) 670. 				    dd->mask |= D_TRAPPED; 671. 			} else 672. 			    dd->mask = D_NODOOR; 673. 		} else { 674. 			if(!rn2(5))	dd->mask = D_LOCKED; 675. 			else		dd->mask = D_CLOSED; 676.  677.  			if(!rn2(20)) dd->mask |= D_TRAPPED; 678. 		}  679.  	}  680.   681.  	do { 682. 		register int dwall, dpos; 683.  684.  		dwall = dd->wall; 685. 		if (dwall == -1)	/* The wall is RANDOM */ 686. 		    dwall = 1 << rn2(4); 687.  688.  		dpos = dd->pos; 689. 		if (dpos == -1)	/* The position is RANDOM */ 690. 		    dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?  691.  			    (broom->hy - broom->ly) : (broom->hx - broom->lx)); 692.  693.  		/* Convert wall and pos into an absolute coordinate! */ 694.   695.  		switch (dwall) { 696. 		      case W_NORTH: 697. 			y = broom->ly - 1; 698. 			x = broom->lx + dpos; 699. 			break; 700. 		      case W_SOUTH: 701. 			y = broom->hy + 1; 702. 			x = broom->lx + dpos; 703. 			break; 704. 		      case W_WEST: 705. 			x = broom->lx - 1; 706. 			y = broom->ly + dpos; 707. 			break; 708. 		      case W_EAST: 709. 			x = broom->hx + 1; 710. 			y = broom->ly + dpos; 711. 			break; 712. 		      default: 713. 			x = y = 0; 714. 			panic("create_door: No wall for door!"); 715. 			break; 716. 		}  717.  		if (okdoor(x,y)) 718. 		    break; 719. 	} while (++trycnt <= 100); 720. 	if (trycnt > 100) { 721. 		impossible("create_door: Can't find a proper place!"); 722. 		return; 723. 	}  724.  	i = add_door(x,y,broom); 725. 	doors[i].arti_key = dd->arti_key; 726. 	levl[x][y].typ = (dd->secret ? SDOOR : DOOR); 727. 	levl[x][y].doormask = dd->mask; 728. }  729.   730.  /*  731.   * Create a secret door in croom on any one of the specified walls. 732.  */  733.  void 734. create_secret_door(croom, walls) 735.     struct mkroom *croom; 736.     xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */ 737. {  738.      xchar sx, sy; /* location of the secret door */ 739.     int count; 740.  741.      for(count = 0; count < 100; count++) { 742. 	sx = rn1(croom->hx - croom->lx + 1, croom->lx); 743. 	sy = rn1(croom->hy - croom->ly + 1, croom->ly); 744.  745.  	switch(rn2(4)) { 746. 	case 0:  /* top */ 747. 	    if(!(walls & W_NORTH)) continue; 748. 	    sy = croom->ly-1; break; 749. 	case 1: /* bottom */ 750. 	    if(!(walls & W_SOUTH)) continue; 751. 	    sy = croom->hy+1; break; 752. 	case 2: /* left */ 753. 	    if(!(walls & W_EAST)) continue; 754. 	    sx = croom->lx-1; break; 755. 	case 3: /* right */ 756. 	    if(!(walls & W_WEST)) continue; 757. 	    sx = croom->hx+1; break; 758. 	}  759.   760.  	if(okdoor(sx,sy)) { 761. 	    levl[sx][sy].typ = SDOOR; 762. 	    levl[sx][sy].doormask = D_CLOSED; 763. 	    add_door(sx,sy,croom); 764. 	    return; 765. 	}  766.      }  767.   768.      impossible("couldn't create secret door on any walls 0x%x", walls); 769. }  770.   771.  /*  772.   * Create a trap in a room. 773.  */  774.   775.  STATIC_OVL void 776. create_trap(t,croom) 777. trap	*t; 778. struct mkroom	*croom; 779. {  780.      schar	x,y; 781.     coord	tm; 782.  783.      if (rn2(100) < t->chance) { 784. 	x = t->x; 785. 	y = t->y; 786. 	if (croom) 787. 	    get_free_room_loc(&x, &y, croom); 788. 	else 789. 	    if (!get_location(&x, &y, DRY)) 790. 		return; 791.  792.  	tm.x = x;  793. tm.y = y; 794. 795. 	mktrap(t->type, 1, (struct mkroom*) 0, &tm); 796.     }  797.  }  798.   799.  /*  800.   * Create a monster in a room. 801.  */  802.   803.  STATIC_OVL int 804. noncoalignment(alignment) 805. aligntyp alignment; 806. {  807.  	int k;  808. 809. 	k = rn2(2); 810. 	if (!alignment) 811. 		return(k ? -1 : 1); 812. 	return(k ? -alignment : 0); 813. }  814.   815.  STATIC_OVL void 816. create_monster(m,croom) 817. monster	*m; 818. struct mkroom	*croom; 819. {  820.      struct monst *mtmp; 821.     schar x, y;  822. char class; 823.     aligntyp amask; 824.     coord cc; 825.     struct permonst *pm; 826.     unsigned g_mvflags; 827.  828.      if (rn2(100) < m->chance) { 829.  830.  	if (m->class >= 0) 831. 	    class = (char) def_char_to_monclass((char)m->class); 832. 	else if (m->class > -11) 833. 	    class = (char) def_char_to_monclass(rmonst[- m->class - 1]); 834. 	else 835. 	    class = 0; 836.  837.  	if (class == MAXMCLASSES) 838. 	    panic("create_monster: unknown monster class '%c'", m->class); 839.  840.  	amask = (m->align == AM_SPLEV_CO) ? 841. 			Align2amask(u.ualignbase[A_ORIGINAL]) : 842. 		(m->align == AM_SPLEV_NONCO) ? 843. 			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) : 844. 		(m->align <= -11) ? induced_align(80) : 845. 		(m->align < 0 ? ralign[-m->align-1] : m->align); 846.  847.  	if (!class) 848. 	    pm = (struct permonst *) 0; 849. 	else if (m->id != NON_PM) { 850. #if 0	/* OBSOLETE */ 851. 	    if (flags.female && Role_if(PM_ELF) /*&& !u.uelf_drow*/ && m->id == PM_EARENDIL) 852. 		m->id = PM_ELWING; 853. #endif 854. 	    /* in the Gnome Mines, make the gnomes & dwarves into 855. 	       orcs, ogres, & zombies (because gnomes & dwarves are friendly...  856.  	       the mines would be hella easy otherwise) */ 857. 		if (In_mines(&u.uz) && ( 858. #ifdef DWARF 859. 			Race_if(PM_DWARF) || 860. #endif 861. 			Race_if(PM_GNOME))) { 862. 		switch (m->id) { 863. 		  case PM_GNOME: m->id = PM_GNOME_ZOMBIE; break; 864. 		  case PM_GNOMISH_WIZARD: m->id = PM_ORC_SHAMAN; break; 865. 		  case PM_GNOME_LORD: m->id = PM_GNOME_MUMMY; break; 866. 		  case PM_GNOME_KING: m->id = PM_OGRE; break; 867. #ifdef DWARF 868. 		  case PM_DWARF: m->id = PM_DWARF_ZOMBIE; break; 869. 		  case PM_DWARF_LORD: m->id = PM_DWARF_MUMMY; break; 870. 		  case PM_DWARF_KING: m->id = PM_WAR_ORC; break; 871. #endif 872. 		}  873.  	    }  874.  	    pm = &mons[m->id]; 875. 	    g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags; 876. 	    if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT)) 877. 		goto m_done; 878. 	    else if (g_mvflags & G_GONE)	/* genocided or extinct */ 879. 		pm = (struct permonst *) 0;	/* make random monster */ 880. 	} else { 881. 	    pm = mkclass(class,G_NOGEN|MKC_ULIMIT); 882. 	    /* if we can't get a specific monster type (pm == 0) then all 883. 	       the monsters of acceptable difficulty in the given class 884. 	       have been genocided, so settle for a random monster */ 885. 	}  886.  	x = m->x; 887. 	y = m->y; 888. 	if (croom) 889. 	    get_room_loc(&x, &y, croom); 890. 	else { 891. 	    boolean found; 892. 	    if (!pm || !is_swimmer(pm) && !likes_lava(pm)) 893. 		found = get_location(&x, &y, DRY); 894. 	    else if (pm->mlet == S_EEL) 895. 		found = get_location(&x, &y, WET); 896. 	    else if (likes_lava(pm)) 897. 		found = get_location(&x, &y, DRY|MOLTEN); 898. 	    else 899. 		found = get_location(&x, &y, DRY|WET); 900. 	    if (!found) 901. 		goto m_done;	/* nowhere */ 902. 	}  903.  	/* try to find a close place if someone else is already there */ 904. 	if (MON_AT(x,y) && enexto(&cc, x, y, pm)) 905. 	    x = cc.x,  y = cc.y;  906. 907. 	if(m->align != -12) 908. 	    mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful); 909. 	else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD) 910. 	         mtmp = mk_mplayer(pm, x, y, FALSE); 911. 	else mtmp = makemon(pm, x, y, NO_MM_FLAGS); 912.  913.  	if (mtmp) { 914. 	    /* handle specific attributes for some special monsters */ 915. 	    if (m->name.str) mtmp = christen_monst(mtmp, m->name.str); 916.  917.  	    /*  918.  	     * This is currently hardwired for mimics only. It should 919. 	     * eventually be expanded. 920. 	     */  921.  	    if (m->appear_as.str && mtmp->data->mlet == S_MIMIC) { 922. 		int i;  923. 924. 		switch (m->appear) { 925. 		    case M_AP_NOTHING: 926. 			impossible(  927.  		"create_monster: mon has an appearance, \"%s\", but no type",  928.  				m->appear_as.str); 929. 			break; 930.  931.  		    case M_AP_FURNITURE: 932. 			for (i = 0; i < MAXPCHARS; i++) 933. 			    if (!strcmp(defsyms[i].explanation, 934. 					m->appear_as.str)) 935. 				break; 936. 			if (i == MAXPCHARS) { 937. 			    impossible(  938.  				"create_monster: can't find feature \"%s\"",  939.  				m->appear_as.str); 940. 			} else { 941. 			    mtmp->m_ap_type = M_AP_FURNITURE; 942. 			    mtmp->mappearance = i;  943. } 944.  			break; 945.  946.  		    case M_AP_OBJECT: 947. 			for (i = 0; i < NUM_OBJECTS; i++) 948. 			    if (OBJ_NAME(objects[i]) &&  949.  				!strcmp(OBJ_NAME(objects[i]),m->appear_as.str)) 950. 				break; 951. 			if (i == NUM_OBJECTS) { 952. 			    impossible(  953.  				"create_monster: can't find object \"%s\"",  954.  				m->appear_as.str); 955. 			} else { 956. 			    mtmp->m_ap_type = M_AP_OBJECT; 957. 			    mtmp->mappearance = i;  958. } 959.  			break; 960.  961.  		    case M_AP_MONSTER: 962. 			/* note: mimics don't appear as monsters! */ 963.  			/*	 (but chameleons can :-)	  */ 964. 		    default: 965. 			impossible(  966.  		"create_monster: unimplemented mon appear type [%d,\"%s\"]",  967.  				m->appear, m->appear_as.str); 968. 			break; 969. 		}  970.  		if (does_block(x, y, &levl[x][y])) 971. 		    block_point(x, y); 972. 	    }  973.   974.  	    if (m->peaceful >= 0) { 975. 		mtmp->mpeaceful = m->peaceful; 976. 		/* changed mpeaceful again; have to reset malign */ 977. 		set_malign(mtmp); 978. 	    }  979.  	    if (m->asleep >= 0) { 980. #ifdef UNIXPC 981. 		/* optimizer bug strikes again */ 982. 		if (m->asleep) 983. 			mtmp->msleeping = 1; 984. 		else 985. 			mtmp->msleeping = 0; 986. #else 987. 		mtmp->msleeping = m->asleep; 988. #endif 989. 	    }  990.  	}  991.   992.      }		/* if (rn2(100) < m->chance) */ 993.  m_done: 994.     Free(m->name.str); 995.     Free(m->appear_as.str); 996. }  997.   998.  /*  999.   * Create an object in a room. 1000. */  1001.  1002. STATIC_OVL void 1003. create_object(o,croom) 1004. object	*o; 1005. struct mkroom	*croom; 1006. { 1007.     struct obj *otmp; 1008.    schar x, y;  1009. char c; 1010. boolean named;	/* has a name been supplied in level description? */ 1011.  1012.     if (rn2(100) < o->chance) { 1013. 	named = o->name.str ? TRUE : FALSE; 1014. 1015. 	x = o->x; y = o->y; 1016. 	if (croom) 1017. 	   get_room_loc(&x, &y, croom); 1018. 	else 1019. 	   if (!get_location(&x, &y, DRY))	/* nowhere */ 1020. 		goto o_done; 1021. 1022. 	if (o->class >= 0) 1023. 	   c = o->class; 1024. 	else if (o->class > -11) 1025. 	   c = robjects[ -(o->class+1)]; 1026. 	else 1027. 	   c = 0; 1028. 1029. 	if (!c) 1030. 	   otmp = mkobj_at(RANDOM_CLASS, x, y, !named); 1031. 	else if (o->id != -1) 1032. 	   otmp = mksobj_at(o->id, x, y, TRUE, !named); 1033. 	else { 1034. 	   /*  1035. 	     * The special levels are compiled with the default "text" object 1036. 	    * class characters. We must convert them to the internal format. 1037. 	    */  1038. 	    char oclass = (char) def_char_to_objclass(c); 1039. 1040. 	    if (oclass == MAXOCLASSES) 1041. 		panic("create_object: unexpected object class '%c'",c); 1042. 1043. 	    /* KMH -- Create piles of gold properly */ 1044. 	   /* Bruce Cox/WAC - some clean ups */ 1045. 	   if (oclass == COIN_CLASS && !o->containment) { 1046. 		mkgold(0L, x, y); 1047. 		otmp = g_at(x,y); 1048. 	   } else 1049. 		otmp = mkobj_at(oclass, x, y, !named); 1050. 	} 1051.  1052. 	if (o->spe != -127)	/* That means NOT RANDOM! */ 1053. 	    otmp->spe = (schar)o->spe; 1054. 1055. 	switch (o->curse_state) { 1056. 	     case 1:	bless(otmp); break; /* BLESSED */ 1057. 	     case 2:	unbless(otmp); uncurse(otmp); break; /* uncursed */ 1058. 	     case 3:	curse(otmp); break; /* CURSED */ 1059. 	     default:	break;	/* Otherwise it's random and we're happy 1060. 				 * with what mkobj gave us! */ 1061. 	}  1062.  1063. 	/*	corpsenm is "empty" if -1, random if -2, otherwise specific */ 1064. 	if (o->corpsenm != NON_PM) { 1065. 	   if (o->corpsenm == NON_PM - 1) otmp->corpsenm = rndmonnum; 1066. 	   else otmp->corpsenm = o->corpsenm; 1067. 	   otmp->owt = weight(otmp); 1068. 	} 1069.  1070. 	if (otmp->otyp == EGG && In_spiders(&u.uz)) { 1071. 	   otmp->corpsenm = PM_GIANT_SPIDER; 1072. 	   otmp->age = monstermoves; 1073. 	} 1074. 	/* assume we wouldn't be given an egg corpsenm unless it was 1075. 	  hatchable */ 1076. 	if (otmp->otyp == EGG && otmp->corpsenm != NON_PM) { 1077. 	   if (dead_species(otmp->otyp, TRUE)) 1078. 		kill_egg(otmp);	/* make sure nothing hatches */ 1079. 	   else 1080. 		attach_egg_hatch_timeout(otmp);	/* attach new hatch timeout */ 1081. 	} 1082.  1083. 	if (named) 1084. 	   otmp = oname(otmp, o->name.str); 1085. 1086. 	switch(o->containment) { 1087. 	   static struct obj *container = 0; 1088. 1089. 	    /* contents */ 1090. 	   case 1: 1091. 		if (!container) { 1092. 		   impossible("create_object: no container"); 1093. 		   break; 1094. 		} 1095. 		remove_object(otmp); 1096. 		(void) add_to_container(container, otmp); 1097. 		goto o_done;		/* don't stack, but do other cleanup */ 1098. 	   /* container */ 1099. 	   case 2: 1100. 		delete_contents(otmp); 1101. 		container = otmp; 1102. 		break; 1103. 	   /* nothing */ 1104. 	   case 0: break; 1105. 1106. 	    default: impossible("containment type %d?", (int) o->containment); 1107. 	} 1108.  1109. 	/* Medusa level special case: statues are petrified monsters, so they 1110. 	 * are not stone-resistant and have monster inventory. They also lack 1111. 	 * other contents, but that can be specified as an empty container. 1112. 	 */ 1113. 	if (o->id == STATUE && Is_medusa_level(&u.uz) &&  1114. 		    o->corpsenm == NON_PM) { 1115. 	   struct monst *was; 1116. 	   struct obj *obj; 1117. 	   int wastyp; 1118. 1119. 	    /* Named random statues are of player types, and aren't stone- 1120. 	    * resistant (if they were, we'd have to reset the name as well as  1121. 	     * setting corpsenm). 1122. 	    */  1123. 	    for (wastyp = otmp->corpsenm; ; wastyp = rndmonnum) { 1124. 		/* makemon without rndmonst might create a group */ 1125. 		was = makemon(&mons[wastyp], 0, 0, NO_MM_FLAGS); 1126. 		if (!resists_ston(was)) break; 1127. 		mongone(was); 1128. 	   }  1129. 	    otmp->corpsenm = wastyp; 1130. 	   while(was->minvent) { 1131. 		obj = was->minvent; 1132. 		obj->owornmask = 0; 1133. 		obj_extract_self(obj); 1134. 		(void) add_to_container(otmp, obj); 1135. 	   }  1136. 	    otmp->owt = weight(otmp); 1137. 	   mongone(was); 1138. 	} 1139.  1140. 	stackobj(otmp); 1141. 1142. 	if (o->oflags & OBJF_LIT) 1143. 	   begin_burn(otmp, FALSE); 1144. 	if (o->oflags & OBJF_BURIED) 1145. 	   otmp = bury_an_obj(otmp); 1146. 1147.     }		/* if (rn2(100) < o->chance) */ 1148. o_done: 1149.    Free(o->name.str); 1150. } 1151.  1152. /*  1153.  * Randomly place a specific engraving, then release its memory. 1154. */  1155. STATIC_OVL void 1156. create_engraving(e, croom) 1157. engraving *e; 1158. struct mkroom *croom; 1159. { 1160. 	xchar x, y;  1161. boolean found = TRUE; 1162. 1163. 	x = e->x,  y = e->y; 1164. 	if (croom) 1165. 	   get_room_loc(&x, &y, croom); 1166. 	else 1167. 	   found = get_location(&x, &y, DRY); 1168. 1169. 	if (found) 1170. 	make_engr_at(x, y, e->engr.str, 0L, e->etype); 1171. 	free((genericptr_t) e->engr.str); 1172. } 1173.  1174. /*  1175.  * Create stairs in a room. 1176. *  1177.  */  1178.  1179. STATIC_OVL void 1180. create_stairs(s,croom) 1181. stair	*s; 1182. struct mkroom	*croom; 1183. { 1184. 	schar		x,y; 1185. 1186. 	x = s->x; y = s->y; 1187. 	get_free_room_loc(&x, &y, croom); 1188. 	mkstairs(x,y,(char)s->up, croom); 1189. } 1190.  1191. /*  1192.  * Create an altar in a room. 1193. */  1194.  1195. STATIC_OVL void 1196. create_altar(a, croom) 1197. 	altar		*a; 1198. 	struct mkroom	*croom; 1199. { 1200. 	schar		sproom,x,y; 1201. 	aligntyp	amask; 1202. 	boolean		croom_is_temple = TRUE; 1203. 	int oldtyp; 1204. 1205. 	x = a->x; y = a->y; 1206. 1207. 	if (croom) { 1208. 	   get_free_room_loc(&x, &y, croom); 1209. 	   if (croom->rtype != TEMPLE) 1210. 		croom_is_temple = FALSE; 1211. 	} else { 1212. 	   if (!get_location(&x, &y, DRY)) 1213. 		return;		/* nowhere */ 1214. 	   if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0) 1215. 		croom = &rooms[sproom - ROOMOFFSET]; 1216. 	   else 1217. 		croom_is_temple = FALSE; 1218. 	} 1219.  1220. 	/* check for existing features */ 1221. 	oldtyp = levl[x][y].typ; 1222. 	if (oldtyp == STAIRS || oldtyp == LADDER) 1223. 	   return; 1224. 1225. 	a->x = x;  1226. a->y = y; 1227. 1228. 	/* Is the alignment random ? 1229. 	 * If so, it's an 80% chance that the altar will be co-aligned. 1230. 	 * 1231. 	 * The alignment is encoded as amask values instead of alignment 1232. 	 * values to avoid conflicting with the rest of the encoding, 1233. 	 * shared by many other parts of the special level code. 1234. 	 */ 1235.  1236. 	amask = (a->align == AM_SPLEV_CO) ? 1237. 			Align2amask(u.ualignbase[A_ORIGINAL]) : 1238. 		(a->align == AM_SPLEV_NONCO) ? 1239. 			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) : 1240. 		(a->align == -11) ? induced_align(80) : 1241. 		(a->align < 0 ? ralign[-a->align-1] : a->align); 1242. 1243. 	levl[x][y].typ = ALTAR; 1244. 	levl[x][y].altarmask = amask; 1245. 1246. 	if (a->shrine < 0) a->shrine = rn2(2);	/* handle random case */ 1247. 1248. 	if (oldtyp == FOUNTAIN) 1249. 	   level.flags.nfountains--; 1250. 	else if (oldtyp == SINK) 1251. 	   level.flags.nsinks--; 1252. 1253. 	if (!croom_is_temple || !a->shrine) return; 1254. 1255. 	if (a->shrine) {	/* Is it a shrine  or sanctum? */ 1256. 	    priestini(&u.uz, croom, x, y, (a->shrine > 1)); 1257. 	   levl[x][y].altarmask |= AM_SHRINE; 1258. 	   level.flags.has_temple = TRUE; 1259. 	} 1260. }  1261.  1262. /*  1263.  * Create a gold pile in a room. 1264. */  1265.  1266. STATIC_OVL void 1267. create_gold(g,croom) 1268. gold *g; 1269. struct mkroom	*croom; 1270. { 1271. 	schar		x,y; 1272. 1273. 	x = g->x; y= g->y; 1274. 	if (croom) 1275. 	   get_room_loc(&x, &y, croom); 1276. 	else 1277. 	   if (!get_location(&x, &y, DRY)) 1278. 		return;		/* nowhere */ 1279. 1280. 	if (g->amount == -1) 1281. 	   g->amount = rnd(200); 1282. 	(void) mkgold((long) g->amount, x, y); 1283. } 1284.  1285. /*  1286.  * Create a feature (e.g a fountain) in a room. 1287. */  1288.  1289. STATIC_OVL void 1290. create_feature(fx, fy, croom, typ) 1291. int		fx, fy; 1292. struct mkroom	*croom; 1293. int		typ; 1294. { 1295. 	schar		x,y; 1296. 	int		trycnt = 0; 1297. 1298. 	x = fx;  y = fy; 1299. 	if (croom) { 1300. 	   if (x < 0 && y < 0) 1301. 		do { 1302. 		   x = -1;  y = -1; 1303. 		   get_room_loc(&x, &y, croom); 1304. 		} while (++trycnt <= 200 && occupied(x,y)); 1305. 	   else 1306. 		get_room_loc(&x, &y, croom); 1307. 	   if(trycnt > 200) 1308. 		return; 1309. 	} else { 1310. 	   if (!get_location(&x, &y, DRY)) 1311. 		return;		/* nowhere */ 1312. 	} 1313. 	/* Don't cover up an existing feature (particularly randomly  1314. 	   placed stairs). However, if the _same_ feature is already 1315. 	  here, it came from the map drawing and we still need to  1316. update the special counters. */ 1317. 	if (IS_FURNITURE(levl[x][y].typ) && levl[x][y].typ != typ) 1318. 	   return; 1319. 1320. 	levl[x][y].typ = typ; 1321. 	if (typ == FOUNTAIN) 1322. 	   level.flags.nfountains++; 1323. 	else if (typ == SINK) 1324. 	   level.flags.nsinks++; 1325. /*     else if (typ == TOILET) 1326. 	   level.flags.nsinks++;*/ 1327. } 1328.  1329. /*  1330.  * Search for a door in a room on a specified wall. 1331. */  1332.  1333. STATIC_OVL boolean 1334. search_door(croom,x,y,wall,cnt) 1335. struct mkroom *croom; 1336. xchar *x, *y; 1337. xchar wall; 1338. int cnt; 1339. { 1340. 	int dx, dy; 1341. 	int xx,yy; 1342. 1343. 	switch(wall) { 1344. 	     case W_NORTH: 1345. 		dy = 0; dx = 1; 1346. 		xx = croom->lx; 1347. 		yy = croom->hy + 1; 1348. 		break; 1349. 	     case W_SOUTH: 1350. 		dy = 0; dx = 1; 1351. 		xx = croom->lx; 1352. 		yy = croom->ly - 1; 1353. 		break; 1354. 	     case W_EAST: 1355. 		dy = 1; dx = 0; 1356. 		xx = croom->hx + 1; 1357. 		yy = croom->ly; 1358. 		break; 1359. 	     case W_WEST: 1360. 		dy = 1; dx = 0; 1361. 		xx = croom->lx - 1; 1362. 		yy = croom->ly; 1363. 		break; 1364. 	     default: 1365. 		dx = dy = xx = yy = 0; 1366. 		panic("search_door: Bad wall!"); 1367. 		break; 1368. 	} 1369. 	while (xx <= croom->hx+1 && yy <= croom->hy+1) { 1370. 		if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) { 1371. 			*x = xx; 1372. 			*y = yy; 1373. 			if (cnt-- <= 0) 1374. 			   return TRUE; 1375. 		} 1376. 		xx += dx; 1377. 		yy += dy; 1378. 	} 1379. 	return FALSE; 1380. } 1381.  1382. /*  1383.  * Dig a corridor between two points. 1384. */  1385.  1386. boolean 1387. dig_corridor(org,dest,nxcor,ftyp,btyp) 1388. coord *org, *dest; 1389. boolean nxcor; 1390. schar ftyp, btyp; 1391. { 1392. 	register int dx=0, dy=0, dix, diy, cct; 1393. 	register struct rm *crm; 1394. 	register int tx, ty, xx, yy; 1395. 1396. 	xx = org->x;  yy = org->y; 1397. 	tx = dest->x; ty = dest->y; 1398. 	if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 || 1399. 	    xx > COLNO-1 || tx > COLNO-1 ||  1400. 	    yy > ROWNO-1 || ty > ROWNO-1) { 1401. #ifdef DEBUG 1402. 		debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).", 1403. 			   xx,yy,tx,ty); 1404. #endif 1405. 		return FALSE; 1406. 	} 1407. 	if (tx > xx)		dx = 1; 1408. 	else if (ty > yy)	dy = 1; 1409. 	else if (tx < xx)	dx = -1; 1410. 	else			dy = -1; 1411. 1412. 	xx -= dx; 1413. 	yy -= dy; 1414. 	cct = 0; 1415. 	while(xx != tx || yy != ty) { 1416. 	   /* loop: dig corridor at [xx,yy] and find new [xx,yy] */ 1417. 	   if(cct++ > 500 || (nxcor && !rn2(35))) 1418. 		return FALSE; 1419. 1420. 	    xx += dx; 1421. 	   yy += dy; 1422. 1423. 	    if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1) 1424. 		return FALSE;		/* impossible */ 1425. 1426. 	    crm = &levl[xx][yy]; 1427. 	   if(crm->typ == btyp) { 1428. 		if(ftyp != CORR || rn2(100)) { 1429. 			crm->typ = ftyp; 1430. 			if(nxcor && !rn2(50)) 1431. 				(void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE); 1432. 		} else { 1433. 			crm->typ = SCORR; 1434. 		} 1435. 	    } else 1436. 	   if(crm->typ != ftyp && crm->typ != SCORR) { 1437. 		/* strange ... */ 1438. 		return FALSE; 1439. 	   }  1440.  1441. 	    /* find next corridor position */ 1442. 	   dix = abs(xx-tx); 1443. 	   diy = abs(yy-ty); 1444. 1445. 	    /* do we have to change direction ? */ 1446. 	    if(dy && dix > diy) { 1447. 		register int ddx = (xx > tx) ? -1 : 1; 1448.  1449. 		crm = &levl[xx+ddx][yy]; 1450. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) { 1451. 		   dx = ddx; 1452. 		   dy = 0; 1453. 		   continue; 1454. 		} 1455. 	    } else if(dx && diy > dix) { 1456. 		register int ddy = (yy > ty) ? -1 : 1; 1457.  1458. 		crm = &levl[xx][yy+ddy]; 1459. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) { 1460. 		   dy = ddy; 1461. 		   dx = 0; 1462. 		   continue; 1463. 		} 1464. 	    }  1465.  1466. 	    /* continue straight on? */ 1467. 	    crm = &levl[xx+dx][yy+dy]; 1468. 	   if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) 1469. 		continue; 1470. 1471. 	    /* no, what must we do now?? */ 1472. 	    if(dx) { 1473. 		dx = 0; 1474. 		dy = (ty < yy) ? -1 : 1; 1475. 	    } else { 1476. 		dy = 0; 1477. 		dx = (tx < xx) ? -1 : 1; 1478. 	    }  1479. 	    crm = &levl[xx+dx][yy+dy]; 1480. 	   if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) 1481. 		continue; 1482. 	   dy = -dy; 1483. 	   dx = -dx; 1484. 	} 1485. 	return TRUE; 1486. } 1487.  1488. /*  1489.  * Disgusting hack: since special levels have their rooms filled before 1490. * sorting the rooms, we have to re-arrange the speed values upstairs_room 1491. * and dnstairs_room after the rooms have been sorted. On normal levels, 1492. * stairs don't get created until _after_ sorting takes place. 1493. */  1494. STATIC_OVL void 1495. fix_stair_rooms 1496. { 1497.     int i;  1498. struct mkroom *croom; 1499. 1500.     if(xdnstair &&  1501.        !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) && 1502. 	 (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) { 1503. 	for(i=0; i < nroom; i++) { 1504. 	   croom = &rooms[i]; 1505. 	   if((croom->lx <= xdnstair && xdnstair <= croom->hx) &&  1506. 	       (croom->ly <= ydnstair && ydnstair <= croom->hy)) { 1507. 		dnstairs_room = croom; 1508. 		break; 1509. 	   }  1510. 	}  1511. 	if(i == nroom) 1512. 	   panic("Couldn't find dnstair room in fix_stair_rooms!"); 1513.    }  1514.     if(xupstair &&  1515.        !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) && 1516. 	 (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) { 1517. 	for(i=0; i < nroom; i++) { 1518. 	   croom = &rooms[i]; 1519. 	   if((croom->lx <= xupstair && xupstair <= croom->hx) &&  1520. 	       (croom->ly <= yupstair && yupstair <= croom->hy)) { 1521. 		upstairs_room = croom; 1522. 		break; 1523. 	   }  1524. 	}  1525. 	if(i == nroom) 1526. 	   panic("Couldn't find upstair room in fix_stair_rooms!"); 1527.    }  1528. }  1529.  1530. /*  1531.  * Corridors always start from a door. But it can end anywhere... 1532. * Basically we search for door coordinates or for endpoints coordinates 1533. * (from a distance). 1534. */  1535.  1536. STATIC_OVL void 1537. create_corridor(c) 1538. corridor	*c; 1539. { 1540. 	coord org, dest; 1541. 1542. 	if (c->src.room == -1) { 1543. 		sort_rooms; 1544. 		fix_stair_rooms; 1545. 		makecorridors; 1546. 		return; 1547. 	} 1548.  1549. 	if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall, 1550. 			 c->src.door)) 1551. 	   return; 1552. 1553. 	if (c->dest.room != -1) { 1554. 		if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y, 1555. c->dest.wall, c->dest.door)) 1556. 		   return; 1557. 		switch(c->src.wall) { 1558. 		     case W_NORTH: org.y--; break; 1559. 		     case W_SOUTH: org.y++; break; 1560. 		     case W_WEST:  org.x--; break; 1561. 		     case W_EAST:  org.x++; break; 1562. 		} 1563. 		switch(c->dest.wall) { 1564. 		     case W_NORTH: dest.y--; break; 1565. 		     case W_SOUTH: dest.y++; break; 1566. 		     case W_WEST:  dest.x--; break; 1567. 		     case W_EAST:  dest.x++; break; 1568. 		} 1569. 		(void) dig_corridor(&org, &dest, FALSE, CORR, STONE); 1570. 	} 1571. }  1572.  1573.  1574. /*  1575.  * Fill a room (shop, zoo, etc...) with appropriate stuff. 1576. */  1577.  1578. void 1579. fill_room(croom, prefilled) 1580. struct mkroom *croom; 1581. boolean prefilled; 1582. { 1583. 	if (!croom || croom->rtype == OROOM) 1584. 	   return; 1585. 1586. 	if (!prefilled) { 1587. 	   int x,y; 1588. 1589. 	    /* Shop ? */ 1590. 	    if (croom->rtype >= SHOPBASE) { 1591. 		   stock_room(croom->rtype - SHOPBASE, croom); 1592. 		   level.flags.has_shop = TRUE; 1593. 		   return; 1594. 	   }  1595.  1596. 	    switch (croom->rtype) { 1597. 		case VAULT: 1598. 		   for (x=croom->lx;x<=croom->hx;x++) 1599. 			for (y=croom->ly;y<=croom->hy;y++) 1600. 			   (void) mkgold((long)rn1(abs(depth(&u.uz))*100, 51), x, y); 1601. 		   break; 1602. 		case COURT: 1603. 		case ZOO: 1604. 		case BEEHIVE: 1605. 		case LEMUREPIT: 1606. 		case MIGOHIVE: 1607. 		case FUNGUSFARM: 1608. 		case MORGUE: 1609. 		case BARRACKS: 1610. 		   fill_zoo(croom); 1611. 		   break; 1612. 	   }  1613. 	}  1614. 	switch (croom->rtype) { 1615. 	   case VAULT: 1616. 		level.flags.has_vault = TRUE; 1617. 		break; 1618. 	   case ZOO: 1619. 		level.flags.has_zoo = TRUE; 1620. 		break; 1621. 	   case COURT: 1622. 		level.flags.has_court = TRUE; 1623. 		break; 1624. 	   case MORGUE: 1625. 		level.flags.has_morgue = TRUE; 1626. 		break; 1627. 	   case BEEHIVE: 1628. 		level.flags.has_beehive = TRUE; 1629. 		break; 1630. 	   case LEMUREPIT: 1631. 		level.flags.has_lemurepit = TRUE; 1632. 		break; 1633. 	   case MIGOHIVE: 1634. 		level.flags.has_migohive = TRUE; 1635. 		break; 1636. 	   case FUNGUSFARM: 1637. 		level.flags.has_fungusfarm = TRUE; 1638. 		break; 1639. 	   case BARRACKS: 1640. 		level.flags.has_barracks = TRUE; 1641. 		break; 1642. 	   case TEMPLE: 1643. 		level.flags.has_temple = TRUE; 1644. 		break; 1645. 	   case SWAMP: 1646. 		level.flags.has_swamp = TRUE; 1647. 		break; 1648. 	} 1649. }  1650.  1651. STATIC_OVL void 1652. free_rooms(ro, n) 1653. room **ro; 1654. int n; 1655. { 1656. 	short j;  1657. room *r; 1658. 1659. 	while(n--) { 1660. 		r = ro[n]; 1661. 		Free(r->name); 1662. 		Free(r->parent); 1663. 		if ((j = r->ndoor) != 0) { 1664. 			while(j--) 1665. 			   Free(r->doors[j]); 1666. 			Free(r->doors); 1667. 		} 1668. 		if ((j = r->nstair) != 0) { 1669. 			while(j--) 1670. 			   Free(r->stairs[j]); 1671. 			Free(r->stairs); 1672. 		} 1673. 		if ((j = r->naltar) != 0) { 1674. 			while (j--) 1675. 			   Free(r->altars[j]); 1676. 			Free(r->altars); 1677. 		} 1678. 		if ((j = r->nfountain) != 0) { 1679. 			while(j--) 1680. 			   Free(r->fountains[j]); 1681. 			Free(r->fountains); 1682. 		} 1683. 		if ((j = r->nsink) != 0) { 1684. 			while(j--) 1685. 			   Free(r->sinks[j]); 1686. 			Free(r->sinks); 1687. 		} 1688. 		if ((j = r->npool) != 0) { 1689. 			while(j--) 1690. 			   Free(r->pools[j]); 1691. 			Free(r->pools); 1692. 		} 1693. 		if ((j = r->ntrap) != 0) { 1694. 			while (j--) 1695. 			   Free(r->traps[j]); 1696. 			Free(r->traps); 1697. 		} 1698. 		if ((j = r->nmonster) != 0) { 1699. 			while (j--) 1700. 				Free(r->monsters[j]); 1701. 			Free(r->monsters); 1702. 		} 1703. 		if ((j = r->nobject) != 0) { 1704. 			while (j--) 1705. 				Free(r->objects[j]); 1706. 			Free(r->objects); 1707. 		} 1708. 		if ((j = r->ngold) != 0) { 1709. 			while(j--) 1710. 			   Free(r->golds[j]); 1711. 			Free(r->golds); 1712. 		} 1713. 		if ((j = r->nengraving) != 0) { 1714. 			while (j--) 1715. 				Free(r->engravings[j]); 1716. 			Free(r->engravings); 1717. 		} 1718. 		Free(r); 1719. 	} 1720. 	Free(ro); 1721. } 1722.  1723. STATIC_OVL void 1724. build_room(r, pr) 1725. room *r, *pr; 1726. { 1727. 	boolean okroom; 1728. 	struct mkroom	*aroom; 1729. 	short i; 1730. xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM; 1731. 1732. 	if(pr) { 1733. 		aroom = &subrooms[nsubroom]; 1734. 		okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h, 1735. 					rtype, r->rlit); 1736. 	} else { 1737. 		aroom = &rooms[nroom]; 1738. 		okroom = create_room(r->x, r->y, r->w, r->h, r->xalign, 1739. 				     r->yalign, rtype, r->rlit); 1740. 		r->mkr = aroom; 1741. 	} 1742.  1743. 	if (okroom) { 1744. 		/* Create subrooms if necessary... */ 1745. 		for(i=0; i < r->nsubroom; i++) 1746. 		   build_room(r->subrooms[i], r); 1747. 		/* And now we can fill the room! */ 1748.  1749. 		/* Priority to the stairs */ 1750. 1751. 		for(i=0; i nstair; i++) 1752. 		   create_stairs(r->stairs[i], aroom); 1753. 1754. 		/* Then to the various elements (sinks, etc..) */ 1755. 		for(i = 0; insink; i++) 1756. 		   create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK); 1757. /*             for(i = 0; intoilet; i++) 1758. 		   create_feature(r->toilets[i]->x, r->toilets[i]->y, aroom, TOILET);*/ 1759. 		for(i = 0; inpool; i++) 1760. 		   create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL); 1761. 		for(i = 0; infountain; i++) 1762. 		   create_feature(r->fountains[i]->x, r->fountains[i]->y,  1763. 				   aroom, FOUNTAIN); 1764. 		for(i = 0; inaltar; i++) 1765. 		   create_altar(r->altars[i], aroom); 1766. 		for(i = 0; indoor; i++) 1767. 		   create_door(r->doors[i], aroom); 1768. 1769. 		/* The traps */ 1770. 		for(i = 0; intrap; i++) 1771. 		   create_trap(r->traps[i], aroom); 1772. 1773. 		/* The monsters */ 1774. 		for(i = 0; inmonster; i++) 1775. 		   create_monster(r->monsters[i], aroom); 1776. 1777. 		/* The objects */ 1778. 		for(i = 0; inobject; i++) 1779. 		   create_object(r->objects[i], aroom); 1780. 1781. 		/* The gold piles */ 1782. 		for(i = 0; ingold; i++) 1783. 		   create_gold(r->golds[i], aroom); 1784. 1785. 		/* The engravings */ 1786. 		for (i = 0; i < r->nengraving; i++) 1787. 		   create_engraving(r->engravings[i], aroom); 1788. 1789. #ifdef SPECIALIZATION 1790. 		topologize(aroom,FALSE);		/* set roomno */ 1791. #else 1792. 		topologize(aroom);			/* set roomno */ 1793. #endif 1794. 		/* MRS - 07/04/91 - This is temporary but should result 1795. 		 * in proper filling of shops, etc. 1796. 		 * DLC - this can fail if corridors are added to this room 1797. 		 * at a later point. Currently no good way to fix this. 1798. 		 */ 1799. 		if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE); 1800. 	} 1801. }  1802.  1803. /*  1804.  * set lighting in a region that will not become a room. 1805. */  1806. STATIC_OVL void 1807. light_region(tmpregion) 1808.    region  *tmpregion; 1809. { 1810.     register boolean litstate = tmpregion->rlit ? 1 : 0; 1811.     register int hiy = tmpregion->y2; 1812.    register int x, y;  1813. register struct rm *lev; 1814.    int lowy = tmpregion->y1; 1815.    int lowx = tmpregion->x1, hix = tmpregion->x2; 1816. 1817.     if(litstate) { 1818. 	/* adjust region size for walls, but only if lighted */ 1819. 	lowx = max(lowx-1,1); 1820. 	hix = min(hix+1,COLNO-1); 1821. 	lowy = max(lowy-1,0); 1822. 	hiy = min(hiy+1, ROWNO-1); 1823.    }  1824.     for(x = lowx; x <= hix; x++) { 1825. 	lev = &levl[x][lowy]; 1826. 	for(y = lowy; y <= hiy; y++) { 1827. 	   if (lev->typ != LAVAPOOL) /* this overrides normal lighting */ 1828. 		lev->lit = litstate; 1829. 	   lev++; 1830. 	} 1831.     }  1832. }  1833.  1834. /* initialization common to all special levels */ 1835. STATIC_OVL void 1836. load_common_data(fd, typ) 1837. dlb *fd; 1838. int typ; 1839. { 1840. 	uchar	n; 1841. 	long	lev_flags; 1842. 	int	i; 1843. 1844.       {  1845. 	aligntyp atmp; 1846. 	/* shuffle 3 alignments; can't use sp_lev_shuffle on aligntyp's */ 1847. 	i = rn2(3);  atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp; 1848. 	if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; } 1849.      }  1850.  1851. 	level.flags.is_maze_lev = typ == SP_LEV_MAZE; 1852. 1853. 	/* Read the level initialization data */ 1854. 	Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd); 1855. 	if(init_lev.init_present) { 1856. 	   if(init_lev.lit < 0) 1857. 		init_lev.lit = rn2(2); 1858. 	   mkmap(&init_lev); 1859. 	} 1860.  1861. 	/* Read the per level flags */ 1862. 	Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd); 1863. 	if (lev_flags & NOTELEPORT) 1864. 	   level.flags.noteleport = 1; 1865. 	if (lev_flags & HARDFLOOR) 1866. 	   level.flags.hardfloor = 1; 1867. 	if (lev_flags & NOMMAP) 1868. 	   level.flags.nommap = 1; 1869. 	if (lev_flags & SHORTSIGHTED) 1870. 	   level.flags.shortsighted = 1; 1871. 	if (lev_flags & ARBOREAL) 1872. 	   level.flags.arboreal = 1; 1873. 	if (lev_flags & SPOOKY) 1874. 	   level.flags.spooky = 1; 1875. 	if (lev_flags & LETHE) 1876. 	   level.flags.lethe = 1; 1877. 1878. 	/* Read message */ 1879. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 1880. 	if (n) { 1881. 	   lev_message = (char *) alloc(n + 1); 1882. 	   Fread((genericptr_t) lev_message, 1, (int) n, fd); 1883. 	   lev_message[n] = 0; 1884. 	} 1885. }  1886.  1887. STATIC_OVL void 1888. load_one_monster(fd, m) 1889. dlb *fd; 1890. monster *m; 1891. { 1892. 	int size; 1893. 1894. 	Fread((genericptr_t) m, 1, sizeof *m, fd); 1895. 	if ((size = m->name.len) != 0) { 1896. 	   m->name.str = (char *) alloc((unsigned)size + 1); 1897. 	   Fread((genericptr_t) m->name.str, 1, size, fd); 1898. 	   m->name.str[size] = '\0'; 1899. 	} else 1900. 	   m->name.str = (char *) 0; 1901. 	if ((size = m->appear_as.len) != 0) { 1902. 	   m->appear_as.str = (char *) alloc((unsigned)size + 1); 1903. 	   Fread((genericptr_t) m->appear_as.str, 1, size, fd); 1904. 	   m->appear_as.str[size] = '\0'; 1905. 	} else 1906. 	   m->appear_as.str = (char *) 0; 1907. } 1908.  1909. STATIC_OVL void 1910. load_one_object(fd, o) 1911. dlb *fd; 1912. object *o; 1913. { 1914. 	int size; 1915. 1916. 	Fread((genericptr_t) o, 1, sizeof *o, fd); 1917. 	if ((size = o->name.len) != 0) { 1918. 	   o->name.str = (char *) alloc((unsigned)size + 1); 1919. 	   Fread((genericptr_t) o->name.str, 1, size, fd); 1920. 	   o->name.str[size] = '\0'; 1921. 	} else 1922. 	   o->name.str = (char *) 0; 1923. } 1924.  1925. STATIC_OVL void 1926. load_one_engraving(fd, e) 1927. dlb *fd; 1928. engraving *e; 1929. { 1930. 	int size; 1931. 1932. 	Fread((genericptr_t) e, 1, sizeof *e, fd); 1933. 	size = e->engr.len; 1934. 	e->engr.str = (char *) alloc((unsigned)size+1); 1935. 	Fread((genericptr_t) e->engr.str, 1, size, fd); 1936. 	e->engr.str[size] = '\0'; 1937. } 1938.  1939. STATIC_OVL boolean 1940. load_rooms(fd) 1941. dlb *fd; 1942. { 1943. 	xchar		nrooms, ncorr; 1944. 	char		n; 1945. 	short		size; 1946. 	corridor	tmpcor; 1947. 	room**		tmproom; 1948. 	int		i, j; 1949. 1950. 	load_common_data(fd, SP_LEV_ROOMS); 1951. 1952. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */ 1953. 	if (n) { 1954. 		Fread((genericptr_t)robjects, sizeof(*robjects), n, fd); 1955. 		sp_lev_shuffle(robjects, (char *)0, (int)n); 1956. 	} 1957.  1958. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */ 1959. 	if (n) { 1960. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd); 1961. 		sp_lev_shuffle(rmonst, (char *)0, (int)n); 1962. 	} 1963.  1964. 	Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd); 1965. 						/* Number of rooms to read */ 1966. 	tmproom = NewTab(room,nrooms); 1967. 	for (i=0;i 0) {	/* Yup, it does! */ 1975. 			r->name = (char *) alloc((unsigned)size + 1); 1976. 			Fread((genericptr_t) r->name, 1, size, fd); 1977. 			r->name[size] = 0; 1978. 		} else 1979. 		   r->name = (char *) 0; 1980. 1981. 		/* Let's see if this room has a parent */ 1982. 		Fread((genericptr_t) &size, 1, sizeof(size), fd); 1983. 		if (size > 0) {	/* Yup, it does! */ 1984. 			r->parent = (char *) alloc((unsigned)size + 1); 1985. 			Fread((genericptr_t) r->parent, 1, size, fd); 1986. 			r->parent[size] = 0; 1987. 		} else 1988. 		   r->parent = (char *) 0; 1989. 1990. 		Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd); 1991. 					/* x pos on the grid (1-5) */ 1992. 		Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd); 1993. 					 /* y pos on the grid (1-5) */ 1994. 		Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd); 1995. 					 /* width of the room */ 1996. 		Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd); 1997. 					 /* height of the room */ 1998. 		Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd); 1999. 					 /* horizontal alignment */ 2000. 		Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd); 2001. 					 /* vertical alignment */ 2002. 		Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd); 2003. 					 /* type of room (zoo, shop, etc.) */ 2004. 		Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd); 2005. 					 /* chance of room being special. */ 2006. 		Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd); 2007. 					 /* lit or not ? */ 2008. 		Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd); 2009. 					 /* to be filled? */ 2010. 		r->nsubroom= 0; 2011. 2012. 		/* read the doors */ 2013. 		Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd); 2014. 		if ((n = r->ndoor) != 0) 2015. 		   r->doors = NewTab(room_door, n); 2016. 		while(n--) { 2017. 			r->doors[(int)n] = New(room_door); 2018. 			Fread((genericptr_t) r->doors[(int)n], 1, 2019. 				sizeof(room_door), fd); 2020. 		} 2021.  2022. 		/* read the stairs */ 2023. 		Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd); 2024. 		if ((n = r->nstair) != 0) 2025. 		   r->stairs = NewTab(stair, n); 2026. 		while (n--) { 2027. 			r->stairs[(int)n] = New(stair); 2028. 			Fread((genericptr_t) r->stairs[(int)n], 1, 2029. 				sizeof(stair), fd); 2030. 		} 2031.  2032. 		/* read the altars */ 2033. 		Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd); 2034. 		if ((n = r->naltar) != 0) 2035. 		   r->altars = NewTab(altar, n); 2036. 		while (n--) { 2037. 			r->altars[(int)n] = New(altar); 2038. 			Fread((genericptr_t) r->altars[(int)n], 1, 2039. 				sizeof(altar), fd); 2040. 		} 2041.  2042. 		/* read the fountains */ 2043. 		Fread((genericptr_t) &r->nfountain, 1, 2044. 			sizeof(r->nfountain), fd); 2045. 		if ((n = r->nfountain) != 0) 2046. 		   r->fountains = NewTab(fountain, n); 2047. 		while (n--) { 2048. 			r->fountains[(int)n] = New(fountain); 2049. 			Fread((genericptr_t) r->fountains[(int)n], 1, 2050. 				sizeof(fountain), fd); 2051. 		} 2052.  2053. 		/* read the sinks */ 2054. 		Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd); 2055. 		if ((n = r->nsink) != 0) 2056. 		   r->sinks = NewTab(sink, n); 2057. 		while (n--) { 2058. 			r->sinks[(int)n] = New(sink); 2059. 			Fread((genericptr_t) r->sinks[(int)n], 1, sizeof(sink), fd); 2060. 		} 2061.  2062. 		/* read the pools */ 2063. 		Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd); 2064. 		if ((n = r->npool) != 0) 2065. 		   r->pools = NewTab(pool,n); 2066. 		while (n--) { 2067. 			r->pools[(int)n] = New(pool); 2068. 			Fread((genericptr_t) r->pools[(int)n], 1, sizeof(pool), fd); 2069. 		} 2070.  2071. 		/* read the traps */ 2072. 		Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd); 2073. 		if ((n = r->ntrap) != 0) 2074. 		   r->traps = NewTab(trap, n); 2075. 		while(n--) { 2076. 			r->traps[(int)n] = New(trap); 2077. 			Fread((genericptr_t) r->traps[(int)n], 1, sizeof(trap), fd); 2078. 		} 2079.  2080. 		/* read the monsters */ 2081. 		Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd); 2082. 		if ((n = r->nmonster) != 0) { 2083. 		   r->monsters = NewTab(monster, n); 2084. 		   while(n--) { 2085. 			r->monsters[(int)n] = New(monster); 2086. 			load_one_monster(fd, r->monsters[(int)n]); 2087. 		   }  2088. 		} else 2089. 		   r->monsters = 0; 2090. 2091. 		/* read the objects, in same order as mazes */ 2092. 		Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd); 2093. 		if ((n = r->nobject) != 0) { 2094. 		   r->objects = NewTab(object, n); 2095. 		   for (j = 0; j < n; ++j) { 2096. 			r->objects[j] = New(object); 2097. 			load_one_object(fd, r->objects[j]); 2098. 		   }  2099. 		} else 2100. 		   r->objects = 0; 2101. 2102. 		/* read the gold piles */ 2103. 		Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd); 2104. 		if ((n = r->ngold) != 0) 2105. 		   r->golds = NewTab(gold, n); 2106. 		while (n--) { 2107. 			r->golds[(int)n] = New(gold); 2108. 			Fread((genericptr_t) r->golds[(int)n], 1, sizeof(gold), fd); 2109. 		} 2110.  2111. 		/* read the engravings */ 2112. 		Fread((genericptr_t) &r->nengraving, 1, 2113. 			sizeof(r->nengraving), fd); 2114. 		if ((n = r->nengraving) != 0) { 2115. 		   r->engravings = NewTab(engraving,n); 2116. 		   while (n--) { 2117. 			r->engravings[(int)n] = New(engraving); 2118. 			load_one_engraving(fd, r->engravings[(int)n]); 2119. 		   }  2120. 		} else 2121. 		   r->engravings = 0; 2122. 2123. 	}  2124.  2125. 	/* Now that we have loaded all the rooms, search the 2126. 	 * subrooms and create the links. 2127. 	 */ 2128.  2129. 	for (i = 0; iparent) { 2131. 		   /* Search the parent room */ 2132. 		   for(j=0; jname && !strcmp(tmproom[j]->name, 2134. 						      tmproom[i]->parent)) { 2135. 				n = tmproom[j]->nsubroom++; 2136. 				tmproom[j]->subrooms[(int)n] = tmproom[i]; 2137. 				break; 2138. 			} 2139. 	    }  2140.  2141. 	/*  2142. 	 * Create the rooms now...  2143. */ 2144.  2145. 	for (i=0; i < nrooms; i++) 2146. 	   if(!tmproom[i]->parent) 2147. 		build_room(tmproom[i], (room *) 0); 2148. 2149. 	free_rooms(tmproom, nrooms); 2150. 2151. 	/* read the corridors */ 2152. 2153. 	Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd); 2154. 	for (i=0; i<ncorr; i++) { 2155. 		Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd); 2156. 		create_corridor(&tmpcor); 2157. 	} 2158.  2159. 	return TRUE; 2160. } 2161.  2162. /*  2163.  * Select a random coordinate in the maze. 2164. *  2165.  * We want a place not 'touched' by the loader. That is, a place in 2166. * the maze outside every part of the special level. 2167. */  2168.  2169. STATIC_OVL void 2170. maze1xy(m, humidity) 2171. coord *m; 2172. int humidity; 2173. { 2174. 	register int x, y, tryct = 2000; 2175. 	/* tryct: normally it won't take more than ten or so tries due 2176. 	  to the circumstances under which we'll be called, but the 2177. 	  `humidity' screening might drastically change the chances */ 2178. 2179. 	do { 2180. 	   x = rn1(x_maze_max - 3, 3); 2181. 	   y = rn1(y_maze_max - 3, 3); 2182. 	   if (--tryct < 0) break;	/* give up */ 2183. 	} while (!(x % 2) || !(y % 2) || Map[x][y] || 2184. 		 !is_ok_location((schar)x, (schar)y, humidity)); 2185. 2186. 	m->x = (xchar)x,  m->y = (xchar)y; 2187. } 2188.  2189. /*  2190.  * The Big Thing: special maze loader 2191. *  2192.  * Could be cleaner, but it works. 2193. */  2194.  2195. STATIC_OVL boolean 2196. load_maze(fd) 2197. dlb *fd; 2198. { 2199.     xchar   x, y, typ; 2200.    boolean prefilled, room_not_needed; 2201. 2202.     char    n, numpart = 0; 2203.    xchar   nwalk = 0, nwalk_sav; 2204.    schar   filling; 2205.    char    halign, valign; 2206. 2207.     int     xi, dir, size; 2208.    coord   mm; 2209.    int     mapcount, mapcountmax, mapfact; 2210. 2211.     lev_region  tmplregion; 2212.    region  tmpregion; 2213.    door    tmpdoor; 2214.    trap    tmptrap; 2215.    monster tmpmons; 2216.    object  tmpobj; 2217.    drawbridge tmpdb; 2218.    walk    tmpwalk; 2219.    digpos  tmpdig; 2220.    lad     tmplad; 2221.    stair   tmpstair, prevstair; 2222.    altar   tmpaltar; 2223.    gold    tmpgold; 2224.    fountain tmpfountain; 2225.    engraving tmpengraving; 2226.    xchar   mustfill[(MAXNROFROOMS+1)*2]; 2227.    struct trap *badtrap; 2228.    boolean has_bounds; 2229. 2230.     (void) memset((genericptr_t)&Map[0][0], 0, sizeof Map); 2231.    load_common_data(fd, SP_LEV_MAZE); 2232. 2233.     /* Initialize map */ 2234.    Fread((genericptr_t) &filling, 1, sizeof(filling), fd); 2235.    if (!init_lev.init_present) { /* don't init if mkmap has been called */ 2236.      for(x = 2; x <= x_maze_max; x++) 2237. 	for(y = 0; y <= y_maze_max; y++) 2238. 	   if (filling == -1) { 2239. #ifndef WALLIFIED_MAZE 2240. 		   levl[x][y].typ = STONE; 2241. #else 2242. 		   levl[x][y].typ = 2243. 			(y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL; 2244. #endif 2245. 	   } else { 2246. 		   levl[x][y].typ = filling; 2247. 	   }  2248.     }  2249.  2250.     /* Start reading the file */ 2251.    Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd); 2252. 						/* Number of parts */ 2253.    if (!numpart || numpart > 9) 2254. 	panic("load_maze error: numpart = %d", (int) numpart); 2255. 2256.     while (numpart--) { 2257. 	Fread((genericptr_t) &halign, 1, sizeof(halign), fd); 2258. 					/* Horizontal alignment */ 2259. 	Fread((genericptr_t) &valign, 1, sizeof(valign), fd); 2260. 					/* Vertical alignment */ 2261. 	Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd); 2262. 					/* size in X */ 2263. 	Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd); 2264. 					/* size in Y */ 2265. 	switch((int) halign) { 2266. 	   case LEFT:	    xstart = 3;					break; 2267. 	   case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);	break; 2268. 	   case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break; 2269. 	   case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);	break; 2270. 	   case RIGHT:     xstart = x_maze_max-xsize-1;		break; 2271. 	} 2272. 	switch((int) valign) { 2273. 	   case TOP:	    ystart = 3;					break; 2274. 	   case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break; 2275. 	   case BOTTOM:    ystart = y_maze_max-ysize-1;		break; 2276. 	} 2277. 	if (!(xstart % 2)) xstart++; 2278. 	if (!(ystart % 2)) ystart++; 2279. 	if ((ystart < 0) || (ystart + ysize > ROWNO)) { 2280. 	   /* try to move the start a bit */ 2281. 	   ystart += (ystart > 0) ? -2 : 2; 2282. 	    if(ysize == ROWNO) ystart = 0; 2283. 	   if(ystart < 0 || ystart + ysize > ROWNO) 2284. 		panic("reading special level with ysize too large"); 2285. 	} 2286.  2287. 	/*  2288. 	 * If any CROSSWALLs are found, must change to ROOM after REGION's  2289. * are laid out. CROSSWALLS are used to specify "invisible" 2290. 	 * boundaries where DOOR syms look bad or aren't desirable. 2291. 	 */ 2292. 	has_bounds = FALSE; 2293. 2294. 	if(init_lev.init_present && xsize <= 1 && ysize <= 1) { 2295. 	   xstart = 1; 2296. 	   ystart = 0; 2297. 	   xsize = COLNO-1; 2298. 	   ysize = ROWNO; 2299. 	} else { 2300. 	   /* Load the map */ 2301. 	   for(y = ystart; y < ystart+ysize; y++) 2302. 		for(x = xstart; x < xstart+xsize; x++) { 2303. 		   levl[x][y].typ = Fgetc(fd); 2304. 		   levl[x][y].lit = FALSE; 2305. 		   /* clear out levl: load_common_data may set them */ 2306. 		   levl[x][y].flags = 0; 2307. 		   levl[x][y].horizontal = 0; 2308. 		   levl[x][y].roomno = 0; 2309. 		   levl[x][y].edge = 0; 2310. 		   /*  2311. 		     * Note: Even though levl[x][y].typ is type schar, 2312. 		    *	 lev_comp.y saves it as type char. Since schar != char 2313. 		    *	 all the time we must make this exception or hack 2314. 		    *	 through lev_comp.y to fix. 2315. 		    */  2316.  2317. 		    /*  2318. 		     *  Set secret doors to closed (why not trapped too?). Set 2319. 		    *  the horizontal bit. 2320. 		    */  2321. 		    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) { 2322. 			if(levl[x][y].typ == SDOOR) 2323. 			   levl[x][y].doormask = D_CLOSED; 2324. 			/* 2325. 			 *  If there is a wall to the left that connects to a  2326. * (secret) door, then it is horizontal. This does 2327. 			 * not allow (secret) doors to be corners of rooms. 2328. 			 */ 2329. 			if (x != xstart && (IS_WALL(levl[x-1][y].typ) || 2330. 					   levl[x-1][y].horizontal)) 2331. 			   levl[x][y].horizontal = 1; 2332. 		   } else if(levl[x][y].typ == HWALL ||  2333. 				levl[x][y].typ == IRONBARS) 2334. 			levl[x][y].horizontal = 1; 2335. 		   else if(levl[x][y].typ == LAVAPOOL) 2336. 			levl[x][y].lit = 1; 2337. 		   else if(levl[x][y].typ == CROSSWALL) 2338. 			has_bounds = TRUE; 2339. 		   Map[x][y] = 1; 2340. 		} 2341. 	    if (init_lev.init_present && init_lev.joined) 2342. 		remove_rooms(xstart, ystart, xstart+xsize, ystart+ysize); 2343. 	} 2344.  2345. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2346. 						/* Number of level regions */ 2347. 	if(n) { 2348. 	   if(num_lregions) { 2349. 		/* realloc the lregion space to add the new ones */ 2350. 		/* don't really free it up until the whole level is done */ 2351. 		lev_region *newl = (lev_region *) alloc(sizeof(lev_region) * 2352. 						(unsigned)(n+num_lregions)); 2353. 		(void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions, 2354. 					sizeof(lev_region) * num_lregions); 2355. 		Free(lregions); 2356. 		num_lregions += n; 2357. lregions = newl; 2358. 	   } else { 2359. 		num_lregions = n; 2360. lregions = (lev_region *) 2361. 				alloc(sizeof(lev_region) * (unsigned)n); 2362. 	   }  2363. 	}  2364.  2365. 	while(n--) { 2366. 	   boolean found = TRUE; 2367. 	   Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd); 2368. 	   if ((size = tmplregion.rname.len) != 0) { 2369. 		tmplregion.rname.str = (char *) alloc((unsigned)size + 1); 2370. 		Fread((genericptr_t) tmplregion.rname.str, size, 1, fd); 2371. 		tmplregion.rname.str[size] = '\0'; 2372. 	   } else 2373. 		tmplregion.rname.str = (char *) 0; 2374. 	   if(!tmplregion.in_islev) { 2375. 		found &= get_location(&tmplregion.inarea.x1, 2376. 				      &tmplregion.inarea.y1, DRY|WET); 2377. 		found &= get_location(&tmplregion.inarea.x2, 2378. 				      &tmplregion.inarea.y2, DRY|WET); 2379. 	   }  2380. 	    if(!tmplregion.del_islev) { 2381. 		found &= get_location(&tmplregion.delarea.x1, 2382. 				      &tmplregion.delarea.y1, DRY|WET); 2383. 		found &= get_location(&tmplregion.delarea.x2, 2384. 				      &tmplregion.delarea.y2, DRY|WET); 2385. 	   }  2386. 	    if (!found) 2387. 		panic("reading special level with region located nowhere"); 2388. 	   lregions[(int)n] = tmplregion; 2389. 	} 2390.  2391. 	/* random level region registers */ 2392. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2393. 	if (n) { 2394. 	   int tmpn = n;  2395. while(n--) { 2396. 		boolean found = TRUE; 2397. 		Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd); 2398. 		if ((size = tmplregion.rname.len) != 0) { 2399. 		   tmplregion.rname.str = (char *) alloc((unsigned)size + 1); 2400. 		   Fread((genericptr_t) tmplregion.rname.str, size, 1, fd); 2401. 		   tmplregion.rname.str[size] = '\0'; 2402. 		} else 2403. 		   tmplregion.rname.str = (char *) 0; 2404. 		if (!found) 2405. 		   panic("reading special level with random region located nowhere"); 2406. 		(void) memcpy((genericptr_t)&rarea[(int)tmpn - n - 1], 2407. 			(genericptr_t)&tmplregion, sizeof(lev_region)); 2408. 	   }  2409. 	}  2410.  2411. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2412. 						/* Random objects */ 2413. 	if(n) { 2414. 		Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd); 2415. 		sp_lev_shuffle(robjects, (char *)0, (int)n); 2416. 	} 2417.  2418. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2419. 						/* Random locations */ 2420. 	if(n) { 2421. 		char nloc[10]; 2422. 		Fread((genericptr_t)nloc, sizeof(*nloc), (int) n, fd); 2423. 		for(xi = 0; xi < n; xi++) { 2424. 		   Fread((genericptr_t)rloc_x[xi], sizeof(*rloc_x[xi]),  2425. 			    (int) nloc[xi], fd); 2426. 		   Fread((genericptr_t)rloc_y[xi], sizeof(*rloc_y[xi]),  2427. 			    (int) nloc[xi], fd); 2428. 		   sp_lev_shuffle(rloc_x[xi], rloc_y[xi], (int)nloc[xi]); 2429. 		} 2430. 	}  2431.  2432. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2433. 						/* Random monsters */ 2434. 	if(n) { 2435. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd); 2436. 		sp_lev_shuffle(rmonst, (char *)0, (int)n); 2437. 	} 2438.  2439. 	(void) memset((genericptr_t)mustfill, 0, sizeof(mustfill)); 2440. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2441. 						/* Number of subrooms */ 2442. 	while(n--) { 2443. 		register struct mkroom *troom; 2444. 2445. 		Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd); 2446. 2447. 		if(tmpregion.rtype > MAXRTYPE) { 2448. 		   tmpregion.rtype -= MAXRTYPE+1; 2449. 		   prefilled = TRUE; 2450. 		} else 2451. 		   prefilled = FALSE; 2452. 2453. 		if(tmpregion.rlit < 0) 2454. 		   tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) 2455. 			? TRUE : FALSE; 2456. 2457. 		if (!get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET) ||  2458. 		  !get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET)) 2459. 		   panic("reading special level with region located nowhere"); 2460. 2461. 		/* for an ordinary room, `prefilled' is a flag to force 2462. 		  an actual room to be created (such rooms are used to  2463. 		   control placement of migrating monster arrivals) */ 2464. 		room_not_needed = (tmpregion.rtype == OROOM && 2465. 				   !tmpregion.rirreg && !prefilled); 2466. 		if (room_not_needed || nroom >= MAXNROFROOMS) { 2467. 		   if (!room_not_needed) 2468. 			impossible("Too many rooms on new level!"); 2469. 		   light_region(&tmpregion); 2470. 		   continue; 2471. 		} 2472.  2473. 		troom = &rooms[nroom]; 2474. 2475. 		/* mark rooms that must be filled, but do it later */ 2476. 		if (tmpregion.rtype != OROOM) 2477. 		   mustfill[nroom] = (prefilled ? 2 : 1); 2478. 2479. 		if(tmpregion.rirreg) { 2480. 		   min_rx = max_rx = tmpregion.x1; 2481. 		   min_ry = max_ry = tmpregion.y1; 2482. 		   flood_fill_rm(tmpregion.x1, tmpregion.y1,  2483. 				  nroom+ROOMOFFSET, tmpregion.rlit, TRUE); 2484. 		   add_room(min_rx, min_ry, max_rx, max_ry,  2485. 			     FALSE, tmpregion.rtype, TRUE); 2486. 		   troom->rlit = tmpregion.rlit; 2487. 		   troom->irregular = TRUE; 2488. 		} else { 2489. 		   add_room(tmpregion.x1, tmpregion.y1,  2490. 			     tmpregion.x2, tmpregion.y2,  2491. 			     tmpregion.rlit, tmpregion.rtype, TRUE); 2492. #ifdef SPECIALIZATION 2493. 		   topologize(troom,FALSE);		/* set roomno */ 2494. #else 2495. 		   topologize(troom);			/* set roomno */ 2496. #endif 2497. 		} 2498. 	}  2499.  2500. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2501. 						/* Number of doors */ 2502. 	while(n--) { 2503. 		struct mkroom *croom = &rooms[0]; 2504. 2505. 		Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd); 2506. 2507. 		x = tmpdoor.x;	y = tmpdoor.y;  2508. typ = tmpdoor.mask == -1 ? rnddoor : tmpdoor.mask; 2509. 2510. 		if (get_location(&x, &y, DRY)) { 2511. 		if(levl[x][y].typ != SDOOR) 2512. 			levl[x][y].typ = DOOR; 2513. 		else { 2514. 			if(typ < D_CLOSED) 2515. 			   typ = D_CLOSED; /* force it to be closed */ 2516. 		} 2517. 		levl[x][y].doormask = typ; 2518. 		} 2519.  2520. 		/* Now the complicated part, list it with each subroom */ 2521. 		/* The dog move and mail daemon routines use this */ 2522. 		xi = -1; 2523. 		while(croom->hx >= 0 && doorindex < DOORMAX) { 2524. 		   if(croom->hx >= x-1 && croom->lx <= x+1 &&  2525. 		       croom->hy >= y-1 && croom->ly <= y+1) { 2526. 			/* Found it */ 2527. 			xi = add_door(x, y, croom); 2528. 			doors[xi].arti_key = tmpdoor.arti_key; 2529. 		   }  2530. 		    croom++; 2531. 		} 2532. 		if (xi < 0) {	/* Not in any room */ 2533. 		   if (doorindex >= DOORMAX) 2534. 			impossible("Too many doors?"); 2535. 		   else { 2536. 			xi = add_door(x, y, (struct mkroom *)0); 2537. 			doors[xi].arti_key = tmpdoor.arti_key; 2538. 		   }  2539. 		}  2540. 	}  2541.  2542. 	/* now that we have rooms _and_ associated doors, fill the rooms */ 2543. 	for(n = 0; n < SIZE(mustfill); n++) 2544. 	   if(mustfill[(int)n]) 2545. 		fill_room(&rooms[(int)n], (mustfill[(int)n] == 2)); 2546. 2547. 	/* if special boundary syms (CROSSWALL) in map, remove them now */ 2548. 	if(has_bounds) { 2549. 	   for(x = xstart; x < xstart+xsize; x++) 2550. 		for(y = ystart; y < ystart+ysize; y++) 2551. 		   if(levl[x][y].typ == CROSSWALL) 2552. 			levl[x][y].typ = ROOM; 2553. 	} 2554.  2555. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2556. 						/* Number of drawbridges */ 2557. 	while(n--) { 2558. 		Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd); 2559. 2560. 		x = tmpdb.x;  y = tmpdb.y;  2561. if (get_location(&x, &y, DRY|WET)) { 2562. 		if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open)) 2563. 		   impossible("Cannot create drawbridge."); 2564. 	} 2565. 	}  2566.  2567. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2568. 						/* Number of mazewalks */ 2569. 	while(n--) { 2570. 		Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd); 2571. 2572. 		if (get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET)) 2573. 		walklist[nwalk++] = tmpwalk; 2574. 	} 2575.  2576. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2577. 						/* Number of non_diggables */ 2578. 	while(n--) { 2579. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd); 2580. 2581. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET); 2582. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET); 2583. 2584. 		set_wall_property(tmpdig.x1, tmpdig.y1,  2585. 				  tmpdig.x2, tmpdig.y2, W_NONDIGGABLE); 2586. 	} 2587.  2588. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2589. 						/* Number of non_passables */ 2590. 	while(n--) { 2591. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd); 2592. 2593. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET); 2594. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET); 2595. 2596. 		set_wall_property(tmpdig.x1, tmpdig.y1,  2597. 				  tmpdig.x2, tmpdig.y2, W_NONPASSWALL); 2598. 	} 2599.  2600. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2601. 						/* Number of ladders */ 2602. 	while(n--) { 2603. 		Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd); 2604. 2605. 		x = tmplad.x;  y = tmplad.y;  2606. if (get_location(&x, &y, DRY)) { 2607. 		levl[x][y].typ = LADDER; 2608. 		if (tmplad.up == 1) { 2609. 			xupladder = x;	yupladder = y; 2610. levl[x][y].ladder = LA_UP; 2611. 		} else { 2612. 			xdnladder = x;	ydnladder = y; 2613. levl[x][y].ladder = LA_DOWN; 2614. 		} 2615. 	}  2616. 	}  2617.  2618. 	prevstair.x = prevstair.y = 0; 2619. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2620. 						/* Number of stairs */ 2621. 	while(n--) { 2622. 		boolean found; 2623. 		Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd); 2624. 2625. 		xi = 0; 2626. 		do { 2627. 		   x = tmpstair.x;  y = tmpstair.y;  2628. found = get_location(&x, &y, DRY); 2629. 		} while(found && prevstair.x && xi++ < 100 && 2630. 			distmin(x,y,prevstair.x,prevstair.y) <= 8); 2631. 		if (!found) 2632. 		   continue; 2633. 		if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap); 2634. 		mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0); 2635. 		prevstair.x = x; 2636. prevstair.y = y; 2637. } 2638.  2639. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2640. 						/* Number of altars */ 2641. 	while(n--) { 2642. 		Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd); 2643. 2644. 		create_altar(&tmpaltar, (struct mkroom *)0); 2645. 	} 2646.  2647. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2648. 						/* Number of fountains */ 2649. 	while (n--) { 2650. 		Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd); 2651. 2652. 		create_feature(tmpfountain.x, tmpfountain.y,  2653. 			       (struct mkroom *)0, FOUNTAIN); 2654. 	} 2655.  2656. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2657. 						/* Number of traps */ 2658. 	while(n--) { 2659. 		Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd); 2660. 2661. 		create_trap(&tmptrap, (struct mkroom *)0); 2662. 	} 2663.  2664. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2665. 						/* Number of monsters */ 2666. 	while(n--) { 2667. 		load_one_monster(fd, &tmpmons); 2668. 2669. 		create_monster(&tmpmons, (struct mkroom *)0); 2670. 	} 2671.  2672. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2673. 						/* Number of objects */ 2674. 	while(n--) { 2675. 		load_one_object(fd, &tmpobj); 2676. 2677. 		create_object(&tmpobj, (struct mkroom *)0); 2678. 	} 2679.  2680. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2681. 						/* Number of gold piles */ 2682. 	while (n--) { 2683. 		Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd); 2684. 2685. 		create_gold(&tmpgold, (struct mkroom *)0); 2686. 	} 2687.  2688. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); 2689. 						/* Number of engravings */ 2690. 	while(n--) { 2691. 		load_one_engraving(fd, &tmpengraving); 2692. 2693. 		create_engraving(&tmpengraving, (struct mkroom *)0); 2694. 	} 2695.  2696.     }		/* numpart loop */ 2697. 2698.     nwalk_sav = nwalk; 2699.    while(nwalk--) { 2700. 	   x = (xchar) walklist[nwalk].x;  2701. y = (xchar) walklist[nwalk].y; 2702. dir = walklist[nwalk].dir; 2703. 2704. 	    /* don't use move - it doesn't use W_NORTH, etc. */ 2705. 	   switch (dir) { 2706. 		case W_NORTH: --y; break; 2707. 		case W_SOUTH: y++; break; 2708. 		case W_EAST: x++; break; 2709. 		case W_WEST: --x; break; 2710. 		default: panic("load_maze: bad MAZEWALK direction"); 2711. 	   }  2712.  2713. 	    if(!IS_DOOR(levl[x][y].typ)) { 2714. #ifndef WALLIFIED_MAZE 2715. 		levl[x][y].typ = CORR; 2716. #else 2717. 		levl[x][y].typ = ROOM; 2718. #endif 2719. 		levl[x][y].flags = 0; 2720. 	   }  2721.  2722. 	    /*  2723. 	     * We must be sure that the parity of the coordinates for 2724. 	    * walkfrom is odd. But we must also take into account 2725. 	    * what direction was chosen. 2726. 	    */  2727. 	    if(!(x % 2)) { 2728. 		if (dir == W_EAST) 2729. 		   x++; 2730. 		else 2731. 		   x--; 2732. 2733. 		/* no need for IS_DOOR check; out of map bounds */ 2734. #ifndef WALLIFIED_MAZE 2735. 		levl[x][y].typ = CORR; 2736. #else 2737. 		levl[x][y].typ = ROOM; 2738. #endif 2739. 		levl[x][y].flags = 0; 2740. 	   }  2741.  2742. 	    if (!(y % 2)) { 2743. 		if (dir == W_SOUTH) 2744. 		   y++; 2745. 		else 2746. 		   y--; 2747. 	   }  2748.  2749. 	    walkfrom(x, y); 2750.    }  2751.     wallification(1, 0, COLNO-1, ROWNO-1, FALSE); 2752. 2753.     /*  2754.      * If there's a significant portion of maze unused by the special level, 2755.     * we don't want it empty. 2756.     *  2757.      * Makes the number of traps, monsters, etc. proportional 2758.     * to the size of the maze. 2759.     */  2760.     mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2); 2761. 2762.     for(x = 2; x < x_maze_max; x++) 2763. 	for(y = 0; y < y_maze_max; y++) 2764. 	   if(Map[x][y]) mapcount--; 2765. 2766.     if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) { 2767. 	   mapfact = (int) ((mapcount * 100L) / mapcountmax); 2768. 	   for(x = rnd((int) (20 * mapfact) / 100); x; x--) { 2769. 		   maze1xy(&mm, DRY); 2770. 		   (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,  2771. 							mm.x, mm.y, TRUE); 2772. 	   }  2773. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) { 2774. 		   maze1xy(&mm, DRY); 2775. 		   (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE); 2776. 	   }  2777. 	    for (x = rn2(2); x; x--) { 2778. 		maze1xy(&mm, DRY); 2779. 		(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS); 2780. 	   }  2781. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) { 2782. 		   maze1xy(&mm, WET|DRY); 2783. 		   (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS); 2784. 	   }  2785. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) { 2786. 		   maze1xy(&mm, DRY); 2787. 		   (void) mkgold(0L,mm.x,mm.y); 2788. 	   }  2789. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) { 2790. 		   int trytrap; 2791. 2792. 		    maze1xy(&mm, DRY); 2793. 		   trytrap = rndtrap; 2794. 		   if (sobj_at(BOULDER, mm.x, mm.y)) 2795. 			while (trytrap == PIT || trytrap == SPIKED_PIT || 2796. 				trytrap == TRAPDOOR || trytrap == HOLE) 2797. 			   trytrap = rndtrap; 2798. 		   (void) maketrap(mm.x, mm.y, trytrap); 2799. 	   }  2800.     }  2801.     return TRUE; 2802. } 2803.  2804. /*  2805.  * General loader 2806. */  2807.  2808. boolean 2809. load_special(name) 2810. const char *name; 2811. { 2812. 	dlb *fd; 2813. 	boolean result = FALSE; 2814. 	char c; 2815. struct version_info vers_info; 2816. 2817. 	fd = dlb_fopen_area(FILE_AREA_UNSHARE, name, RDBMODE); 2818. 	if (!fd) return FALSE; 2819. 2820. 	Fread((genericptr_t) &vers_info, sizeof vers_info, 1, fd); 2821. 	if (!check_version(&vers_info, name, TRUE)) 2822. 	   goto give_up; 2823. 2824. 	Fread((genericptr_t) &c, sizeof c, 1, fd); /* c Header */ 2825. 2826. 	switch (c) { 2827. 		case SP_LEV_ROOMS: 2828. 		   result = load_rooms(fd); 2829. 		   break; 2830. 		case SP_LEV_MAZE: 2831. 		   result = load_maze(fd); 2832. 		   break; 2833. 		default:	/* ??? */ 2834. 		    result = FALSE; 2835. 	} 2836.  give_up: 2837. 	(void)dlb_fclose(fd); 2838. 	return result; 2839. } 2840.  2841. /*sp_lev.c*/