abstract
| - 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 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 546. lev = &levl[x][0]; 547. for(y=0; 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) { /* 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*/
|