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