| abstract
| - Below is the full text to dungeon.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/dungeon.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)dungeon.c 3.1 93/01/17 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "dgn_file.h" 7. 8. #ifdef OVL1 9. 10. #define DUNGEON_FILE "dungeon" 11. #if defined(MICRO) && !defined(AMIGA) 12. # define RDMODE "rb" 13. #else 14. # define RDMODE "r" 15. #endif 16. 17. #ifdef MULDGN 18. #define X_START "x-start" 19. #define X_LOCATE "x-locate" 20. #define X_GOAL "x-goal" 21. #endif 22. 23. struct proto_dungeon { 24. struct tmpdungeon tmpdungeon[MAXDUNGEON]; 25. struct tmplevel tmplevel[LEV_LIMIT]; 26. s_level *final_lev[LEV_LIMIT]; /* corresponding level pointers */ 27. struct tmpbranch tmpbranch[BRANCH_LIMIT]; 28. 29. int start; /* starting index of current dungeon sp levels */ 30. int n_levs; /* number of tmplevel entries */ 31. int n_brs; /* number of tmpbranch entries */ 32. }; 33. 34. int n_dgns; /* number of dungeons (used here, */ 35. /* and mklev.c) */ 36. static branch *branches = (branch *) 0; /* dungeon branch list */ 37. 38. static void FDECL(Fread, (genericptr_t, int, int, FILE *)); 39. static xchar FDECL(dname_to_dnum, (const char *)); 40. static int FDECL(find_branch, (const char *, struct proto_dungeon *)); 41. static xchar FDECL(parent_dnum, (const char *, struct proto_dungeon *)); 42. static int FDECL(level_range, (XCHAR_P,int,int,int,struct proto_dungeon *,int *)); 43. static xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *)); 44. static int FDECL(correct_branch_type, (struct tmpbranch *)); 45. static branch *FDECL(add_branch, (int, int, struct proto_dungeon *)); 46. static void FDECL(add_level, (s_level *)); 47. static void FDECL(init_level, (int,int,struct proto_dungeon *)); 48. static int FDECL(possible_places, (int, boolean *, struct proto_dungeon *)); 49. static xchar FDECL(pick_level, (boolean *, int)); 50. static boolean FDECL(place_level, (int, struct proto_dungeon *)); 51. #ifdef WIZARD 52. static const char *FDECL(br_string, (int)); 53. static void FDECL(print_branch, (winid, int, int, int)); 54. #endif 55. 56. #ifdef DEBUG 57. #define DD dungeons[i] 58. static void NDECL(dumpit); 59. 60. static void 61. dumpit() 62. { 63. int i; 64. s_level *x; 65. branch *br; 66. 67. for(i = 0; i < n_dgns; i++) { 68. fprintf(stderr, "
#%d \"%s\" (%s):
", i, 69. DD.dname, DD.proto); 70. fprintf(stderr, " num_dunlevs %d, dunlev_ureached %d
", 71. DD.num_dunlevs, DD.dunlev_ureached); 72. fprintf(stderr, " depth_start %d, ledger_start %d
", 73. DD.depth_start, DD.ledger_start); 74. fprintf(stderr, " flags:%s%s%s
", 75. DD.flags.rogue_like ? " rogue_like" : "", 76. DD.flags.maze_like ? " maze_like" : "", 77. DD.flags.hellish ? " hellish" : ""); 78. getchar(); 79. } 80. fprintf(stderr,"
Special levels:
"); 81. for(x = sp_levchn; x; x = x->next) { 82. fprintf(stderr, "%s (%d): ", x->proto, x->rndlevs); 83. fprintf(stderr, "on %d, %d; ", x->dlevel.dnum, x->dlevel.dlevel); 84. fprintf(stderr, "flags:%s%s%s%s
", 85. x->flags.rogue_like ? " rogue_like" : "", 86. x->flags.maze_like ? " maze_like" : "", 87. x->flags.hellish ? " hellish" : "", 88. x->flags.town ? " town" : ""); 89. getchar(); 90. } 91. fprintf(stderr,"
Branches:
"); 92. for (br = branches; br; br = br->next) { 93. fprintf(stderr, "%d: %s, end1 %d %d, end2 %d %d, %s
", 94. br->id, 95. br->type == BR_STAIR ? "stair" : 96. br->type == BR_NO_END1 ? "no end1" : 97. br->type == BR_NO_END2 ? "no end2" : 98. br->type == BR_PORTAL ? "portal" : 99. "unknown", 100. br->end1.dnum, br->end1.dlevel, 101. br->end2.dnum, br->end2.dlevel, 102. br->end1_up ? "end1 up" : "end1 down"); 103. } 104. getchar(); 105. fprintf(stderr,"
Done
"); 106. getchar(); 107. } 108. #endif 109. 110. /* Save the dungeon structures. */ 111. void 112. save_dungeon(fd) 113. int fd; 114. { 115. branch *curr; 116. int count; 117. 118. bwrite(fd, (genericptr_t) &n_dgns, sizeof(n_dgns)); 119. bwrite(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned)n_dgns); 120. bwrite(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology); 121. bwrite(fd, (genericptr_t) tune, sizeof tune); 122. 123. for (count = 0, curr = branches; curr; curr = curr->next) 124. count++; 125. 126. bwrite(fd, (genericptr_t) &count, sizeof(count)); 127. for (curr = branches; curr; curr = curr->next) 128. bwrite(fd, (genericptr_t) curr, sizeof(branch)); 129. } 130. 131. /* Restore the dungeon structures. */ 132. void 133. restore_dungeon(fd) 134. int fd; 135. { 136. branch *curr, *last; 137. int count, i; 138. 139. mread(fd, (genericptr_t) &n_dgns, sizeof(n_dgns)); 140. mread(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned)n_dgns); 141. mread(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology); 142. mread(fd, (genericptr_t) tune, sizeof tune); 143. 144. last = branches = (branch *) 0; 145. 146. mread(fd, (genericptr_t) &count, sizeof(count)); 147. for (i = 0; i < count; i++) { 148. curr = (branch *) alloc(sizeof(branch)); 149. mread(fd, (genericptr_t) curr, sizeof(branch)); 150. curr->next = (branch *) 0; 151. if (last) 152. last->next = curr; 153. else 154. branches = curr; 155. last = curr; 156. } 157. } 158. 159. static void 160. Fread(ptr, size, nitems, stream) 161. genericptr_t ptr; 162. int size, nitems; 163. FILE *stream; 164. { 165. int cnt; 166. 167. if((cnt = fread(ptr, size, nitems, stream)) != nitems) { 168. 169. panic("PREMATURE EOF ON DUNGEON DESCRIPTION FILE!
Expected %d bytes - got %d
", 170. (size * nitems), (size * cnt)); 171. terminate(1); 172. } 173. } 174. 175. static xchar 176. dname_to_dnum(s) 177. const char *s; 178. { 179. xchar i; 180. 181. for (i = 0; i < n_dgns; i++) 182. if (!strcmp(dungeons[i].dname, s)) return i; 183. 184. panic("Couldn't resolve dungeon number for name \"%s\".", s); 185. #if defined(LINT) || defined(GCC_WARN) 186. return (xchar)0; 187. #endif 188. } 189. 190. s_level * 191. find_level(s) 192. const char *s; 193. { 194. s_level *curr; 195. for(curr = sp_levchn; curr; curr = curr->next) 196. if(!strcmp(s, curr->proto)) break; 197. return curr; 198. } 199. 200. /* Find the branch that links the named dungeon. */ 201. static int 202. find_branch(s, pd) 203. const char *s; /* dungeon name */ 204. struct proto_dungeon *pd; 205. { 206. int i; 207. for (i = 0; i < pd->n_brs; i++) 208. if (!strcmp(pd->tmpbranch[i].name, s)) break; 209. if (i == pd->n_brs) panic("find_branch: can't find %s", s); 210. return i; 211. } 212. 213. 214. /* 215. * Find the "parent" by searching the prototype branch list for the branch 216. * listing, then figuring out to which dungeon it belongs. 217. */ 218. static xchar 219. parent_dnum(s, pd) 220. const char *s; /* dungeon name */ 221. struct proto_dungeon *pd; 222. { 223. int i; 224. xchar pdnum; 225. 226. i = find_branch(s, pd); 227. /* 228. * Got branch, now find parent dungeon. Stop if we have reached 229. * "this" dungeon (if we haven't found it by now it is an error). 230. */ 231. for (pdnum = 0; strcmp(pd->tmpdungeon[pdnum].name, s); pdnum++) 232. if ((i -= pd->tmpdungeon[pdnum].branches) < 0) 233. return(pdnum); 234. 235. panic("parent_dnum: couldn't resolve branch."); 236. #if defined(LINT) || defined(GCC_WARN) 237. return (xchar)0; 238. #endif 239. } 240. 241. /* 242. * Return a starting point and number of successive positions a level 243. * or dungeon entrance can occupy. 244. * 245. * Note: This follows the acouple (instead of the rcouple) rules for a 246. * negative random component (rand < 0). These rules are found 247. * in dgn_comp.y. The acouple [absolute couple] section says that 248. * a negative random component means from the (adjusted) base to the 249. * end of the dungeon. 250. */ 251. static int 252. level_range(dgn, base, rand, chain, pd, adjusted_base) 253. xchar dgn; 254. int base, rand, chain; 255. struct proto_dungeon *pd; 256. int *adjusted_base; 257. { 258. int lmax = dungeons[dgn].num_dunlevs; 259. 260. if (chain >= 0) { /* relative to a special level */ 261. s_level *levtmp = pd->final_lev[chain]; 262. if (!levtmp) panic("level_range: empty chain level!"); 263. 264. base += levtmp->dlevel.dlevel; 265. } else { /* absolute in the dungeon */ 266. /* from end of dungeon */ 267. if (base < 0) base = (lmax + base + 1); 268. } 269. 270. if (base < 1 || base > lmax) 271. panic("level_range: base value out of range"); 272. 273. *adjusted_base = base; 274. 275. if (rand == -1) { /* from base to end of dungeon */ 276. return (lmax - base + 1); 277. } else if (rand) { 278. /* make sure we don't run off the end of the dungeon */ 279. return (((base + rand - 1) > lmax) ? lmax-base+1 : rand); 280. } /* else only one choice */ 281. return 1; 282. } 283. 284. static xchar 285. parent_dlevel(s, pd) 286. const char *s; 287. struct proto_dungeon *pd; 288. { 289. int i, num, base; 290. 291. i = find_branch(s, pd); 292. num = level_range(parent_dnum(s, pd), pd->tmpbranch[i].lev.base, 293. pd->tmpbranch[i].lev.rand, 294. pd->tmpbranch[i].chain, 295. pd, &base); 296. return (xchar) rn1(num,base); 297. } 298. 299. /* Convert from the temporary branch type to the dungeon branch type. */ 300. static int 301. correct_branch_type(tbr) 302. struct tmpbranch *tbr; 303. { 304. switch (tbr->type) { 305. case TBR_STAIR: return BR_STAIR; 306. case TBR_NO_UP: return tbr->up ? BR_NO_END1 : BR_NO_END2; 307. case TBR_NO_DOWN: return tbr->up ? BR_NO_END2 : BR_NO_END1; 308. case TBR_PORTAL: return BR_PORTAL; 309. } 310. impossible("correct_branch_type: unknown branch type"); 311. return BR_STAIR; 312. } 313. 314. /* 315. * Add the given branch to the branch list. The branch list is ordered 316. * by end1 dungeon and level followed by end2 dungeon and level. If 317. * extract_first is true, then the branch is already part of the list 318. * but needs to be repositioned. 319. */ 320. void 321. insert_branch(new_branch, extract_first) 322. branch *new_branch; 323. boolean extract_first; 324. { 325. branch *curr, *prev; 326. long new_val, curr_val, prev_val; 327. 328. if (extract_first) { 329. for (prev = 0, curr = branches; curr; prev = curr, curr = curr->next) 330. if (curr == new_branch) break; 331. 332. if (!curr) panic("insert_branch: not found"); 333. if (prev) 334. prev->next = curr->next; 335. else 336. branches = curr->next; 337. } 338. new_branch->next = (branch *) 0; 339. 340. /* Convert the branch into a unique number so we can sort them. */ 341. #define branch_val(bp) ((((long)(bp)->end1.dnum * (MAXLEVEL+1) + (long)(bp)->end1.dlevel) * (MAXDUNGEON+1) * (MAXLEVEL+1)) + ((long)(bp)->end2.dnum * (MAXLEVEL+1) + (long)(bp)->end2.dlevel)) 342. 343. /* 344. * Insert the new branch into the correct place in the branch list. 345. */ 346. prev = (branch *) 0; 347. prev_val = -1; 348. new_val = branch_val(new_branch); 349. for (curr = branches; curr; 350. prev_val = curr_val, prev = curr, curr = curr->next) { 351. curr_val = branch_val(curr); 352. if (prev_val < new_val && new_val <= curr_val) break; 353. } 354. if (prev) { 355. new_branch->next = curr; 356. prev->next = new_branch; 357. } else { 358. new_branch->next = branches; 359. branches = new_branch; 360. } 361. } 362. 363. /* Add a dungeon branch to the branch list. */ 364. static branch * 365. add_branch(dgn, child_entry_level, pd) 366. int dgn; 367. int child_entry_level; 368. struct proto_dungeon *pd; 369. { 370. static int branch_id = 0; 371. int branch_num; 372. branch *new_branch; 373. 374. branch_num = find_branch(dungeons[dgn].dname,pd); 375. new_branch = (branch *) alloc(sizeof(branch)); 376. new_branch->next = (branch *) 0; 377. new_branch->id = branch_id++; 378. new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]); 379. new_branch->end1.dnum = parent_dnum(dungeons[dgn].dname, pd); 380. new_branch->end1.dlevel = parent_dlevel(dungeons[dgn].dname, pd); 381. new_branch->end2.dnum = dgn; 382. new_branch->end2.dlevel = child_entry_level; 383. new_branch->end1_up = pd->tmpbranch[branch_num].up ? TRUE : FALSE; 384. 385. insert_branch(new_branch, FALSE); 386. return new_branch; 387. } 388. 389. /* 390. * Add new level to special level chain. Insert it in level order with the 391. * other levels in this dungeon. This assumes that we are never given a 392. * level that has a dungeon number less than the dungeon number of the 393. * last entry. 394. */ 395. static void 396. add_level(new_lev) 397. s_level *new_lev; 398. { 399. s_level *prev, *curr; 400. 401. prev = (s_level *) 0; 402. for (curr = sp_levchn; curr; curr = curr->next) { 403. if (curr->dlevel.dnum == new_lev->dlevel.dnum && 404. curr->dlevel.dlevel > new_lev->dlevel.dlevel) 405. break; 406. prev = curr; 407. } 408. if (!prev) { 409. new_lev->next = sp_levchn; 410. sp_levchn = new_lev; 411. } else { 412. new_lev->next = curr; 413. prev->next = new_lev; 414. } 415. } 416. 417. static void 418. init_level(dgn, proto_index, pd) 419. int dgn, proto_index; 420. struct proto_dungeon *pd; 421. { 422. s_level *new_level; 423. struct tmplevel *tlevel = &pd->tmplevel[proto_index]; 424. 425. pd->final_lev[proto_index] = (s_level *) 0; /* no "real" level */ 426. #ifdef WIZARD 427. if (!wizard) 428. #endif 429. if (tlevel->chance <= rn2(100)) return; 430. 431. pd->final_lev[proto_index] = new_level = 432. (s_level *) alloc(sizeof(s_level)); 433. /* load new level with data */ 434. Strcpy(new_level->proto, tlevel->name); 435. new_level->boneid = tlevel->boneschar; 436. new_level->dlevel.dnum = dgn; 437. new_level->dlevel.dlevel = 0; /* for now */ 438. 439. new_level->flags.town = !!(tlevel->flags & TOWN); 440. new_level->flags.hellish = !!(tlevel->flags & HELLISH); 441. new_level->flags.maze_like = !!(tlevel->flags & MAZELIKE); 442. new_level->flags.rogue_like = !!(tlevel->flags & ROGUELIKE); 443. new_level->flags.align = ((tlevel->flags & D_ALIGN_MASK) >> 4); 444. 445. new_level->rndlevs = tlevel->rndlevs; 446. new_level->next = (s_level *) 0; 447. } 448. 449. static int 450. possible_places(idx, map, pd) 451. int idx; /* prototype index */ 452. boolean *map; /* array MAXLEVEL+1 in length */ 453. struct proto_dungeon *pd; 454. { 455. int i, start, count; 456. s_level *lev = pd->final_lev[idx]; 457. 458. /* init level possibilities */ 459. for (i = 0; i <= MAXLEVEL; i++) map[i] = FALSE; 460. 461. /* get base and range and set those entried to true */ 462. count = level_range(lev->dlevel.dnum, pd->tmplevel[idx].lev.base, 463. pd->tmplevel[idx].lev.rand, 464. pd->tmplevel[idx].chain, 465. pd, &start); 466. for (i = start; i < start+count; i++) 467. map[i] = TRUE; 468. 469. /* mark off already placed levels */ 470. for (i = pd->start; i < idx; i++) { 471. if (pd->final_lev[i] && map[pd->final_lev[i]->dlevel.dlevel]) { 472. map[pd->final_lev[i]->dlevel.dlevel] = FALSE; 473. --count; 474. } 475. } 476. 477. return count; 478. } 479. 480. /* Pick the nth TRUE entry in the given boolean array. */ 481. static xchar 482. pick_level(map, nth) 483. boolean *map; /* an array MAXLEVEL+1 in size */ 484. int nth; 485. { 486. int i; 487. for (i = 1; i <= MAXLEVEL; i++) 488. if (map[i] && !nth--) return (xchar) i; 489. panic("pick_level: ran out of valid levels"); 490. return 0; 491. } 492. 493. #ifdef DDEBUG 494. static void FDECL(indent,(int)); 495. 496. static void 497. indent(d) 498. int d; 499. { 500. while (d-- > 0) fputs(" ", stderr); 501. } 502. #endif 503. 504. /* 505. * Place a level. First, find the possible places on a dungeon map 506. * template. Next pick one. Then try to place the next level. If 507. * sucessful, we're done. Otherwise, try another (and another) until 508. * all possible places have been tried. If all possible places have 509. * been exausted, return false. 510. */ 511. static boolean 512. place_level(proto_index, pd) 513. int proto_index; 514. struct proto_dungeon *pd; 515. { 516. boolean map[MAXLEVEL+1]; /* valid levels are 1..MAXLEVEL inclusive */ 517. s_level *lev; 518. int npossible; 519. #ifdef DDEBUG 520. int i; 521. #endif 522. 523. if (proto_index == pd->n_levs) return TRUE; /* at end of proto levels */ 524. 525. lev = pd->final_lev[proto_index]; 526. 527. /* No level created for this prototype, goto next. */ 528. if (!lev) return place_level(proto_index+1, pd); 529. 530. npossible = possible_places(proto_index, map, pd); 531. 532. for (; npossible; --npossible) { 533. lev->dlevel.dlevel = pick_level(map, rn2(npossible)); 534. #ifdef DDEBUG 535. indent(proto_index-pd->start); 536. fprintf(stderr,"%s: trying %d [ ", lev->proto, lev->dlevel.dlevel); 537. for (i = 1; i <= MAXLEVEL; i++) 538. if (map[i]) fprintf(stderr,"%d ", i); 539. fprintf(stderr,"]
"); 540. #endif 541. if (place_level(proto_index+1, pd)) return TRUE; 542. map[lev->dlevel.dlevel] = FALSE; /* this choice didn't work */ 543. } 544. #ifdef DDEBUG 545. indent(proto_index-pd->start); 546. fprintf(stderr,"%s: failed
", lev->proto); 547. #endif 548. return FALSE; 549. } 550. 551. void 552. init_dungeons() /* initialize the "dungeon" structs */ 553. { 554. FILE *dgn_file; 555. register int i, cl = 0, cb = 0; 556. register s_level *x; 557. struct proto_dungeon pd; 558. 559. pd.n_levs = pd.n_brs = 0; 560. 561. dgn_file = fopen_datafile(DUNGEON_FILE, RDMODE); 562. if (!dgn_file) 563. panic("CANNOT OPEN DUNGEON DESCRIPTION FILE %s.", DUNGEON_FILE); 564. 565. /* 566. * Read in each dungeon and transfer the results to the internal 567. * dungeon arrays. 568. */ 569. sp_levchn = (s_level *) 0; 570. Fread((genericptr_t)&n_dgns, sizeof(int), 1, dgn_file); 571. if (n_dgns >= MAXDUNGEON) 572. panic("init_dungeons: too many dungeons"); 573. 574. for (i = 0; i < n_dgns; i++) { 575. Fread((genericptr_t)&pd.tmpdungeon[i], 576. sizeof(struct tmpdungeon), 1, dgn_file); 577. #ifdef WIZARD 578. if(!wizard) 579. #endif 580. if(pd.tmpdungeon[i].chance && (pd.tmpdungeon[i].chance <= rn2(100))) { 581. int j; 582. 583. /* skip over any levels or branches */ 584. for(j = 0; j < pd.tmpdungeon[i].levels; j++) 585. Fread((genericptr_t)&pd.tmplevel[cl], sizeof(struct tmplevel), 586. 1, dgn_file); 587. 588. for(j = 0; j < pd.tmpdungeon[i].branches; j++) 589. Fread((genericptr_t)&pd.tmpbranch[cb], 590. sizeof(struct tmpbranch), 1, dgn_file); 591. n_dgns--; i--; 592. continue; 593. } 594. 595. Strcpy(dungeons[i].dname, pd.tmpdungeon[i].name); 596. Strcpy(dungeons[i].proto, pd.tmpdungeon[i].protoname); 597. dungeons[i].boneid = pd.tmpdungeon[i].boneschar; 598. 599. if(pd.tmpdungeon[i].lev.rand) 600. dungeons[i].num_dunlevs = rn1(pd.tmpdungeon[i].lev.rand, 601. pd.tmpdungeon[i].lev.base); 602. else dungeons[i].num_dunlevs = pd.tmpdungeon[i].lev.base; 603. 604. if(!i) { 605. dungeons[i].ledger_start = 0; 606. dungeons[i].depth_start = 1; 607. dungeons[i].dunlev_ureached = 1; 608. } else { 609. dungeons[i].ledger_start = dungeons[i-1].ledger_start + 610. dungeons[i-1].num_dunlevs; 611. dungeons[i].dunlev_ureached = 0; 612. } 613. 614. dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH); 615. dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE); 616. dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE); 617. dungeons[i].flags.align = ((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4); 618. /* 619. * Set the entry level for this dungeon. The pd.tmpdungeon entry 620. * value means: 621. * < 0 from bottom (-1 == bottom level) 622. * 0 default (top) 623. * > 0 actual level (1 = top) 624. * 625. * Note that the entry_lev field in the dungeon structure is 626. * redundant. It is used only here and in print_dungeon(). 627. */ 628. if (pd.tmpdungeon[i].entry_lev < 0) { 629. dungeons[i].entry_lev = dungeons[i].num_dunlevs + 630. pd.tmpdungeon[i].entry_lev + 1; 631. if (dungeons[i].entry_lev <= 0) dungeons[i].entry_lev = 1; 632. } else if (pd.tmpdungeon[i].entry_lev > 0) { 633. dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev; 634. if (dungeons[i].entry_lev > dungeons[i].num_dunlevs) 635. dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev; 636. } else { /* default */ 637. dungeons[i].entry_lev = 1; /* defaults to top level */ 638. } 639. 640. if (i) { /* set depth */ 641. branch *br; 642. xchar from_depth; 643. boolean from_up; 644. 645. br = add_branch(i, dungeons[i].entry_lev, &pd); 646. 647. /* Get the depth of the connecting end. */ 648. if (br->end1.dnum == i) { 649. from_depth = depth(&br->end2); 650. from_up = !br->end1_up; 651. } else { 652. from_depth = depth(&br->end1); 653. from_up = br->end1_up; 654. } 655. 656. /* 657. * Calculate the depth of the top of the dungeon via 658. * its branch. First, the depth of the entry point: 659. * 660. * depth of branch from "parent" dungeon 661. * + -1 or 1 depending on a up or down stair or 662. * 0 if portal 663. * 664. * Followed by the depth of the top of the dungeon: 665. * 666. * - (entry depth - 1) 667. * 668. * We'll say that portals stay on the same depth. 669. */ 670. dungeons[i].depth_start = from_depth 671. + (br->type == BR_PORTAL ? 0 : 672. (from_up ? -1 : 1)) 673. - (dungeons[i].entry_lev - 1); 674. } 675. 676. /* this is redundant - it should have been flagged by dgn_comp */ 677. if(dungeons[i].num_dunlevs > MAXLEVEL) 678. dungeons[i].num_dunlevs = MAXLEVEL; 679. 680. pd.start = pd.n_levs; /* save starting point */ 681. pd.n_levs += pd.tmpdungeon[i].levels; 682. if (pd.n_levs > LEV_LIMIT) 683. panic("init_dungeon: too many special levels"); 684. /* 685. * Read in the prototype special levels. Don't add generated 686. * special levels until they are all placed. 687. */ 688. for(; cl < pd.n_levs; cl++) { 689. Fread((genericptr_t)&pd.tmplevel[cl], 690. sizeof(struct tmplevel), 1, dgn_file); 691. init_level(i, cl, &pd); 692. } 693. /* 694. * Recursively place the generated levels for this dungeon. This 695. * routine will attempt all possible combinations before giving 696. * up. 697. */ 698. if (!place_level(pd.start, &pd)) 699. panic("init_dungeon: couldn't place levels"); 700. #ifdef DDEBUG 701. fprintf(stderr, "--- end of dungeon %d ---
", i); 702. fflush(stderr); 703. getchar(); 704. #endif 705. for (; pd.start < pd.n_levs; pd.start++) 706. if (pd.final_lev[pd.start]) add_level(pd.final_lev[pd.start]); 707. 708. 709. pd.n_brs += pd.tmpdungeon[i].branches; 710. if (pd.n_brs > BRANCH_LIMIT) 711. panic("init_dungeon: too many branches"); 712. for(; cb < pd.n_brs; cb++) 713. Fread((genericptr_t)&pd.tmpbranch[cb], 714. sizeof(struct tmpbranch), 1, dgn_file); 715. } 716. (void) fclose(dgn_file); 717. 718. for (i = 0; i < 5; i++) tune[i] = 'A' + rn2(7); 719. tune[5] = 0; 720. 721. /* 722. * Find most of the special levels and dungeons so we can access their 723. * locations quickly. 724. */ 725. #ifdef REINCARNATION 726. if ((x = find_level("rogue")) != 0) 727. assign_level(&rogue_level, &x->dlevel); 728. #endif 729. if ((x = find_level("oracle")) != 0) 730. assign_level(&oracle_level, &x->dlevel); 731. if ((x = find_level("bigroom")) != 0) 732. assign_level(&bigroom_level, &x->dlevel); 733. if ((x = find_level("medusa")) != 0) 734. assign_level(&medusa_level, &x->dlevel); 735. if ((x = find_level("castle")) != 0) 736. assign_level(&stronghold_level, &x->dlevel); 737. if ((x = find_level("valley")) != 0) 738. assign_level(&valley_level, &x->dlevel); 739. if ((x = find_level("wizard1")) != 0) 740. assign_level(&wiz1_level, &x->dlevel); 741. if ((x = find_level("wizard2")) != 0) 742. assign_level(&wiz2_level, &x->dlevel); 743. if ((x = find_level("wizard3")) != 0) 744. assign_level(&wiz3_level, &x->dlevel); 745. if ((x = find_level("juiblex")) != 0) 746. assign_level(&juiblex_level, &x->dlevel); 747. if ((x = find_level("orcus")) != 0) 748. assign_level(&orcus_level, &x->dlevel); 749. if ((x = find_level("asmodeus")) != 0) 750. assign_level(&asmodeus_level, &x->dlevel); 751. if ((x = find_level("baalz")) != 0) 752. assign_level(&baalzebub_level, &x->dlevel); 753. if ((x = find_level("fakewiz1")) != 0) 754. assign_level(&portal_level, &x->dlevel); 755. if ((x = find_level("sanctum")) != 0) 756. assign_level(&sanctum_level, &x->dlevel); 757. if ((x = find_level("earth")) != 0) 758. assign_level(&earth_level, &x->dlevel); 759. if ((x = find_level("water")) != 0) 760. assign_level(&water_level, &x->dlevel); 761. if ((x = find_level("fire")) != 0) 762. assign_level(&fire_level, &x->dlevel); 763. if ((x = find_level("air")) != 0) 764. assign_level(&air_level, &x->dlevel); 765. if ((x = find_level("astral")) != 0) 766. assign_level(&astral_level, &x->dlevel); 767. #ifdef MULDGN 768. if ((x = find_level("knox")) != 0) { 769. branch *br; 770. assign_level(&knox_level, &x->dlevel); 771. /* 772. * Kludge to allow floating Knox entrance. We specify a floating 773. * entrance by the fact that it's entrance (end1) has a bogus dnum, 774. * namely n_dgns. 775. */ 776. for (br = branches; br; br = br->next) 777. if (on_level(&br->end2, &knox_level)) break; 778. 779. if (br) br->end1.dnum = n_dgns; 780. /* adjust the branch's position on the list */ 781. insert_branch(br, TRUE); 782. } 783. /* 784. * This is where the name substitution on the levels of the quest 785. * dungeon occur. 786. */ 787. if ((x = find_level(X_START)) != 0) { 788. x->proto[0] = pl_character[0]; 789. assign_level(&qstart_level, &x->dlevel); 790. } 791. if ((x = find_level(X_LOCATE)) != 0) { 792. x->proto[0] = pl_character[0]; 793. assign_level(&qlocate_level, &x->dlevel); 794. } 795. if ((x = find_level(X_GOAL)) != 0) { 796. x->proto[0] = pl_character[0]; 797. assign_level(&nemesis_level, &x->dlevel); 798. } 799. /* 800. * I hate hardwiring these names. :-( 801. */ 802. quest_dnum = dname_to_dnum("The Quest"); 803. mines_dnum = dname_to_dnum("The Gnomish Mines"); 804. #endif 805. tower_dnum = dname_to_dnum("Vlad's Tower"); 806. 807. #ifdef DEBUG 808. dumpit(); 809. #endif 810. } 811. 812. xchar 813. dunlev(lev) /* return the level number for lev in *this* dungeon */ 814. d_level *lev; 815. { 816. return(lev->dlevel); 817. } 818. 819. xchar 820. dunlevs_in_dungeon(lev) /* return the lowest level number for *this* dungeon*/ 821. d_level *lev; 822. { 823. return(dungeons[lev->dnum].num_dunlevs); 824. } 825. 826. xchar 827. deepest_lev_reached(noquest) /* return the lowest level explored in the game*/ 828. boolean noquest; 829. { 830. /* this function is used for three purposes: to provide a factor 831. * of difficulty in monster generation; to provide a factor of 832. * difficulty in experience calculations (botl.c and end.c); and 833. * to insert the deepest level reached in the game in the topten 834. * display. the 'noquest' arg switch is required for the latter. 835. * 836. * from the player's point of view, going into the Quest is _not_ 837. * going deeper into the dungeon -- it is going back "home", where 838. * the dungeon starts at level 1. given the setup in dungeon.def, 839. * the depth of the Quest (thought of as starting at level 1) is 840. * never lower than the level of entry into the Quest, so we exclude 841. * the Quest from the topten "deepest level reached" display 842. * calculation. _However_ the Quest is a difficult dungeon, so we 843. * include it in the factor of difficulty calculations. 844. */ 845. register int i; 846. d_level tmp; 847. register xchar ret = 0; 848. 849. for(i = 0; i < n_dgns; i++) { 850. if((tmp.dlevel = dungeons[i].dunlev_ureached) == 0) continue; 851. if(!strcmp(dungeons[i].dname, "The Quest") && noquest) continue; 852. 853. tmp.dnum = i; 854. if(depth(&tmp) > ret) ret = depth(&tmp); 855. } 856. return(ret); 857. } 858. 859. /* return a bookkeeping level number for purpose of comparisons and 860. * save/restore */ 861. xchar 862. ledger_no(lev) 863. d_level *lev; 864. { 865. return(lev->dlevel + dungeons[lev->dnum].ledger_start); 866. } 867. 868. /* 869. * The last level in the bookkeeping list of level is the bottom of the last 870. * dungeon in the dungeons[] array. 871. * 872. * Maxledgerno() -- which is the max number of levels in the bookkeeping 873. * list, should not be confused with dunlevs_in_dungeon(lev) -- which 874. * returns the max number of levels in lev's dungeon, and both should 875. * not be confused with deepest_lev_reached() -- which returns the lowest 876. * depth visited by the player. 877. */ 878. xchar 879. maxledgerno() 880. { 881. return (xchar) (dungeons[n_dgns-1].ledger_start + 882. dungeons[n_dgns-1].num_dunlevs); 883. } 884. 885. /* return the dungeon that this ledgerno exists in */ 886. xchar 887. ledger_to_dnum(ledgerno) 888. xchar ledgerno; 889. { 890. xchar i; 891. 892. for(i = 0; i < n_dgns; i++) 893. if(dungeons[i].ledger_start >= ledgerno) return(i-1); 894. 895. return(MAXDUNGEON); 896. } 897. 898. /* return the level of the dungeon this ledgerno exists in */ 899. xchar 900. ledger_to_dlev(ledgerno) 901. xchar ledgerno; 902. { 903. return(ledgerno - dungeons[ledger_to_dnum(ledgerno)].ledger_start); 904. } 905. 906. #endif /* OVL1 */ 907. #ifdef OVL0 908. 909. /* returns the depth of a level, in floors below the surface */ 910. /* (note levels in different dungeons can have the same depth). */ 911. xchar 912. depth(lev) 913. d_level *lev; 914. { 915. return dungeons[lev->dnum].depth_start + lev->dlevel - 1; 916. } 917. 918. boolean 919. on_level(lev1, lev2) /* are "lev1" and "lev2" actually the same? */ 920. d_level *lev1, *lev2; 921. { 922. return((lev1->dnum == lev2->dnum) && (lev1->dlevel == lev2->dlevel)); 923. } 924. 925. #endif /* OVL0 */ 926. #ifdef OVL1 927. 928. s_level * 929. /* is this level referenced in the special level chain? */ 930. Is_special(lev) 931. d_level *lev; 932. { 933. s_level *levtmp; 934. 935. for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next) 936. if (on_level(lev, &levtmp->dlevel)) return(levtmp); 937. 938. return((s_level *)0); 939. } 940. 941. /* 942. * Is this a multi-dungeon branch level? If so, return a pointer to the 943. * branch. Otherwise, return NULL. 944. */ 945. branch * 946. Is_branchlev(lev) 947. d_level *lev; 948. { 949. branch *curr; 950. 951. for (curr = branches; curr; curr = curr->next) { 952. if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2)) 953. return curr; 954. } 955. return (branch *) 0; 956. } 957. 958. /* goto the next level (or appropriate dungeon) */ 959. void 960. next_level(at_stairs ) 961. boolean at_stairs; 962. { 963. if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) { 964. /* Taking a down dungeon branch. */ 965. goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE); 966. } else { 967. /* Going down a stairs or jump in a trap door. */ 968. d_level newlevel; 969. 970. newlevel.dnum = u.uz.dnum; 971. newlevel.dlevel = u.uz.dlevel + 1; 972. goto_level(&newlevel, at_stairs, !at_stairs, FALSE); 973. } 974. } 975. 976. /* goto the previous level (or appropriate dungeon) */ 977. void 978. prev_level(at_stairs) 979. boolean at_stairs; 980. { 981. if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) { 982. /* Taking an up dungeon branch. */ 983. if(!u.uz.dnum && !u.uhave.amulet) done(ESCAPED); 984. else goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE); 985. } else { 986. /* Going up a stairs or rising through the ceiling. */ 987. d_level newlevel; 988. newlevel.dnum = u.uz.dnum; 989. newlevel.dlevel = u.uz.dlevel - 1; 990. goto_level(&newlevel, at_stairs, FALSE, FALSE); 991. } 992. } 993. 994. void 995. u_on_sstairs() { /* place you on the special staircase */ 996. 997. if (sstairs.sx && sstairs.sy) { 998. u.ux = sstairs.sx; 999. u.uy = sstairs.sy; 1000. } else { 1001. /* code stolen from goto_level */ 1002. int try = 0; 1003. #ifdef DEBUG 1004. pline("u_on_sstairs: picking random spot"); 1005. #endif 1006. #define badspot(x,y) ((levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y)) 1007. do { 1008. u.ux = rnd(COLNO-1); 1009. u.uy = rn2(ROWNO); 1010. } while(try++ < 100 && badspot(u.ux, u.uy)); 1011. if (try >= 100) 1012. panic("u_on_sstairs: could not relocate player!"); 1013. #undef badspot 1014. } 1015. } 1016. 1017. void 1018. u_on_upstairs() /* place you on upstairs (or special equivalent) */ 1019. { 1020. if(xupstair && yupstair) { 1021. 1022. u.ux = xupstair; 1023. u.uy = yupstair; 1024. } 1025. else u_on_sstairs(); 1026. } 1027. 1028. void 1029. u_on_dnstairs() /* place you on dnstairs (or special equivalent) */ 1030. { 1031. if(xdnstair && ydnstair) { 1032. 1033. u.ux = xdnstair; 1034. u.uy = ydnstair; 1035. } 1036. else u_on_sstairs(); 1037. } 1038. 1039. boolean 1040. On_stairs(x, y) 1041. xchar x, y; 1042. { 1043. return((x == xupstair && y == yupstair) || 1044. (x == xdnstair && y == ydnstair) || 1045. (x == xdnladder && y == ydnladder) || 1046. (x == xupladder && y == yupladder) || 1047. (x == sstairs.sx && y == sstairs.sy)); 1048. } 1049. 1050. boolean 1051. Is_botlevel(lev) 1052. d_level *lev; 1053. { 1054. return lev->dlevel == dungeons[lev->dnum].num_dunlevs; 1055. } 1056. 1057. boolean 1058. Can_dig_down(lev) 1059. d_level *lev; 1060. { 1061. return !level.flags.hardfloor 1062. && !Is_botlevel(lev) && !Invocation_lev(lev); 1063. } 1064. 1065. /* 1066. * Like Can_dig_down (above), but also allows falling through on the 1067. * stronghold level. Normally, the bottom level of a dungeon resists 1068. * both digging and falling. 1069. */ 1070. boolean 1071. Can_fall_thru(lev) 1072. d_level *lev; 1073. { 1074. return Can_dig_down(lev) || Is_stronghold(lev); 1075. } 1076. 1077. /* 1078. * True if one can rise up a level (e.g. cursed gain level). 1079. * This happens on intermediate dungeon levels or on any top dungeon 1080. * level that has a stairwell style branch to the next higher dungeon. 1081. * Checks for amulets and such must be done elsewhere. 1082. */ 1083. boolean 1084. Can_rise_up(lev) 1085. d_level *lev; 1086. { 1087. return !In_endgame(lev) && 1088. (lev->dlevel > 1 || 1089. (dungeons[lev->dnum].entry_lev == 1 && ledger_no(lev) != 1 && 1090. sstairs.sx && sstairs.up)); 1091. } 1092. 1093. /* 1094. * It is expected that the second argument of get_level is a depth value, 1095. * either supplied by the user (teleport control) or randomly generated. 1096. * But more than one level can be at the same depth. If the target level 1097. * is "above" the present depth location, get_level must trace "up" from 1098. * the player's location (through the ancestors dungeons) the dungeon 1099. * within which the target level is located. With only one exception 1100. * which does not pass through this routine (see level_tele), teleporting 1101. * "down" is confined to the current dungeon. At present, level teleport 1102. * in dungeons that build up is confined within them. 1103. */ 1104. void 1105. get_level(newlevel, levnum) 1106. d_level *newlevel; 1107. int levnum; 1108. { 1109. branch *br; 1110. xchar dgn = u.uz.dnum; 1111. 1112. if (levnum <= 0) { 1113. impossible("get_level: levnum = %d
", levnum); 1114. levnum = u.uz.dlevel; 1115. } else if (levnum > dungeons[dgn].depth_start 1116. + dungeons[dgn].num_dunlevs - 1) { 1117. /* beyond end of dungeon, jump to last level */ 1118. levnum = dungeons[dgn].num_dunlevs; 1119. } else { 1120. /* The desired level is in this dungeon or a "higher" one. */ 1121. 1122. /* 1123. * Branch up the tree until we reach a dungeon that contains the 1124. * levnum. 1125. */ 1126. if (levnum < dungeons[dgn].depth_start) { 1127. 1128. do { 1129. /* 1130. * Find the parent dungeon of this dungeon. 1131. * 1132. * This assumes that end2 is always the "child" and it is 1133. * unique. 1134. */ 1135. for (br = branches; br; br = br->next) 1136. if (br->end2.dnum == dgn) break; 1137. if (!br) 1138. panic("get_level: can't find parent dungeon"); 1139. 1140. dgn = br->end1.dnum; 1141. } while (levnum < dungeons[dgn].depth_start); 1142. } 1143. 1144. /* We're within the same dungeon; calculate the level. */ 1145. levnum = levnum - dungeons[dgn].depth_start + 1; 1146. } 1147. 1148. newlevel->dnum = dgn; 1149. newlevel->dlevel = levnum; 1150. } 1151. 1152. #endif /* OVL1 */ 1153. #ifdef OVL0 1154. 1155. #ifdef MULDGN 1156. boolean 1157. In_quest(lev) /* are you in the quest dungeon? */ 1158. d_level *lev; 1159. { 1160. return(lev->dnum == quest_dnum); 1161. } 1162. #endif /* MULDGN */ 1163. 1164. #endif /* OVL0 */ 1165. #ifdef OVL1 1166. 1167. #ifdef MULDGN 1168. boolean 1169. In_mines(lev) /* are you in the mines dungeon? */ 1170. d_level *lev; 1171. { 1172. return(lev->dnum == mines_dnum); 1173. } 1174. 1175. /* 1176. * Return the branch for the given dungeon. 1177. * 1178. * This function assumes: 1179. * + This is not called with "Dungeons of Doom". 1180. * + There is only _one_ branch to a given dungeon. 1181. * + Field end2 is the "child" dungeon. 1182. */ 1183. branch * 1184. dungeon_branch(s) 1185. const char *s; 1186. { 1187. branch *br; 1188. xchar dnum; 1189. 1190. dnum = dname_to_dnum(s); 1191. 1192. /* Find the branch that connects to dungeon i's branch. */ 1193. for (br = branches; br; br = br->next) 1194. if (br->end2.dnum == dnum) break; 1195. 1196. if (!br) panic("dgn_entrance: can't find entrance to %s", s); 1197. 1198. return br; 1199. } 1200. 1201. /* 1202. * This returns true if the hero is on the same level as the entrance to 1203. * the named dungeon. 1204. * 1205. * Called from do.c and mklev.c. 1206. * 1207. * Assumes that end1 is always the "parent". 1208. */ 1209. boolean 1210. at_dgn_entrance(s) 1211. const char *s; 1212. { 1213. branch *br; 1214. 1215. br = dungeon_branch(s); 1216. return on_level(&u.uz, &br->end1) ? TRUE : FALSE; 1217. } 1218. #endif /* MULDGN */ 1219. 1220. boolean 1221. In_tower(lev) /* are you inside the tower? */ 1222. d_level *lev; 1223. { 1224. return(lev->dnum == tower_dnum); 1225. } 1226. 1227. #endif /* OVL1 */ 1228. #ifdef OVL0 1229. 1230. boolean 1231. In_hell(lev) /* are you in one of the Hell levels? */ 1232. d_level *lev; 1233. { 1234. return(dungeons[lev->dnum].flags.hellish); 1235. } 1236. 1237. #endif /* OVL0 */ 1238. #ifdef OVL1 1239. 1240. void 1241. goto_hell(at_stairs, falling) /* go directly to hell... */ 1242. boolean at_stairs, falling; 1243. { 1244. d_level lev; 1245. 1246. lev.dnum = wiz1_level.dnum; 1247. lev.dlevel = 1; 1248. goto_level(&lev, at_stairs, falling, FALSE); 1249. } 1250. 1251. void 1252. assign_level(dest, src) /* equivalent to dest = source */ 1253. d_level *dest, *src; 1254. { 1255. dest->dnum = src->dnum; 1256. dest->dlevel = src->dlevel; 1257. } 1258. 1259. void 1260. assign_rnd_level(dest, src, range) /* dest = src + rn1(range) */ 1261. d_level *dest, *src; 1262. int range; 1263. { 1264. dest->dnum = src->dnum; 1265. dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range)) ; 1266. 1267. if(dest->dlevel > dunlevs_in_dungeon(dest)) 1268. dest->dlevel = dunlevs_in_dungeon(dest); 1269. else if(dest->dlevel < 1) 1270. dest->dlevel = 1; 1271. } 1272. 1273. #endif /* OVL1 */ 1274. #ifdef OVL0 1275. 1276. int 1277. induced_align(pct) 1278. int pct; 1279. { 1280. s_level *lev = Is_special(&u.uz); 1281. aligntyp al; 1282. 1283. if (lev && lev->flags.align) 1284. if(rn2(100) < pct) return(lev->flags.align); 1285. 1286. if(dungeons[u.uz.dnum].flags.align) 1287. if(rn2(100) < pct) return(dungeons[u.uz.dnum].flags.align); 1288. 1289. al = rn2(3) - 1; 1290. return(Align2amask(al)); 1291. } 1292. 1293. #endif /* OVL0 */ 1294. #ifdef OVL1 1295. 1296. boolean 1297. Invocation_lev(lev) 1298. d_level *lev; 1299. { 1300. return(In_hell(lev) && 1301. lev->dlevel == (dungeons[lev->dnum].num_dunlevs - 1)); 1302. } 1303. 1304. /* use instead of depth() wherever a degree of difficulty is made 1305. * dependent on the location in the dungeon (eg. monster creation). 1306. */ 1307. xchar 1308. level_difficulty() 1309. { 1310. if (In_endgame(&u.uz)) 1311. return(depth(&sanctum_level) + u.ulevel/2); 1312. else 1313. if (u.uhave.amulet) 1314. return(deepest_lev_reached(FALSE)); 1315. else 1316. return(depth(&u.uz)); 1317. } 1318. 1319. 1320. #ifdef WIZARD 1321. 1322. /* Convert a branch type to a string usable by print_dungeon(). */ 1323. static const char * 1324. br_string(type) 1325. int type; 1326. { 1327. switch (type) { 1328. case BR_PORTAL: return "Portal"; 1329. case BR_NO_END1: return "Connection"; 1330. case BR_NO_END2: return "One way stair"; 1331. case BR_STAIR: return "Stair"; 1332. } 1333. return " (unknown)"; 1334. } 1335. 1336. /* Print all child branches between the lower and upper bounds. */ 1337. static void 1338. print_branch(win, dnum, lower_bound, upper_bound) 1339. winid win; 1340. int dnum; 1341. int lower_bound; 1342. int upper_bound; 1343. { 1344. branch *br; 1345. char buf[BUFSZ]; 1346. 1347. /* This assumes that end1 is the "parent". */ 1348. for (br = branches; br; br = br->next) { 1349. if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel && 1350. br->end1.dlevel <= upper_bound) { 1351. Sprintf(buf," %s to %s: %d", 1352. br_string(br->type), 1353. dungeons[br->end2.dnum].dname, 1354. depth(&br->end1)); 1355. putstr(win, 0, buf); 1356. } 1357. } 1358. } 1359. 1360. /* Print available dungeon information. */ 1361. void 1362. print_dungeon() 1363. { 1364. int i, last_level, nlev; 1365. char buf[BUFSZ]; 1366. boolean first; 1367. s_level *slev; 1368. dungeon *dptr; 1369. branch *br; 1370. winid win = create_nhwindow(NHW_MENU); 1371. 1372. for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) { 1373. nlev = dptr->num_dunlevs; 1374. if (nlev > 1) 1375. Sprintf(buf, "%s: levels %d to %d", dptr->dname, dptr->depth_start, 1376. dptr->depth_start + nlev - 1); 1377. else 1378. Sprintf(buf, "%s: level %d", dptr->dname, dptr->depth_start); 1379. 1380. /* Most entrances are uninteresting. */ 1381. if (dptr->entry_lev != 1) { 1382. if (dptr->entry_lev == nlev) 1383. Strcat(buf, ", entrance from below"); 1384. else 1385. Sprintf(eos(buf), ", entrance on %d", 1386. dptr->depth_start + dptr->entry_lev - 1); 1387. } 1388. putstr(win, 0, buf); 1389. 1390. /* 1391. * Circle through the special levels to find levels that are in 1392. * this dungeon. 1393. */ 1394. for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) { 1395. if (slev->dlevel.dnum != i) continue; 1396. 1397. /* print any branches before this level */ 1398. print_branch(win, i, last_level, slev->dlevel.dlevel); 1399. 1400. Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel)); 1401. if (Is_stronghold(&slev->dlevel)) 1402. Sprintf(eos(buf), " (tune %s)", tune); 1403. putstr(win, 0, buf); 1404. 1405. last_level = slev->dlevel.dlevel; 1406. } 1407. /* print branches after the last special level */ 1408. print_branch(win, i, last_level, MAXLEVEL); 1409. } 1410. 1411. /* Print out floating branches (if any). */ 1412. for (first = TRUE, br = branches; br; br = br->next) { 1413. if (br->end1.dnum == n_dgns) { 1414. if (first) { 1415. putstr(win, 0, ""); 1416. putstr(win, 0, "Floating branches"); 1417. first = FALSE; 1418. } 1419. Sprintf(buf, " %s to %s", 1420. br_string(br->type), dungeons[br->end2.dnum].dname); 1421. putstr(win, 0, buf); 1422. } 1423. } 1424. 1425. /* I hate searching for the invocation pos while debugging. -dean */ 1426. if (Invocation_lev(&u.uz)) { 1427. putstr(win, 0, ""); 1428. Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)", 1429. inv_pos.x, inv_pos.y, u.ux, u.uy); 1430. putstr(win, 0, buf); 1431. } 1432. /* 1433. * The following is based on the assumption that the inter-level portals 1434. * created by the level compiler (not the dungeon compiler) only exist 1435. * one per level (currently true, of course). 1436. */ 1437. else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz) 1438. || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) { 1439. struct trap *trap; 1440. for (trap = ftrap; trap; trap = trap->ntrap) 1441. if (trap->ttyp == MAGIC_PORTAL) break; 1442. 1443. putstr(win, 0, ""); 1444. if (trap) 1445. Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)", 1446. trap->tx, trap->ty, u.ux, u.uy); 1447. else 1448. Sprintf(buf, "No portal found."); 1449. putstr(win, 0, buf); 1450. } 1451. 1452. display_nhwindow(win, TRUE); 1453. destroy_nhwindow(win); 1454. } 1455. 1456. #endif /* WIZARD */ 1457. #endif /* OVL1 */ 1458. 1459. /*dungeon.c*/
|