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