Source:NetHack 3.3.0/sp lev.c

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