Source:NetHack 3.4.0/sp lev.c

Below is the full text to sp_lev.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/sp_lev.c#line123 ]], for example.

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