Source:NetHack 3.2.0/sp lev.c

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