Source:Mklev.c

Below is the full text to src/mklev.c from NetHack 3.4.3. To link to a particular line, write [[mklev.c#line123 ]], for example. 1.   /*	SCCS Id: @(#)mklev.c	3.4	2001/11/29	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.

5.   #include "hack.h"  6.    /* #define DEBUG */	/* uncomment to enable code debugging */ 7.    8.    #ifdef DEBUG 9.   # ifdef WIZARD 10.  #define debugpline	if (wizard) pline 11.  # else 12.  #define debugpline	pline 13.  # endif 14.  #endif 15.   16.   /* for UNIX, Rand #def'd to (long)lrand48 or (long)random */ 17.  /* croom->lx etc are schar (width <= int), so % arith ensures that */ 18.  /* conversion of result to int is reasonable */ 19.   20.    21.   STATIC_DCL void FDECL(mkfount,(int,struct mkroom *)); 22.  #ifdef SINKS 23.  STATIC_DCL void FDECL(mksink,(struct mkroom *)); 24.  #endif 25.  STATIC_DCL void FDECL(mkaltar,(struct mkroom *)); 26.  STATIC_DCL void FDECL(mkgrave,(struct mkroom *)); 27.  STATIC_DCL void NDECL(makevtele); 28.  STATIC_DCL void NDECL(clear_level_structures); 29.  STATIC_DCL void NDECL(makelevel); 30.  STATIC_DCL void NDECL(mineralize); 31.  STATIC_DCL boolean FDECL(bydoor,(XCHAR_P,XCHAR_P)); 32.  STATIC_DCL struct mkroom *FDECL(find_branch_room, (coord *)); 33.  STATIC_DCL struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P)); 34.  STATIC_DCL boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*)); 35.  STATIC_DCL void FDECL(makeniche,(int)); 36.  STATIC_DCL void NDECL(make_niches); 37.   38.   STATIC_PTR int FDECL( CFDECLSPEC do_comp,(const genericptr,const genericptr)); 39.   40.   STATIC_DCL void FDECL(dosdoor,(XCHAR_P,XCHAR_P,struct mkroom *,int)); 41.  STATIC_DCL void FDECL(join,(int,int,BOOLEAN_P)); 42.  STATIC_DCL void FDECL(do_room_or_subroom, (struct mkroom *,int,int,int,int, 43.  				       BOOLEAN_P,SCHAR_P,BOOLEAN_P,BOOLEAN_P)); 44.  STATIC_DCL void NDECL(makerooms); 45.  STATIC_DCL void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P)); 46.  STATIC_DCL void FDECL(mkinvpos, (XCHAR_P,XCHAR_P,int)); 47.  STATIC_DCL void FDECL(mk_knox_portal, (XCHAR_P,XCHAR_P)); 48.   49.   #define create_vault	create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE) 50.  #define init_vault	vault_x = -1 51.  #define do_vault	(vault_x != -1) 52.  static xchar		vault_x, vault_y; 53.  boolean goldseen; 54.  static boolean made_branch;	/* used only during level creation */ 55.   56.   /* Args must be (const genericptr) so that qsort will always be happy. */ 57.    58.   STATIC_PTR int CFDECLSPEC 59.  do_comp(vx,vy) 60.  const genericptr vx; 61.  const genericptr vy; 62.  {  63.   #ifdef LINT 64.  /* lint complains about possible pointer alignment problems, but we know 65.     that vx and vy are always properly aligned. Hence, the following 66.     bogus definition: 67.  */  68.   	return (vx == vy) ? 0 : -1; 69.   #else 70.  	register const struct mkroom *x, *y; 71.   72.   	x = (const struct mkroom *)vx; 73.  	y = (const struct mkroom *)vy; 74.  	if(x->lx < y->lx) return(-1); 75.  	return(x->lx > y->lx); 76.  #endif /* LINT */ 77.  }  78.    79.   STATIC_OVL void 80.  finddpos(cc, xl,yl,xh,yh) 81.  coord *cc; 82.  xchar xl,yl,xh,yh; 83.  {  84.   	register xchar x, y;  85. 86.  	x = (xl == xh) ? xl : (xl + rn2(xh-xl+1)); 87.  	y = (yl == yh) ? yl : (yl + rn2(yh-yl+1)); 88.  	if(okdoor(x, y)) 89.  		goto gotit; 90.   91.   	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) 92.  		if(okdoor(x, y)) 93.  			goto gotit; 94.   95.   	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) 96.  		if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR) 97.  			goto gotit; 98.  	/* cannot find something reasonable -- strange */ 99.  	x = xl; 100. 	y = yh; 101. gotit: 102. 	cc->x = x;  103. cc->y = y; 104. return; 105. }  106.   107.  void 108. sort_rooms 109. {  110.  #if defined(SYSV) || defined(DGUX) 111. 	qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), do_comp); 112. #else 113. 	qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), do_comp); 114. #endif 115. }  116.   117.  STATIC_OVL void 118. do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room) 119.     register struct mkroom *croom; 120.     int lowx, lowy; 121.     register int hix, hiy; 122.     boolean lit; 123.     schar rtype; 124.     boolean special; 125.     boolean is_room; 126. {  127.  	register int x, y;  128. struct rm *lev; 129.  130.  	/* locations might bump level edges in wall-less rooms */ 131. 	/* add/subtract 1 to allow for edge locations */ 132. 	if(!lowx) lowx++; 133. 	if(!lowy) lowy++; 134. 	if(hix >= COLNO-1) hix = COLNO-2; 135. 	if(hiy >= ROWNO-1) hiy = ROWNO-2; 136.  137.  	if(lit) { 138. 		for(x = lowx-1; x <= hix+1; x++) { 139. 			lev = &levl[x][max(lowy-1,0)]; 140. 			for(y = lowy-1; y <= hiy+1; y++) 141. 				lev++->lit = 1; 142. 		}  143.  		croom->rlit = 1; 144. 	} else 145. 		croom->rlit = 0; 146.  147.  	croom->lx = lowx; 148. 	croom->hx = hix; 149. 	croom->ly = lowy; 150. 	croom->hy = hiy; 151. 	croom->rtype = rtype; 152. 	croom->doorct = 0; 153. 	/* if we're not making a vault, doorindex will still be 0 154. 	 * if we are, we'll have problems adding niches to the previous room 155. 	 * unless fdoor is at least doorindex 156. 	 */  157.  	croom->fdoor = doorindex; 158. 	croom->irregular = FALSE; 159.  160.  	croom->nsubrooms = 0; 161. 	croom->sbrooms[0] = (struct mkroom *) 0; 162. 	if (!special) { 163. 	    for(x = lowx-1; x <= hix+1; x++) 164. 		for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) { 165. 		    levl[x][y].typ = HWALL; 166. 		    levl[x][y].horizontal = 1;	/* For open/secret doors. */ 167.  		}  168.  	    for(x = lowx-1; x <= hix+1; x += (hix-lowx+2)) 169. 		for(y = lowy; y <= hiy; y++) { 170. 		    levl[x][y].typ = VWALL; 171. 		    levl[x][y].horizontal = 0;	/* For open/secret doors. */ 172.  		}  173.  	    for(x = lowx; x <= hix; x++) { 174. 		lev = &levl[x][lowy]; 175. 		for(y = lowy; y <= hiy; y++) 176. 		    lev++->typ = ROOM; 177. 	    }  178.  	    if (is_room) { 179. 		levl[lowx-1][lowy-1].typ = TLCORNER; 180. 		levl[hix+1][lowy-1].typ = TRCORNER; 181. 		levl[lowx-1][hiy+1].typ = BLCORNER; 182. 		levl[hix+1][hiy+1].typ = BRCORNER; 183. 	    } else {	/* a subroom */ 184. 		wallification(lowx-1, lowy-1, hix+1, hiy+1); 185. 	    }  186.  	}  187.  }  188.   189.   190.  void 191. add_room(lowx, lowy, hix, hiy, lit, rtype, special) 192. register int lowx, lowy, hix, hiy; 193. boolean lit; 194. schar rtype; 195. boolean special; 196. {  197.  	register struct mkroom *croom; 198.  199.  	croom = &rooms[nroom]; 200. 	do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,  201.  					    rtype, special, (boolean) TRUE); 202. 	croom++; 203. 	croom->hx = -1; 204. 	nroom++; 205. }  206.   207.  void 208. add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special) 209. struct mkroom *proom; 210. register int lowx, lowy, hix, hiy; 211. boolean lit; 212. schar rtype; 213. boolean special; 214. {  215.  	register struct mkroom *croom; 216.  217.  	croom = &subrooms[nsubroom]; 218. 	do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,  219.  					    rtype, special, (boolean) FALSE); 220. 	proom->sbrooms[proom->nsubrooms++] = croom; 221. 	croom++; 222. 	croom->hx = -1; 223. 	nsubroom++; 224. }  225.   226.  STATIC_OVL void 227. makerooms 228. {  229.  	boolean tried_vault = FALSE; 230.  231.  	/* make rooms until satisfied */ 232. 	/* rnd_rect will returns 0 if no more rects are available... */ 233.  	while(nroom < MAXNROFROOMS && rnd_rect) { 234. 		if(nroom >= (MAXNROFROOMS/6) && rn2(2) && !tried_vault) { 235. 			tried_vault = TRUE; 236. 			if (create_vault) { 237. 				vault_x = rooms[nroom].lx; 238. 				vault_y = rooms[nroom].ly; 239. 				rooms[nroom].hx = -1; 240. 			}  241.  		} else 242. 		    if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1)) 243. 			return; 244. 	}  245.  	return; 246. }  247.   248.  STATIC_OVL void 249. join(a,b,nxcor) 250. register int a, b;  251. boolean nxcor; 252. {  253.  	coord cc,tt, org, dest; 254. 	register xchar tx, ty, xx, yy; 255. 	register struct mkroom *croom, *troom; 256. 	register int dx, dy; 257.  258.  	croom = &rooms[a]; 259. 	troom = &rooms[b]; 260.  261.  	/* find positions cc and tt for doors in croom and troom 262. 	   and direction for a corridor between them */ 263.  264.  	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return; 265. 	if(troom->lx > croom->hx) { 266. 		dx = 1; 267. 		dy = 0; 268. 		xx = croom->hx+1; 269. 		tx = troom->lx-1; 270. 		finddpos(&cc, xx, croom->ly, xx, croom->hy); 271. 		finddpos(&tt, tx, troom->ly, tx, troom->hy); 272. 	} else if(troom->hy < croom->ly) { 273. 		dy = -1; 274. 		dx = 0; 275. 		yy = croom->ly-1; 276. 		finddpos(&cc, croom->lx, yy, croom->hx, yy); 277. 		ty = troom->hy+1; 278. 		finddpos(&tt, troom->lx, ty, troom->hx, ty); 279. 	} else if(troom->hx < croom->lx) { 280. 		dx = -1; 281. 		dy = 0; 282. 		xx = croom->lx-1; 283. 		tx = troom->hx+1; 284. 		finddpos(&cc, xx, croom->ly, xx, croom->hy); 285. 		finddpos(&tt, tx, troom->ly, tx, troom->hy); 286. 	} else { 287. 		dy = 1; 288. 		dx = 0; 289. 		yy = croom->hy+1; 290. 		ty = troom->ly-1; 291. 		finddpos(&cc, croom->lx, yy, croom->hx, yy); 292. 		finddpos(&tt, troom->lx, ty, troom->hx, ty); 293. 	}  294.  	xx = cc.x;  295. yy = cc.y; 296. tx = tt.x - dx; 297. 	ty = tt.y - dy; 298. 	if(nxcor && levl[xx+dx][yy+dy].typ) 299. 		return; 300. 	if (okdoor(xx,yy) || !nxcor) 301. 	    dodoor(xx,yy,croom); 302.  303.  	org.x  = xx+dx; org.y  = yy+dy; 304. 	dest.x = tx; dest.y = ty; 305.  306.  	if (!dig_corridor(&org, &dest, nxcor, 307. 			level.flags.arboreal ? ROOM : CORR, STONE)) 308. 	    return; 309.  310.  	/* we succeeded in digging the corridor */ 311. 	if (okdoor(tt.x, tt.y) || !nxcor) 312. 	    dodoor(tt.x, tt.y, troom); 313.  314.  	if(smeq[a] < smeq[b]) 315. 		smeq[b] = smeq[a]; 316. 	else 317. 		smeq[a] = smeq[b]; 318. }  319.   320.  void 321. makecorridors 322. {  323.  	int a, b, i;  324. boolean any = TRUE; 325.  326.  	for(a = 0; a < nroom-1; a++) { 327. 		join(a, a+1, FALSE); 328. 		if(!rn2(50)) break; /* allow some randomness */ 329. 	}  330.  	for(a = 0; a < nroom-2; a++) 331. 	    if(smeq[a] != smeq[a+2]) 332. 		join(a, a+2, FALSE); 333. 	for(a = 0; any && a < nroom; a++) { 334. 	    any = FALSE; 335. 	    for(b = 0; b < nroom; b++) 336. 		if(smeq[a] != smeq[b]) { 337. 		    join(a, b, FALSE); 338. 		    any = TRUE; 339. 		}  340.  	}  341.  	if(nroom > 2) 342. 	    for(i = rn2(nroom) + 4; i; i--) { 343. 		a = rn2(nroom); 344. 		b = rn2(nroom-2); 345. 		if(b >= a) b += 2; 346. 		join(a, b, TRUE); 347. 	    }  348.  }  349.   350.  void 351. add_door(x,y,aroom) 352. register int x, y;  353. register struct mkroom *aroom; 354. {  355.  	register struct mkroom *broom; 356. 	register int tmp; 357.  358.  	aroom->doorct++; 359. 	broom = aroom+1; 360. 	if(broom->hx < 0) 361. 		tmp = doorindex; 362. 	else 363. 		for(tmp = doorindex; tmp > broom->fdoor; tmp--) 364. 			doors[tmp] = doors[tmp-1]; 365. 	doorindex++; 366. 	doors[tmp].x = x;  367. doors[tmp].y = y; 368. for(broom->hx >= 0; broom++) broom->fdoor++; 369. }  370.   371.  STATIC_OVL void 372. dosdoor(x,y,aroom,type) 373. register xchar x, y;  374. register struct mkroom *aroom; 375. register int type; 376. {  377.  	boolean shdoor = ((*in_rooms(x, y, SHOPBASE))? TRUE : FALSE); 378.  379.  	if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */ 380. 		type = DOOR; 381. 	levl[x][y].typ = type; 382. 	if(type == DOOR) { 383. 	    if(!rn2(3)) {      /* is it a locked door, closed, or a doorway? */ 384.  		if(!rn2(5)) 385. 		    levl[x][y].doormask = D_ISOPEN; 386. 		else if(!rn2(6)) 387. 		    levl[x][y].doormask = D_LOCKED; 388. 		else 389. 		    levl[x][y].doormask = D_CLOSED; 390.  391.  		if (levl[x][y].doormask != D_ISOPEN && !shdoor &&  392.  		    level_difficulty >= 5 && !rn2(25)) 393. 		    levl[x][y].doormask |= D_TRAPPED; 394. 	    } else 395. #ifdef STUPID 396. 		if (shdoor) 397. 			levl[x][y].doormask = D_ISOPEN; 398. 		else 399. 			levl[x][y].doormask = D_NODOOR; 400. #else 401. 		levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR); 402. #endif 403. 	    if(levl[x][y].doormask & D_TRAPPED) { 404. 		struct monst *mtmp; 405.  406.  		if (level_difficulty >= 9 && !rn2(5) &&  407.  		   !((mvitals[PM_SMALL_MIMIC].mvflags & G_GONE) && 408. 		     (mvitals[PM_LARGE_MIMIC].mvflags & G_GONE) && 409. 		     (mvitals[PM_GIANT_MIMIC].mvflags & G_GONE))) { 410. 		    /* make a mimic instead */ 411. 		    levl[x][y].doormask = D_NODOOR; 412. 		    mtmp = makemon(mkclass(S_MIMIC,0), x, y, NO_MM_FLAGS); 413. 		    if (mtmp) 414. 			set_mimic_sym(mtmp); 415. 		}  416.  	    }  417.  	    /* newsym(x,y); */ 418. 	} else { /* SDOOR */ 419. 		if(shdoor || !rn2(5))	levl[x][y].doormask = D_LOCKED; 420. 		else			levl[x][y].doormask = D_CLOSED; 421.  422.  		if(!shdoor && level_difficulty >= 4 && !rn2(20)) 423. 		    levl[x][y].doormask |= D_TRAPPED; 424. 	}  425.   426.  	add_door(x,y,aroom); 427. }  428.   429.  STATIC_OVL boolean 430. place_niche(aroom,dy,xx,yy) 431. register struct mkroom *aroom; 432. int *dy, *xx, *yy; 433. {  434.  	coord dd; 435.  436.  	if(rn2(2)) { 437. 	    *dy = 1; 438. 	    finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1); 439. 	} else { 440. 	    *dy = -1; 441. 	    finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1); 442. 	}  443.  	*xx = dd.x;  444. *yy = dd.y; 445. return((boolean)((isok(*xx,*yy+*dy) && levl[*xx][*yy+*dy].typ == STONE) 446. 	    && (isok(*xx,*yy-*dy) && !IS_POOL(levl[*xx][*yy-*dy].typ)  447.  				  && !IS_FURNITURE(levl[*xx][*yy-*dy].typ)))); 448. }  449.   450.  /* there should be one of these per trap, in the same order as trap.h */ 451. static NEARDATA const char *trap_engravings[TRAPNUM] = { 452. 			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 453. 			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 454. 			(char *)0, (char *)0, (char *)0, (char *)0, 455. 			/* 14..16: trap door, teleport, level-teleport */ 456. 			"Vlad was here", "ad aerarium", "ad aerarium", 457. 			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 458. 			(char *)0, 459. };  460.   461.  STATIC_OVL void 462. makeniche(trap_type) 463. int trap_type; 464. {  465.  	register struct mkroom *aroom; 466. 	register struct rm *rm; 467. 	register int vct = 8; 468. 	int dy, xx, yy; 469. 	register struct trap *ttmp; 470.  471.  	if(doorindex < DOORMAX) 472. 	  while(vct--) { 473. 	    aroom = &rooms[rn2(nroom)]; 474. 	    if(aroom->rtype != OROOM) continue;	/* not an ordinary room */ 475. 	    if(aroom->doorct == 1 && rn2(5)) continue; 476. 	    if(!place_niche(aroom,&dy,&xx,&yy)) continue; 477.  478.  	    rm = &levl[xx][yy+dy]; 479. 	    if(trap_type || !rn2(4)) { 480.  481.  		rm->typ = SCORR; 482. 		if(trap_type) { 483. 		    if((trap_type == HOLE || trap_type == TRAPDOOR)  484.  			&& !Can_fall_thru(&u.uz)) 485. 			trap_type = ROCKTRAP; 486. 		    ttmp = maketrap(xx, yy+dy, trap_type); 487. 		    if (ttmp) { 488. 			if (trap_type != ROCKTRAP) ttmp->once = 1; 489. 			if (trap_engravings[trap_type]) { 490. 			    make_engr_at(xx, yy-dy,  491.  				     trap_engravings[trap_type], 0L, DUST); 492. 			    wipe_engr_at(xx, yy-dy, 5); /* age it a little */ 493. 			}  494.  		    }  495.  		}  496.  		dosdoor(xx, yy, aroom, SDOOR); 497. 	    } else { 498. 		rm->typ = CORR; 499. 		if(rn2(7)) 500. 		    dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); 501. 		else { 502. 		    if (!level.flags.noteleport) 503. 			(void) mksobj_at(SCR_TELEPORTATION,  504.  					 xx, yy+dy, TRUE, FALSE); 505. 		    if (!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE); 506. 		}  507.  	    }  508.  	    return; 509. 	}  510.  }  511.   512.  STATIC_OVL void 513. make_niches 514. {  515.  	register int ct = rnd((nroom>>1) + 1), dep = depth(&u.uz); 516.  517.  	boolean	ltptr = (!level.flags.noteleport && dep > 15), 518. 		vamp = (dep > 5 && dep < 25); 519.  520.  	while(ct--) { 521. 		if (ltptr && !rn2(6)) { 522. 			ltptr = FALSE; 523. 			makeniche(LEVEL_TELEP); 524. 		} else if (vamp && !rn2(6)) { 525. 			vamp = FALSE; 526. 			makeniche(TRAPDOOR); 527. 		} else	makeniche(NO_TRAP); 528. 	}  529.  }  530.   531.  STATIC_OVL void 532. makevtele 533. {  534.  	makeniche(TELEP_TRAP); 535. }  536.   537.  /* clear out various globals that keep information on the current level. 538.  * some of this is only necessary for some types of levels (maze, normal,  539.   * special) but it's easier to put it all in one place than make sure 540.  * each type initializes what it needs to separately. 541.  */  542.  STATIC_OVL void 543. clear_level_structures 544. {  545.  	static struct rm zerorm = { cmap_to_glyph(S_stone), 546. 						0, 0, 0, 0, 0, 0, 0, 0 };  547.  	register int x,y; 548. 	register struct rm *lev; 549.  550.  	for(x=0; x<COLNO; x++) { 551. 	    lev = &levl[x][0]; 552. 	    for(y=0; y<ROWNO; y++) { 553. 		*lev++ = zerorm; 554. #ifdef MICROPORT_BUG 555. 		level.objects[x][y] = (struct obj *)0; 556. 		level.monsters[x][y] = (struct monst *)0; 557. #endif 558. 	    }  559.  	}  560.  #ifndef MICROPORT_BUG 561. 	(void) memset((genericptr_t)level.objects, 0, sizeof(level.objects)); 562. 	(void) memset((genericptr_t)level.monsters, 0, sizeof(level.monsters)); 563. #endif 564. 	level.objlist = (struct obj *)0; 565. 	level.buriedobjlist = (struct obj *)0; 566. 	level.monlist = (struct monst *)0; 567. 	level.damagelist = (struct damage *)0; 568.  569.  	level.flags.nfountains = 0; 570. 	level.flags.nsinks = 0; 571. 	level.flags.has_shop = 0; 572. 	level.flags.has_vault = 0; 573. 	level.flags.has_zoo = 0; 574. 	level.flags.has_court = 0; 575. 	level.flags.has_morgue = level.flags.graveyard = 0; 576. 	level.flags.has_beehive = 0; 577. 	level.flags.has_barracks = 0; 578. 	level.flags.has_temple = 0; 579. 	level.flags.has_swamp = 0; 580. 	level.flags.noteleport = 0; 581. 	level.flags.hardfloor = 0; 582. 	level.flags.nommap = 0; 583. 	level.flags.hero_memory = 1; 584. 	level.flags.shortsighted = 0; 585. 	level.flags.arboreal = 0; 586. 	level.flags.is_maze_lev = 0; 587. 	level.flags.is_cavernous_lev = 0; 588.  589.  	nroom = 0; 590. 	rooms[0].hx = -1; 591. 	nsubroom = 0; 592. 	subrooms[0].hx = -1; 593. 	doorindex = 0; 594. 	init_rect; 595. 	init_vault; 596. 	xdnstair = ydnstair = xupstair = yupstair = 0; 597. 	sstairs.sx = sstairs.sy = 0; 598. 	xdnladder = ydnladder = xupladder = yupladder = 0; 599. 	made_branch = FALSE; 600. 	clear_regions; 601. }  602.   603.  STATIC_OVL void 604. makelevel 605. {  606.  	register struct mkroom *croom, *troom; 607. 	register int tryct; 608. 	register int x, y;  609. struct monst *tmonst;	/* always put a web with a spider */ 610. 	branch *branchp; 611. 	int room_threshold; 612.  613.  	if(wiz1_level.dlevel == 0) init_dungeons; 614. 	oinit;	/* assign level dependent obj probabilities */ 615. 	clear_level_structures; 616.  617.  	{  618.  	    register s_level *slev = Is_special(&u.uz); 619.  620.  	    /* check for special levels */ 621. #ifdef REINCARNATION 622. 	    if (slev && !Is_rogue_level(&u.uz)) 623. #else 624. 	    if (slev) 625. #endif 626. 	    {  627.  		    makemaz(slev->proto); 628. 		    return; 629. 	    } else if (dungeons[u.uz.dnum].proto[0]) { 630. 		    makemaz(""); 631. 		    return; 632. 	    } else if (In_mines(&u.uz)) { 633. 		    makemaz("minefill"); 634. 		    return; 635. 	    } else if (In_quest(&u.uz)) { 636. 		    char	fillname[9]; 637. 		    s_level	*loc_lev; 638.  639.  		    Sprintf(fillname, "%s-loca", urole.filecode); 640. 		    loc_lev = find_level(fillname); 641.  642.  		    Sprintf(fillname, "%s-fil", urole.filecode); 643. 		    Strcat(fillname,  644.  			   (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b"); 645. 		    makemaz(fillname); 646. 		    return; 647. 	    } else if(In_hell(&u.uz) ||  648.  		  (rn2(5) && u.uz.dnum == medusa_level.dnum 649. 			  && depth(&u.uz) > depth(&medusa_level))) { 650. 		    makemaz(""); 651. 		    return; 652. 	    }  653.  	}  654.   655.  	/* otherwise, fall through - it's a "regular" level. */ 656.   657.  #ifdef REINCARNATION 658. 	if (Is_rogue_level(&u.uz)) { 659. 		makeroguerooms; 660. 		makerogueghost; 661. 	} else 662. #endif 663. 		makerooms; 664. 	sort_rooms; 665.  666.  	/* construct stairs (up and down in different rooms if possible) */ 667. 	croom = &rooms[rn2(nroom)]; 668. 	if (!Is_botlevel(&u.uz)) 669. 	     mkstairs(somex(croom), somey(croom), 0, croom);	/* down */ 670. 	if (nroom > 1) { 671. 	    troom = croom; 672. 	    croom = &rooms[rn2(nroom-1)]; 673. 	    if (croom == troom) croom++; 674. 	}  675.   676.  	if (u.uz.dlevel != 1) { 677. 	    xchar sx, sy; 678. 	    do { 679. 		sx = somex(croom); 680. 		sy = somey(croom); 681. 	    } while(occupied(sx, sy)); 682. 	    mkstairs(sx, sy, 1, croom);	/* up */ 683. 	}  684.   685.  	branchp = Is_branchlev(&u.uz);	/* possible dungeon branch */ 686. 	room_threshold = branchp ? 4 : 3; /* minimum number of rooms needed 687. 					     to allow a random special room */ 688. #ifdef REINCARNATION 689. 	if (Is_rogue_level(&u.uz)) goto skip0; 690. #endif 691. 	makecorridors; 692. 	make_niches; 693.  694.  	/* make a secret treasure vault, not connected to the rest */ 695. 	if(do_vault) { 696. 		xchar w,h; 697. #ifdef DEBUG 698. 		debugpline("trying to make a vault..."); 699. #endif 700. 		w = 1; 701. 		h = 1; 702. 		if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) { 703. 		    fill_vault: 704. 			add_room(vault_x, vault_y, vault_x+w,  705.  				 vault_y+h, TRUE, VAULT, FALSE); 706. 			level.flags.has_vault = 1; 707. 			++room_threshold; 708. 			fill_room(&rooms[nroom - 1], FALSE); 709. 			mk_knox_portal(vault_x+w, vault_y+h); 710. 			if(!level.flags.noteleport && !rn2(3)) makevtele; 711. 		} else if(rnd_rect && create_vault) { 712. 			vault_x = rooms[nroom].lx; 713. 			vault_y = rooms[nroom].ly; 714. 			if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) 715. 				goto fill_vault; 716. 			else 717. 				rooms[nroom].hx = -1; 718. 		}  719.  	}  720.   721.      {  722.  	register int u_depth = depth(&u.uz); 723.  724.  #ifdef WIZARD 725. 	if(wizard && nh_getenv("SHOPTYPE")) mkroom(SHOPBASE); else 726. #endif 727. 	if (u_depth > 1 &&  728.  	    u_depth < depth(&medusa_level) &&  729.  	    nroom >= room_threshold &&  730.  	    rn2(u_depth) < 3) mkroom(SHOPBASE); 731. 	else if (u_depth > 4 && !rn2(6)) mkroom(COURT); 732. 	else if (u_depth > 5 && !rn2(8) &&  733.  	   !(mvitals[PM_LEPRECHAUN].mvflags & G_GONE)) mkroom(LEPREHALL); 734. 	else if (u_depth > 6 && !rn2(7)) mkroom(ZOO); 735. 	else if (u_depth > 8 && !rn2(5)) mkroom(TEMPLE); 736. 	else if (u_depth > 9 && !rn2(5) &&  737.  	   !(mvitals[PM_KILLER_BEE].mvflags & G_GONE)) mkroom(BEEHIVE); 738. 	else if (u_depth > 11 && !rn2(6)) mkroom(MORGUE); 739. 	else if (u_depth > 12 && !rn2(8)) mkroom(ANTHOLE); 740. 	else if (u_depth > 14 && !rn2(4) &&  741.  	   !(mvitals[PM_SOLDIER].mvflags & G_GONE)) mkroom(BARRACKS); 742. 	else if (u_depth > 15 && !rn2(6)) mkroom(SWAMP); 743. 	else if (u_depth > 16 && !rn2(8) &&  744.  	   !(mvitals[PM_COCKATRICE].mvflags & G_GONE)) mkroom(COCKNEST); 745.     }  746.   747.  #ifdef REINCARNATION 748. skip0: 749. #endif 750. 	/* Place multi-dungeon branch. */ 751.  	place_branch(branchp, 0, 0); 752.  753.  	/* for each room: put things inside */ 754. 	for(croom = rooms; croom->hx > 0; croom++) { 755. 		if(croom->rtype != OROOM) continue; 756.  757.  		/* put a sleeping monster inside */ 758. 		/* Note: monster may be on the stairs. This cannot be 759. avoided: maybe the player fell through a trap door 760. 		   while a monster was on the stairs. Conclusion: 761. 		   we have to check for monsters on the stairs anyway. */ 762.   763.  		if(u.uhave.amulet || !rn2(3)) { 764. 		    x = somex(croom); y = somey(croom); 765. 		    tmonst = makemon((struct permonst *) 0, x,y,NO_MM_FLAGS); 766. 		    if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER] &&  767.  			    !occupied(x, y)) 768. 			(void) maketrap(x, y, WEB); 769. 		}  770.  		/* put traps and mimics inside */ 771. 		goldseen = FALSE; 772. 		x = 8 - (level_difficulty/6); 773. 		if (x <= 1) x = 2; 774. 		while (!rn2(x)) 775. 		    mktrap(0,0,croom,(coord*)0); 776. 		if (!goldseen && !rn2(3)) 777. 		    (void) mkgold(0L, somex(croom), somey(croom)); 778. #ifdef REINCARNATION 779. 		if(Is_rogue_level(&u.uz)) goto skip_nonrogue; 780. #endif 781. 		if(!rn2(10)) mkfount(0,croom); 782. #ifdef SINKS 783. 		if(!rn2(60)) mksink(croom); 784. #endif 785. 		if(!rn2(60)) mkaltar(croom); 786. 		x = 80 - (depth(&u.uz) * 2); 787. 		if (x < 2) x = 2; 788. 		if(!rn2(x)) mkgrave(croom); 789.  790.  		/* put statues inside */ 791. 		if(!rn2(20)) 792. 		    (void) mkcorpstat(STATUE, (struct monst *)0,  793.  				      (struct permonst *)0,  794.  				      somex(croom), somey(croom), TRUE); 795. 		/* put box/chest inside; 796. 		 *  40% chance for at least 1 box, regardless of number 797. 		 *  of rooms; about 5 - 7.5% for 2 boxes, least likely 798. 		 *  when few rooms; chance for 3 or more is neglible. 799. 		 */  800.  		if(!rn2(nroom * 5 / 2)) 801. 		    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,  802.  				     somex(croom), somey(croom), TRUE, FALSE); 803.  804.  		/* maybe make some graffiti */ 805. 		if(!rn2(27 + 3 * abs(depth(&u.uz)))) { 806. 		    char buf[BUFSZ]; 807. 		    const char *mesg = random_engraving(buf); 808. 		    if (mesg) { 809. 			do { 810. 			    x = somex(croom);  y = somey(croom); 811. 			} while(levl[x][y].typ != ROOM && !rn2(40)); 812. 			if (!(IS_POOL(levl[x][y].typ) || 813. 			      IS_FURNITURE(levl[x][y].typ))) 814. 			    make_engr_at(x, y, mesg, 0L, MARK); 815. 		    }  816.  		}  817.   818.  #ifdef REINCARNATION 819. 	skip_nonrogue: 820. #endif 821. 		if(!rn2(3)) { 822. 		    (void) mkobj_at(0, somex(croom), somey(croom), TRUE); 823. 		    tryct = 0; 824. 		    while(!rn2(5)) { 825. 			if(++tryct > 100) { 826. 			    impossible("tryct overflow4"); 827. 			    break; 828. 			}  829.  			(void) mkobj_at(0, somex(croom), somey(croom), TRUE); 830. 		    }  831.  		}  832.  	}  833.  }  834.   835.  /*  836.   *	Place deposits of minerals (gold and misc gems) in the stone 837.  *	surrounding the rooms on the map. 838.  *	Also place kelp in water. 839.  */  840.  STATIC_OVL void 841. mineralize 842. {  843.  	s_level *sp; 844. 	struct obj *otmp; 845. 	int goldprob, gemprob, x, y, cnt; 846.  847.   848.  	/* Place kelp, except on the plane of water */ 849. 	if (In_endgame(&u.uz)) return; 850. 	for (x = 2; x < (COLNO - 2); x++) 851. 	    for (y = 1; y < (ROWNO - 1); y++) 852. 		if ((levl[x][y].typ == POOL && !rn2(10)) ||  853.  			(levl[x][y].typ == MOAT && !rn2(30))) 854. 		    (void) mksobj_at(KELP_FROND, x, y, TRUE, FALSE); 855.  856.  	/* determine if it is even allowed; 857. 	   almost all special levels are excluded */ 858. 	if (In_hell(&u.uz) || In_V_tower(&u.uz) ||  859.  #ifdef REINCARNATION  860.  		Is_rogue_level(&u.uz) ||  861.  #endif  862.  		level.flags.arboreal ||  863.  		((sp = Is_special(&u.uz)) != 0 && !Is_oracle_level(&u.uz) 864. 					&& (!In_mines(&u.uz) || sp->flags.town) 865. 	    )) return; 866.  867.  	/* basic level-related probabilities */ 868. 	goldprob = 20 + depth(&u.uz) / 3; 869. 	gemprob = goldprob / 4; 870.  871.  	/* mines have ***MORE*** goodies - otherwise why mine? */ 872.  	if (In_mines(&u.uz)) { 873. 	    goldprob *= 2; 874. 	    gemprob *= 3; 875. 	} else if (In_quest(&u.uz)) { 876. 	    goldprob /= 4; 877. 	    gemprob /= 6; 878. 	}  879.   880.  	/*  881.  	 * Seed rock areas with gold and/or gems. 882. 	 * We use fairly low level object handling to avoid unnecessary 883. 	 * overhead from placing things in the floor chain prior to burial. 884. 	 */  885.  	for (x = 2; x < (COLNO - 2); x++) 886. 	  for (y = 1; y < (ROWNO - 1); y++) 887. 	    if (levl[x][y+1].typ != STONE) {	 /*  spot not eligible */ 888. 		y += 2;		/* next two spots aren't eligible either */ 889. 	    } else if (levl[x][y].typ != STONE) { /* this spot not eligible */ 890. 		y += 1;		/* next spot isn't eligible either */ 891. 	    } else if (!(levl[x][y].wall_info & W_NONDIGGABLE) &&  892.  		  levl[x][y-1].typ   == STONE &&  893.  		  levl[x+1][y-1].typ == STONE && levl[x-1][y-1].typ == STONE &&  894.  		  levl[x+1][y].typ   == STONE && levl[x-1][y].typ   == STONE &&  895.  		  levl[x+1][y+1].typ == STONE && levl[x-1][y+1].typ == STONE) { 896. 		if (rn2(1000) < goldprob) { 897. 		    if ((otmp = mksobj(GOLD_PIECE, FALSE, FALSE)) != 0) { 898. 			otmp->ox = x,  otmp->oy = y;  899. otmp->quan = 1L + rnd(goldprob * 3); 900. 			otmp->owt = weight(otmp); 901. 			if (!rn2(3)) add_to_buried(otmp); 902. 			else place_object(otmp, x, y); 903. 		    }  904.  		}  905.  		if (rn2(1000) < gemprob) { 906. 		    for (cnt = rnd(2 + dunlev(&u.uz) / 3); cnt > 0; cnt--) 907. 			if ((otmp = mkobj(GEM_CLASS, FALSE)) != 0) { 908. 			    if (otmp->otyp == ROCK) { 909. 				dealloc_obj(otmp);	/* discard it */ 910. 			    } else { 911. 				otmp->ox = x,  otmp->oy = y;  912. if (!rn2(3)) add_to_buried(otmp); 913. 				else place_object(otmp, x, y); 914. 			    }  915.  		    }  916.  		}  917.  	    }  918.  }  919.   920.  void 921. mklev 922. {  923.  	struct mkroom *croom; 924.  925.  	if(getbones) return; 926. 	in_mklev = TRUE; 927. 	makelevel; 928. 	bound_digging; 929. 	mineralize; 930. 	in_mklev = FALSE; 931. 	/* has_morgue gets cleared once morgue is entered; graveyard stays 932. 	   set (graveyard might already be set even when has_morgue is clear  933.  	   [see fixup_special], so don't update it unconditionally) */ 934. 	if (level.flags.has_morgue) 935. 	    level.flags.graveyard = 1; 936. 	if (!level.flags.is_maze_lev) { 937. 	    for (croom = &rooms[0]; croom != &rooms[nroom]; croom++) 938. #ifdef SPECIALIZATION 939. 		topologize(croom, FALSE); 940. #else 941. 		topologize(croom); 942. #endif 943. 	}  944.  	set_wall_state; 945. }  946.   947.  void 948. #ifdef SPECIALIZATION 949. topologize(croom, do_ordinary) 950. register struct mkroom *croom; 951. boolean do_ordinary; 952. #else 953. topologize(croom) 954. register struct mkroom *croom; 955. #endif 956. {  957.  	register int x, y, roomno = (croom - rooms) + ROOMOFFSET; 958. 	register int lowx = croom->lx, lowy = croom->ly; 959. 	register int hix = croom->hx, hiy = croom->hy; 960. #ifdef SPECIALIZATION 961. 	register schar rtype = croom->rtype; 962. #endif 963. 	register int subindex, nsubrooms = croom->nsubrooms; 964.  965.  	/* skip the room if already done; i.e. a shop handled out of order */ 966. 	/* also skip if this is non-rectangular (it _must_ be done already) */ 967. 	if ((int) levl[lowx][lowy].roomno == roomno || croom->irregular) 968. 	    return; 969. #ifdef SPECIALIZATION 970. # ifdef REINCARNATION 971. 	if (Is_rogue_level(&u.uz)) 972. 	    do_ordinary = TRUE;		/* vision routine helper */ 973. # endif 974. 	if ((rtype != OROOM) || do_ordinary) 975. #endif 976. 	{  977.  	    /* do innards first */ 978. 	    for(x = lowx; x <= hix; x++) 979. 		for(y = lowy; y <= hiy; y++) 980. #ifdef SPECIALIZATION 981. 		    if (rtype == OROOM) 982. 			levl[x][y].roomno = NO_ROOM; 983. 		    else 984. #endif 985. 			levl[x][y].roomno = roomno; 986. 	    /* top and bottom edges */ 987. 	    for(x = lowx-1; x <= hix+1; x++) 988. 		for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) { 989. 		    levl[x][y].edge = 1; 990. 		    if (levl[x][y].roomno) 991. 			levl[x][y].roomno = SHARED; 992. 		    else 993. 			levl[x][y].roomno = roomno; 994. 		}  995.  	    /* sides */ 996. 	    for(x = lowx-1; x <= hix+1; x += (hix-lowx+2)) 997. 		for(y = lowy; y <= hiy; y++) { 998. 		    levl[x][y].edge = 1; 999. 		    if (levl[x][y].roomno) 1000. 			levl[x][y].roomno = SHARED; 1001. 		   else 1002. 			levl[x][y].roomno = roomno; 1003. 		} 1004. 	}  1005. 	/* subrooms */ 1006. 	for (subindex = 0; subindex < nsubrooms; subindex++) 1007. #ifdef SPECIALIZATION 1008. 		topologize(croom->sbrooms[subindex], (rtype != OROOM)); 1009. #else 1010. 		topologize(croom->sbrooms[subindex]); 1011. #endif 1012. } 1013.  1014. /* Find an unused room for a branch location. */ 1015. STATIC_OVL struct mkroom * 1016. find_branch_room(mp) 1017.    coord *mp; 1018. { 1019.     struct mkroom *croom = 0; 1020. 1021.     if (nroom == 0) { 1022. 	mazexy(mp);		/* already verifies location */ 1023.    } else { 1024. 	/* not perfect - there may be only one stairway */ 1025. 	if(nroom > 2) { 1026. 	   int tryct = 0; 1027. 1028. 	    do  1029. croom = &rooms[rn2(nroom)]; 1030. 	   while((croom == dnstairs_room || croom == upstairs_room || 1031. 		 croom->rtype != OROOM) && (++tryct < 100)); 1032. 	} else 1033. 	   croom = &rooms[rn2(nroom)]; 1034. 1035. 	do { 1036. 	   if (!somexy(croom, mp)) 1037. 		impossible("Can't place branch!"); 1038. 	} while(occupied(mp->x, mp->y) || 1039. 	    (levl[mp->x][mp->y].typ != CORR && levl[mp->x][mp->y].typ != ROOM)); 1040.    }  1041.     return croom; 1042. } 1043.  1044. /* Find the room for (x,y). Return null if not in a room. */ 1045. STATIC_OVL struct mkroom * 1046. pos_to_room(x, y) 1047. xchar x, y; 1048. { 1049.     int i;  1050. struct mkroom *curr; 1051. 1052.     for (curr = rooms, i = 0; i < nroom; curr++, i++) 1053. 	if (inside_room(curr, x, y)) return curr;; 1054.    return (struct mkroom *) 0; 1055. } 1056.  1057.  1058. /* If given a branch, randomly place a special stair or portal. */ 1059. void 1060. place_branch(br, x, y) 1061. branch *br;	/* branch to place */ 1062. xchar x, y;	/* location */ 1063. { 1064. 	coord	      m;  1065. d_level	     *dest; 1066. 	boolean	     make_stairs; 1067. 	struct mkroom *br_room; 1068. 1069. 	/*  1070. 	 * Return immediately if there is no branch to make or we have 1071. 	 * already made one. This routine can be called twice when 1072. 	 * a special level is loaded that specifies an SSTAIR location 1073. 	 * as a favored spot for a branch. 1074. 	 */ 1075. 	if (!br || made_branch) return; 1076. 1077. 	if (!x) {	/* find random coordinates for branch */ 1078. 	   br_room = find_branch_room(&m); 1079. 	   x = m.x;  1080. y = m.y; 1081. } else { 1082. 	   br_room = pos_to_room(x, y); 1083. 	} 1084.  1085. 	if (on_level(&br->end1, &u.uz)) { 1086. 	   /* we're on end1 */ 1087. 	   make_stairs = br->type != BR_NO_END1; 1088. 	   dest = &br->end2; 1089. 	} else { 1090. 	   /* we're on end2 */ 1091. 	   make_stairs = br->type != BR_NO_END2; 1092. 	   dest = &br->end1; 1093. 	} 1094.  1095. 	if (br->type == BR_PORTAL) { 1096. 	   mkportal(x, y, dest->dnum, dest->dlevel); 1097. 	} else if (make_stairs) { 1098. 	   sstairs.sx = x;  1099. sstairs.sy = y; 1100. sstairs.up = (char) on_level(&br->end1, &u.uz) ? 1101. 					   br->end1_up : !br->end1_up; 1102. 	   assign_level(&sstairs.tolev, dest); 1103. 	   sstairs_room = br_room; 1104. 1105. 	    levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN; 1106. 	   levl[x][y].typ = STAIRS; 1107. 	} 1108. 	/*  1109. 	 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.  1110. 	 * make_stairs is false) since there is currently only one branch 1111. 	 * per level, if we failed once, we're going to fail again on the 1112. 	 * next call. 1113. 	 */ 1114. 	made_branch = TRUE; 1115. } 1116.  1117. STATIC_OVL boolean 1118. bydoor(x, y) 1119. register xchar x, y; 1120. { 1121. 	register int typ; 1122. 1123. 	if (isok(x+1, y)) { 1124. 		typ = levl[x+1][y].typ; 1125. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE; 1126. 	} 1127. 	if (isok(x-1, y)) { 1128. 		typ = levl[x-1][y].typ; 1129. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE; 1130. 	} 1131. 	if (isok(x, y+1)) { 1132. 		typ = levl[x][y+1].typ; 1133. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE; 1134. 	} 1135. 	if (isok(x, y-1)) { 1136. 		typ = levl[x][y-1].typ; 1137. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE; 1138. 	} 1139. 	return FALSE; 1140. } 1141.  1142. /* see whether it is allowable to create a door at [x,y] */ 1143. int 1144. okdoor(x,y) 1145. register xchar x, y; 1146. { 1147. 	register boolean near_door = bydoor(x, y); 1148. 1149. 	return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&  1150. 			doorindex < DOORMAX && !near_door); 1151. } 1152.  1153. void 1154. dodoor(x,y,aroom) 1155. register int x, y; 1156. register struct mkroom *aroom; 1157. { 1158. 	if(doorindex >= DOORMAX) { 1159. 		impossible("DOORMAX exceeded?"); 1160. 		return; 1161. 	} 1162.  1163. 	dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR); 1164. } 1165.  1166. boolean 1167. occupied(x, y) 1168. register xchar x, y; 1169. { 1170. 	return((boolean)(t_at(x, y)  1171. || IS_FURNITURE(levl[x][y].typ) 1172. 		|| is_lava(x,y) 1173. 		|| is_pool(x,y) 1174. 		|| invocation_pos(x,y) 1175. 		)); 1176. }  1177.  1178. /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */ 1179. /* if tm != null, make trap at that location */ 1180. void 1181. mktrap(num, mazeflag, croom, tm) 1182. register int num, mazeflag; 1183. register struct mkroom *croom; 1184. coord *tm; 1185. { 1186. 	register int kind; 1187. 	coord m; 1188. 1189. 	/* no traps in pools */ 1190. 	if (tm && is_pool(tm->x,tm->y)) return; 1191. 1192. 	if (num > 0 && num < TRAPNUM) { 1193. 	   kind = num; 1194. #ifdef REINCARNATION 1195. 	} else if (Is_rogue_level(&u.uz)) { 1196. 	   switch (rn2(7)) { 1197. 		default: kind = BEAR_TRAP; break; /* 0 */ 1198. 		case 1: kind = ARROW_TRAP; break; 1199. 		case 2: kind = DART_TRAP; break; 1200. 		case 3: kind = TRAPDOOR; break; 1201. 		case 4: kind = PIT; break; 1202. 		case 5: kind = SLP_GAS_TRAP; break; 1203. 		case 6: kind = RUST_TRAP; break; 1204. 	   }  1205. #endif 1206. 	} else if (Inhell && !rn2(5)) { 1207. 	   /* bias the frequency of fire traps in Gehennom */ 1208. 	   kind = FIRE_TRAP; 1209. 	} else { 1210. 	   unsigned lvl = level_difficulty; 1211. 1212. 	    do { 1213. 		kind = rnd(TRAPNUM-1); 1214. 		/* reject "too hard" traps */ 1215. 		switch (kind) { 1216. 		   case MAGIC_PORTAL: 1217. 			kind = NO_TRAP; break; 1218. 		   case ROLLING_BOULDER_TRAP: 1219. 		   case SLP_GAS_TRAP: 1220. 			if (lvl < 2) kind = NO_TRAP; break; 1221. 		   case LEVEL_TELEP: 1222. 			if (lvl < 5 || level.flags.noteleport) 1223. 			   kind = NO_TRAP; break; 1224. 		   case SPIKED_PIT: 1225. 			if (lvl < 5) kind = NO_TRAP; break; 1226. 		   case LANDMINE: 1227. 			if (lvl < 6) kind = NO_TRAP; break; 1228. 		   case WEB: 1229. 			if (lvl < 7) kind = NO_TRAP; break; 1230. 		   case STATUE_TRAP: 1231. 		   case POLY_TRAP: 1232. 			if (lvl < 8) kind = NO_TRAP; break; 1233. 		   case FIRE_TRAP: 1234. 			if (!Inhell) kind = NO_TRAP; break; 1235. 		   case TELEP_TRAP: 1236. 			if (level.flags.noteleport) kind = NO_TRAP; break; 1237. 		   case HOLE: 1238. 			/* make these much less often than other traps */ 1239. 			if (rn2(7)) kind = NO_TRAP; break; 1240. 		} 1241. 	    } while (kind == NO_TRAP); 1242. 	} 1243.  1244. 	if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz)) 1245. 		kind = ROCKTRAP; 1246. 1247. 	if (tm) 1248. 	   m = *tm; 1249. 	else { 1250. 	   register int tryct = 0; 1251. 	   boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT ||  1252. 				     kind == TRAPDOOR || kind == HOLE); 1253. 1254. 	    do { 1255. 		if (++tryct > 200) 1256. 		   return; 1257. 		if (mazeflag) 1258. 		   mazexy(&m); 1259. 		else if (!somexy(croom,&m)) 1260. 		   return; 1261. 	   } while (occupied(m.x, m.y) ||  1262. 			(avoid_boulder && sobj_at(BOULDER, m.x, m.y))); 1263. 	} 1264.  1265. 	(void) maketrap(m.x, m.y, kind); 1266. 	if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], 1267. 						m.x, m.y, NO_MM_FLAGS); 1268. } 1269.  1270. void 1271. mkstairs(x, y, up, croom) 1272. xchar x, y; 1273. char up; 1274. struct mkroom *croom; 1275. { 1276. 	if (!x) { 1277. 	   impossible("mkstairs:  bogus stair attempt at <%d,%d>", x, y); 1278. 	   return; 1279. 	} 1280.  1281. 	/*  1282. 	 * We can't make a regular stair off an end of the dungeon. This 1283. 	 * attempt can happen when a special level is placed at an end and 1284. 	 * has an up or down stair specified in its description file. 1285. 	 */ 1286. 	if ((dunlev(&u.uz) == 1 && up) ||  1287. 			(dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up)) 1288. 	   return; 1289. 1290. 	if(up) { 1291. 		xupstair = x; 1292. yupstair = y; 1293. upstairs_room = croom; 1294. 	} else { 1295. 		xdnstair = x; 1296. ydnstair = y; 1297. dnstairs_room = croom; 1298. 	} 1299.  1300. 	levl[x][y].typ = STAIRS; 1301. 	levl[x][y].ladder = up ? LA_UP : LA_DOWN; 1302. } 1303.  1304. STATIC_OVL 1305. void 1306. mkfount(mazeflag,croom) 1307. register int mazeflag; 1308. register struct mkroom *croom; 1309. { 1310. 	coord m;  1311. register int tryct = 0; 1312. 1313. 	do { 1314. 	   if(++tryct > 200) return; 1315. 	   if(mazeflag) 1316. 		mazexy(&m); 1317. 	   else 1318. 		if (!somexy(croom, &m)) 1319. 		   return; 1320. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y)); 1321. 1322. 	/* Put a fountain at m.x, m.y */ 1323. 	levl[m.x][m.y].typ = FOUNTAIN; 1324. 	/* Is it a "blessed" fountain? (affects drinking from fountain) */ 1325. 	if(!rn2(7)) levl[m.x][m.y].blessedftn = 1; 1326. 1327. 	level.flags.nfountains++; 1328. } 1329.  1330. #ifdef SINKS 1331. STATIC_OVL void 1332. mksink(croom) 1333. register struct mkroom *croom; 1334. { 1335. 	coord m;  1336. register int tryct = 0; 1337. 1338. 	do { 1339. 	   if(++tryct > 200) return; 1340. 	   if (!somexy(croom, &m)) 1341. 		return; 1342. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y)); 1343. 1344. 	/* Put a sink at m.x, m.y */ 1345. 	levl[m.x][m.y].typ = SINK; 1346. 1347. 	level.flags.nsinks++; 1348. } 1349. #endif /* SINKS */ 1350. 1351.  1352. STATIC_OVL void 1353. mkaltar(croom) 1354. register struct mkroom *croom; 1355. { 1356. 	coord m;  1357. register int tryct = 0; 1358. 	aligntyp al; 1359. 1360. 	if (croom->rtype != OROOM) return; 1361. 1362. 	do { 1363. 	   if(++tryct > 200) return; 1364. 	   if (!somexy(croom, &m)) 1365. 		return; 1366. 	} while (occupied(m.x, m.y) || bydoor(m.x, m.y)); 1367. 1368. 	/* Put an altar at m.x, m.y */ 1369. 	levl[m.x][m.y].typ = ALTAR; 1370. 1371. 	/* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */ 1372. 	al = rn2((int)A_LAWFUL+2) - 1; 1373. 	levl[m.x][m.y].altarmask = Align2amask( al ); 1374. } 1375.  1376. static void 1377. mkgrave(croom) 1378. struct mkroom *croom; 1379. { 1380. 	coord m;  1381. register int tryct = 0; 1382. 	register struct obj *otmp; 1383. 	boolean dobell = !rn2(10); 1384. 1385.  1386. 	if(croom->rtype != OROOM) return; 1387. 1388. 	do { 1389. 	   if(++tryct > 200) return; 1390. 	   if (!somexy(croom, &m)) 1391. 		return; 1392. 	} while (occupied(m.x, m.y) || bydoor(m.x, m.y)); 1393. 1394. 	/* Put a grave at m.x, m.y */ 1395. 	make_grave(m.x, m.y, dobell ? "Saved by the bell!" : (char *) 0); 1396. 1397. 	/* Possibly fill it with objects */ 1398. 	if (!rn2(3)) (void) mkgold(0L, m.x, m.y); 1399. 	for (tryct = rn2(5); tryct; tryct--) { 1400. 	   otmp = mkobj(RANDOM_CLASS, TRUE); 1401. 	   if (!otmp) return; 1402. 	   curse(otmp); 1403. 	   otmp->ox = m.x;  1404. otmp->oy = m.y; 1405. add_to_buried(otmp); 1406. 	} 1407.  1408. 	/* Leave a bell, in case we accidentally buried someone alive */ 1409. 	if (dobell) (void) mksobj_at(BELL, m.x, m.y, TRUE, FALSE); 1410. 	return; 1411. } 1412.  1413.  1414. /* maze levels have slightly different constraints from normal levels */ 1415. #define x_maze_min 2 1416. #define y_maze_min 2 1417. /* 1418.  * Major level transmutation: add a set of stairs (to the Sanctum) after 1419. * an earthquake that leaves behind a a new topology, centered at inv_pos. 1420. * Assumes there are no rooms within the invocation area and that inv_pos 1421. * is not too close to the edge of the map. Also assume the hero can see, 1422. * which is guaranteed for normal play due to the fact that sight is needed 1423. * to read the Book of the Dead. 1424. */  1425. void 1426. mkinvokearea 1427. { 1428.     int dist; 1429.    xchar xmin = inv_pos.x, xmax = inv_pos.x;  1430. xchar ymin = inv_pos.y, ymax = inv_pos.y; 1431. register xchar i; 1432. 1433.    pline_The("floor shakes violently under you!"); 1434.    pline_The("walls around you begin to bend and crumble!"); 1435.    display_nhwindow(WIN_MESSAGE, TRUE); 1436. 1437.     mkinvpos(xmin, ymin, 0);		/* middle, before placing stairs */ 1438. 1439.     for(dist = 1; dist < 7; dist++) { 1440. 	xmin--; xmax++; 1441. 1442. 	/* top and bottom */ 1443. 	if(dist != 3) { /* the area is wider that it is high */ 1444. 	   ymin--; ymax++; 1445. 	   for(i = xmin+1; i < xmax; i++) { 1446. 		mkinvpos(i, ymin, dist); 1447. 		mkinvpos(i, ymax, dist); 1448. 	   }  1449. 	}  1450.  1451. 	/* left and right */ 1452. 	for(i = ymin; i <= ymax; i++) { 1453. 	   mkinvpos(xmin, i, dist); 1454. 	   mkinvpos(xmax, i, dist); 1455. 	} 1456.  1457. 	flush_screen(1);	/* make sure the new glyphs shows up */ 1458. 	delay_output; 1459.    }  1460.  1461.     You("are standing at the top of a stairwell leading down!"); 1462.    mkstairs(u.ux, u.uy, 0, (struct mkroom *)0); /* down */ 1463.    newsym(u.ux, u.uy); 1464.    vision_full_recalc = 1;	/* everything changed */ 1465. } 1466.  1467. /* Change level topology. Boulders in the vicinity are eliminated. 1468. * Temporarily overrides vision in the name of a nice effect. 1469. */  1470. STATIC_OVL void 1471. mkinvpos(x,y,dist) 1472. xchar x,y; 1473. int dist; 1474. { 1475.     struct trap *ttmp; 1476.    struct obj *otmp; 1477.    boolean make_rocks; 1478.    register struct rm *lev = &levl[x][y]; 1479. 1480.     /* clip at existing map borders if necessary */ 1481.    if (!within_bounded_area(x, y, x_maze_min + 1, y_maze_min + 1, 1482. 				  x_maze_max - 1, y_maze_max - 1)) { 1483. 	/* only outermost 2 columns and/or rows may be truncated due to edge */ 1484. 	if (dist < (7 - 2)) 1485. 	   panic("mkinvpos: <%d,%d> (%d) off map edge!", x, y, dist); 1486. 	return; 1487.    }  1488.  1489.     /* clear traps */ 1490.    if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp); 1491. 1492.     /* clear boulders; leave some rocks for non-{moat|trap} locations */ 1493.    make_rocks = (dist != 1 && dist != 4 && dist != 5) ? TRUE : FALSE; 1494.    while ((otmp = sobj_at(BOULDER, x, y)) != 0) { 1495. 	if (make_rocks) { 1496. 	   fracture_rock(otmp); 1497. 	   make_rocks = FALSE;		/* don't bother with more rocks */ 1498. 	} else { 1499. 	   obj_extract_self(otmp); 1500. 	   obfree(otmp, (struct obj *)0); 1501. 	} 1502.     }  1503.     unblock_point(x,y);	/* make sure vision knows this location is open */ 1504. 1505.     /* fake out saved state */ 1506.    lev->seenv = 0; 1507.    lev->doormask = 0; 1508.    if(dist < 6) lev->lit = TRUE; 1509.    lev->waslit = TRUE; 1510.    lev->horizontal = FALSE; 1511.    viz_array[y][x] = (dist < 6 ) ? 1512. 	(IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */ 1513. 	COULD_SEE; 1514. 1515.     switch(dist) { 1516.    case 1: /* fire traps */ 1517. 	if (is_pool(x,y)) break; 1518. 	lev->typ = ROOM; 1519. 	ttmp = maketrap(x, y, FIRE_TRAP); 1520. 	if (ttmp) ttmp->tseen = TRUE; 1521. 	break; 1522.    case 0: /* lit room locations */ 1523.    case 2: 1524.    case 3: 1525.    case 6: /* unlit room locations */ 1526. 	lev->typ = ROOM; 1527. 	break; 1528.    case 4: /* pools (aka a wide moat) */ 1529.    case 5: 1530. 	lev->typ = MOAT; 1531. 	/* No kelp! */ 1532. 	break; 1533.    default: 1534. 	impossible("mkinvpos called with dist %d", dist); 1535. 	break; 1536.    }  1537.  1538.     /* display new value of position; could have a monster/object on it */ 1539.    newsym(x,y); 1540. } 1541.  1542. /*  1543.  * The portal to Ludios is special. The entrance can only occur within a 1544. * vault in the main dungeon at a depth greater than 10. The Ludios branch 1545. * structure reflects this by having a bogus "source" dungeon:  the value 1546. * of n_dgns (thus, Is_branchlev will never find it). 1547. *  1548.  * Ludios will remain isolated until the branch is corrected by this function. 1549. */  1550. STATIC_OVL void 1551. mk_knox_portal(x, y) 1552. xchar x, y; 1553. { 1554. 	extern int n_dgns;		/* from dungeon.c */ 1555. 	d_level *source; 1556. 	branch *br; 1557. 	schar u_depth; 1558. 1559. 	br = dungeon_branch("Fort Ludios"); 1560. 	if (on_level(&knox_level, &br->end1)) { 1561. 	   source = &br->end2; 1562. 	} else { 1563. 	   /* disallow Knox branch on a level with one branch already */ 1564. 	   if(Is_branchlev(&u.uz)) 1565. 		return; 1566. 	   source = &br->end1; 1567. 	} 1568.  1569. 	/* Already set or 2/3 chance of deferring until a later level. */ 1570. 	if (source->dnum < n_dgns || (rn2(3) 1571. #ifdef WIZARD 1572. 				     && !wizard 1573. #endif 1574. 				     )) return; 1575. 1576. 	if (! (u.uz.dnum == oracle_level.dnum	    /* in main dungeon */ 1577. 		&& !at_dgn_entrance("The Quest")   /* but not Quest's entry */ 1578. 		&& (u_depth = depth(&u.uz)) > 10   /* beneath 10 */ 1579. 		&& u_depth < depth(&medusa_level))) /* and above Medusa */ 1580. 	   return; 1581. 1582. 	/* Adjust source to be current level and re-insert branch. */ 1583. 	*source = u.uz; 1584. 	insert_branch(br, TRUE); 1585. 1586. #ifdef DEBUG 1587. 	pline("Made knox portal."); 1588. #endif 1589. 	place_branch(br, x, y); 1590. } 1591.  1592. /*mklev.c*/