Source:NetHack 3.1.0/sp lev.c

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