1 /* NetHack 3.6 dungeon.c $NHDT-Date: 1448862377 2015/11/30 05:46:17 $ $NHDT-Branch: master $:$NHDT-Revision: 1.69 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
10 #define DUNGEON_FILE "dungeon"
12 #define X_START "x-strt"
13 #define X_LOCATE "x-loca"
14 #define X_GOAL "x-goal"
16 struct proto_dungeon {
17 struct tmpdungeon tmpdungeon[MAXDUNGEON];
18 struct tmplevel tmplevel[LEV_LIMIT];
19 s_level *final_lev[LEV_LIMIT]; /* corresponding level pointers */
20 struct tmpbranch tmpbranch[BRANCH_LIMIT];
22 int start; /* starting index of current dungeon sp levels */
23 int n_levs; /* number of tmplevel entries */
24 int n_brs; /* number of tmpbranch entries */
27 int n_dgns; /* number of dungeons (also used in mklev.c and do.c) */
28 static branch *branches = (branch *) 0; /* dungeon branch list */
30 mapseen *mapseenchn = (struct mapseen *) 0; /*DUNGEON_OVERVIEW*/
35 schar playerlev[MAXLINFO];
40 static void FDECL(Fread, (genericptr_t, int, int, dlb *));
41 STATIC_DCL xchar FDECL(dname_to_dnum, (const char *));
42 STATIC_DCL int FDECL(find_branch, (const char *, struct proto_dungeon *));
43 STATIC_DCL xchar FDECL(parent_dnum, (const char *, struct proto_dungeon *));
44 STATIC_DCL int FDECL(level_range, (XCHAR_P, int, int, int,
45 struct proto_dungeon *, int *));
46 STATIC_DCL xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *));
47 STATIC_DCL int FDECL(correct_branch_type, (struct tmpbranch *));
48 STATIC_DCL branch *FDECL(add_branch, (int, int, struct proto_dungeon *));
49 STATIC_DCL void FDECL(add_level, (s_level *));
50 STATIC_DCL void FDECL(init_level, (int, int, struct proto_dungeon *));
51 STATIC_DCL int FDECL(possible_places, (int, boolean *,
52 struct proto_dungeon *));
53 STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
54 STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
55 STATIC_DCL boolean FDECL(unplaced_floater, (struct dungeon *));
56 STATIC_DCL boolean FDECL(unreachable_level, (d_level *, BOOLEAN_P));
57 STATIC_DCL void FDECL(tport_menu, (winid, char *, struct lchoice *, d_level *,
59 STATIC_DCL const char *FDECL(br_string, (int));
60 STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
62 STATIC_DCL mapseen *FDECL(load_mapseen, (int));
63 STATIC_DCL void FDECL(save_mapseen, (int, mapseen *));
64 STATIC_DCL mapseen *FDECL(find_mapseen, (d_level *));
65 STATIC_DCL void FDECL(print_mapseen, (winid, mapseen *, int, int, BOOLEAN_P));
66 STATIC_DCL boolean FDECL(interest_mapseen, (mapseen *));
67 STATIC_DCL void FDECL(traverse_mapseenchn, (BOOLEAN_P, winid,
69 STATIC_DCL const char *FDECL(seen_string, (XCHAR_P, const char *));
70 STATIC_DCL const char *FDECL(br_string2, (branch *));
71 STATIC_DCL const char *FDECL(endgamelevelname, (char *, int));
72 STATIC_DCL const char *FDECL(shop_string, (int));
73 STATIC_DCL char *FDECL(tunesuffix, (mapseen *, char *));
76 #define DD dungeons[i]
77 STATIC_DCL void NDECL(dumpit);
86 if (!explicitdebug(__FILE__))
89 for (i = 0; i < n_dgns; i++) {
90 fprintf(stderr, "\n#%d \"%s\" (%s):\n", i, DD.dname, DD.proto);
91 fprintf(stderr, " num_dunlevs %d, dunlev_ureached %d\n",
92 DD.num_dunlevs, DD.dunlev_ureached);
93 fprintf(stderr, " depth_start %d, ledger_start %d\n",
94 DD.depth_start, DD.ledger_start);
95 fprintf(stderr, " flags:%s%s%s\n",
96 DD.flags.rogue_like ? " rogue_like" : "",
97 DD.flags.maze_like ? " maze_like" : "",
98 DD.flags.hellish ? " hellish" : "");
101 fprintf(stderr, "\nSpecial levels:\n");
102 for (x = sp_levchn; x; x = x->next) {
103 fprintf(stderr, "%s (%d): ", x->proto, x->rndlevs);
104 fprintf(stderr, "on %d, %d; ", x->dlevel.dnum, x->dlevel.dlevel);
105 fprintf(stderr, "flags:%s%s%s%s\n",
106 x->flags.rogue_like ? " rogue_like" : "",
107 x->flags.maze_like ? " maze_like" : "",
108 x->flags.hellish ? " hellish" : "",
109 x->flags.town ? " town" : "");
112 fprintf(stderr, "\nBranches:\n");
113 for (br = branches; br; br = br->next) {
114 fprintf(stderr, "%d: %s, end1 %d %d, end2 %d %d, %s\n", br->id,
117 : br->type == BR_NO_END1
119 : br->type == BR_NO_END2
121 : br->type == BR_PORTAL
124 br->end1.dnum, br->end1.dlevel, br->end2.dnum,
125 br->end2.dlevel, br->end1_up ? "end1 up" : "end1 down");
128 fprintf(stderr, "\nDone\n");
133 /* Save the dungeon structures. */
135 save_dungeon(fd, perform_write, free_data)
137 boolean perform_write, free_data;
140 mapseen *curr_ms, *next_ms;
144 bwrite(fd, (genericptr_t) &n_dgns, sizeof n_dgns);
145 bwrite(fd, (genericptr_t) dungeons,
146 sizeof(dungeon) * (unsigned) n_dgns);
147 bwrite(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
148 bwrite(fd, (genericptr_t) tune, sizeof tune);
150 for (count = 0, curr = branches; curr; curr = curr->next)
152 bwrite(fd, (genericptr_t) &count, sizeof(count));
154 for (curr = branches; curr; curr = curr->next)
155 bwrite(fd, (genericptr_t) curr, sizeof(branch));
157 count = maxledgerno();
158 bwrite(fd, (genericptr_t) &count, sizeof count);
159 bwrite(fd, (genericptr_t) level_info,
160 (unsigned) count * sizeof(struct linfo));
161 bwrite(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
163 for (count = 0, curr_ms = mapseenchn; curr_ms;
164 curr_ms = curr_ms->next)
166 bwrite(fd, (genericptr_t) &count, sizeof(count));
168 for (curr_ms = mapseenchn; curr_ms; curr_ms = curr_ms->next)
169 save_mapseen(fd, curr_ms);
173 for (curr = branches; curr; curr = next) {
175 free((genericptr_t) curr);
178 for (curr_ms = mapseenchn; curr_ms; curr_ms = next_ms) {
179 next_ms = curr_ms->next;
181 free((genericptr_t) curr_ms->custom);
182 free((genericptr_t) curr_ms);
188 /* Restore the dungeon structures. */
195 mapseen *curr_ms, *last_ms;
197 mread(fd, (genericptr_t) &n_dgns, sizeof(n_dgns));
198 mread(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned) n_dgns);
199 mread(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
200 mread(fd, (genericptr_t) tune, sizeof tune);
202 last = branches = (branch *) 0;
204 mread(fd, (genericptr_t) &count, sizeof(count));
205 for (i = 0; i < count; i++) {
206 curr = (branch *) alloc(sizeof(branch));
207 mread(fd, (genericptr_t) curr, sizeof(branch));
208 curr->next = (branch *) 0;
216 mread(fd, (genericptr_t) &count, sizeof(count));
217 if (count >= MAXLINFO)
218 panic("level information count larger (%d) than allocated size",
220 mread(fd, (genericptr_t) level_info,
221 (unsigned) count * sizeof(struct linfo));
222 mread(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
224 mread(fd, (genericptr_t) &count, sizeof(count));
225 last_ms = (mapseen *) 0;
226 for (i = 0; i < count; i++) {
227 curr_ms = load_mapseen(fd);
228 curr_ms->next = (mapseen *) 0;
230 last_ms->next = curr_ms;
232 mapseenchn = curr_ms;
238 Fread(ptr, size, nitems, stream)
245 if ((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) {
247 "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
248 (size * nitems), (size * cnt));
249 terminate(EXIT_FAILURE);
259 for (i = 0; i < n_dgns; i++)
260 if (!strcmp(dungeons[i].dname, s))
263 panic("Couldn't resolve dungeon number for name \"%s\".", s);
273 for (curr = sp_levchn; curr; curr = curr->next)
274 if (!strcmpi(s, curr->proto))
279 /* Find the branch that links the named dungeon. */
282 const char *s; /* dungeon name */
283 struct proto_dungeon *pd;
288 for (i = 0; i < pd->n_brs; i++)
289 if (!strcmp(pd->tmpbranch[i].name, s))
292 panic("find_branch: can't find %s", s);
294 /* support for level tport by name */
298 for (br = branches; br; br = br->next) {
299 dnam = dungeons[br->end2.dnum].dname;
300 if (!strcmpi(dnam, s)
301 || (!strncmpi(dnam, "The ", 4) && !strcmpi(dnam + 4, s)))
304 i = br ? ((ledger_no(&br->end1) << 8) | ledger_no(&br->end2)) : -1;
310 * Find the "parent" by searching the prototype branch list for the branch
311 * listing, then figuring out to which dungeon it belongs.
315 const char *s; /* dungeon name */
316 struct proto_dungeon *pd;
321 i = find_branch(s, pd);
323 * Got branch, now find parent dungeon. Stop if we have reached
324 * "this" dungeon (if we haven't found it by now it is an error).
326 for (pdnum = 0; strcmp(pd->tmpdungeon[pdnum].name, s); pdnum++)
327 if ((i -= pd->tmpdungeon[pdnum].branches) < 0)
330 panic("parent_dnum: couldn't resolve branch.");
336 * Return a starting point and number of successive positions a level
337 * or dungeon entrance can occupy.
339 * Note: This follows the acouple (instead of the rcouple) rules for a
340 * negative random component (randc < 0). These rules are found
341 * in dgn_comp.y. The acouple [absolute couple] section says that
342 * a negative random component means from the (adjusted) base to the
343 * end of the dungeon.
346 level_range(dgn, base, randc, chain, pd, adjusted_base)
348 int base, randc, chain;
349 struct proto_dungeon *pd;
352 int lmax = dungeons[dgn].num_dunlevs;
354 if (chain >= 0) { /* relative to a special level */
355 s_level *levtmp = pd->final_lev[chain];
357 panic("level_range: empty chain level!");
359 base += levtmp->dlevel.dlevel;
360 } else { /* absolute in the dungeon */
361 /* from end of dungeon */
363 base = (lmax + base + 1);
366 if (base < 1 || base > lmax)
367 panic("level_range: base value out of range");
369 *adjusted_base = base;
371 if (randc == -1) { /* from base to end of dungeon */
372 return (lmax - base + 1);
374 /* make sure we don't run off the end of the dungeon */
375 return (((base + randc - 1) > lmax) ? lmax - base + 1 : randc);
376 } /* else only one choice */
383 struct proto_dungeon *pd;
385 int i, j, num, base, dnum = parent_dnum(s, pd);
388 i = find_branch(s, pd);
389 num = level_range(dnum, pd->tmpbranch[i].lev.base,
390 pd->tmpbranch[i].lev.rand, pd->tmpbranch[i].chain, pd,
393 /* KMH -- Try our best to find a level without an existing branch */
398 for (curr = branches; curr; curr = curr->next)
399 if ((curr->end1.dnum == dnum && curr->end1.dlevel == base + i)
400 || (curr->end2.dnum == dnum && curr->end2.dlevel == base + i))
402 } while (curr && i != j);
406 /* Convert from the temporary branch type to the dungeon branch type. */
408 correct_branch_type(tbr)
409 struct tmpbranch *tbr;
415 return tbr->up ? BR_NO_END1 : BR_NO_END2;
417 return tbr->up ? BR_NO_END2 : BR_NO_END1;
421 impossible("correct_branch_type: unknown branch type");
426 * Add the given branch to the branch list. The branch list is ordered
427 * by end1 dungeon and level followed by end2 dungeon and level. If
428 * extract_first is true, then the branch is already part of the list
429 * but needs to be repositioned.
432 insert_branch(new_branch, extract_first)
434 boolean extract_first;
437 long new_val, curr_val, prev_val;
440 for (prev = 0, curr = branches; curr; prev = curr, curr = curr->next)
441 if (curr == new_branch)
445 panic("insert_branch: not found");
447 prev->next = curr->next;
449 branches = curr->next;
451 new_branch->next = (branch *) 0;
453 /* Convert the branch into a unique number so we can sort them. */
454 #define branch_val(bp) \
455 ((((long) (bp)->end1.dnum * (MAXLEVEL + 1) + (long) (bp)->end1.dlevel) \
456 * (MAXDUNGEON + 1) * (MAXLEVEL + 1)) \
457 + ((long) (bp)->end2.dnum * (MAXLEVEL + 1) + (long) (bp)->end2.dlevel))
460 * Insert the new branch into the correct place in the branch list.
464 new_val = branch_val(new_branch);
465 for (curr = branches; curr;
466 prev_val = curr_val, prev = curr, curr = curr->next) {
467 curr_val = branch_val(curr);
468 if (prev_val < new_val && new_val <= curr_val)
472 new_branch->next = curr;
473 prev->next = new_branch;
475 new_branch->next = branches;
476 branches = new_branch;
480 /* Add a dungeon branch to the branch list. */
482 add_branch(dgn, child_entry_level, pd)
484 int child_entry_level;
485 struct proto_dungeon *pd;
487 static int branch_id = 0;
491 branch_num = find_branch(dungeons[dgn].dname, pd);
492 new_branch = (branch *) alloc(sizeof(branch));
493 new_branch->next = (branch *) 0;
494 new_branch->id = branch_id++;
495 new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
496 new_branch->end1.dnum = parent_dnum(dungeons[dgn].dname, pd);
497 new_branch->end1.dlevel = parent_dlevel(dungeons[dgn].dname, pd);
498 new_branch->end2.dnum = dgn;
499 new_branch->end2.dlevel = child_entry_level;
500 new_branch->end1_up = pd->tmpbranch[branch_num].up ? TRUE : FALSE;
502 insert_branch(new_branch, FALSE);
507 * Add new level to special level chain. Insert it in level order with the
508 * other levels in this dungeon. This assumes that we are never given a
509 * level that has a dungeon number less than the dungeon number of the
516 s_level *prev, *curr;
518 prev = (s_level *) 0;
519 for (curr = sp_levchn; curr; curr = curr->next) {
520 if (curr->dlevel.dnum == new_lev->dlevel.dnum
521 && curr->dlevel.dlevel > new_lev->dlevel.dlevel)
526 new_lev->next = sp_levchn;
529 new_lev->next = curr;
530 prev->next = new_lev;
535 init_level(dgn, proto_index, pd)
536 int dgn, proto_index;
537 struct proto_dungeon *pd;
540 struct tmplevel *tlevel = &pd->tmplevel[proto_index];
542 pd->final_lev[proto_index] = (s_level *) 0; /* no "real" level */
543 if (!wizard && tlevel->chance <= rn2(100))
546 pd->final_lev[proto_index] = new_level =
547 (s_level *) alloc(sizeof(s_level));
548 /* load new level with data */
549 Strcpy(new_level->proto, tlevel->name);
550 new_level->boneid = tlevel->boneschar;
551 new_level->dlevel.dnum = dgn;
552 new_level->dlevel.dlevel = 0; /* for now */
554 new_level->flags.town = !!(tlevel->flags & TOWN);
555 new_level->flags.hellish = !!(tlevel->flags & HELLISH);
556 new_level->flags.maze_like = !!(tlevel->flags & MAZELIKE);
557 new_level->flags.rogue_like = !!(tlevel->flags & ROGUELIKE);
558 new_level->flags.align = ((tlevel->flags & D_ALIGN_MASK) >> 4);
559 if (!new_level->flags.align)
560 new_level->flags.align =
561 ((pd->tmpdungeon[dgn].flags & D_ALIGN_MASK) >> 4);
563 new_level->rndlevs = tlevel->rndlevs;
564 new_level->next = (s_level *) 0;
568 possible_places(idx, map, pd)
569 int idx; /* prototype index */
570 boolean *map; /* array MAXLEVEL+1 in length */
571 struct proto_dungeon *pd;
574 s_level *lev = pd->final_lev[idx];
576 /* init level possibilities */
577 for (i = 0; i <= MAXLEVEL; i++)
580 /* get base and range and set those entries to true */
581 count = level_range(lev->dlevel.dnum, pd->tmplevel[idx].lev.base,
582 pd->tmplevel[idx].lev.rand, pd->tmplevel[idx].chain,
584 for (i = start; i < start + count; i++)
587 /* mark off already placed levels */
588 for (i = pd->start; i < idx; i++) {
589 if (pd->final_lev[i] && map[pd->final_lev[i]->dlevel.dlevel]) {
590 map[pd->final_lev[i]->dlevel.dlevel] = FALSE;
598 /* Pick the nth TRUE entry in the given boolean array. */
601 boolean *map; /* an array MAXLEVEL+1 in size */
605 for (i = 1; i <= MAXLEVEL; i++)
606 if (map[i] && !nth--)
608 panic("pick_level: ran out of valid levels");
613 static void FDECL(indent, (int));
625 * Place a level. First, find the possible places on a dungeon map
626 * template. Next pick one. Then try to place the next level. If
627 * successful, we're done. Otherwise, try another (and another) until
628 * all possible places have been tried. If all possible places have
629 * been exhausted, return false.
632 place_level(proto_index, pd)
634 struct proto_dungeon *pd;
636 boolean map[MAXLEVEL + 1]; /* valid levels are 1..MAXLEVEL inclusive */
643 if (proto_index == pd->n_levs)
644 return TRUE; /* at end of proto levels */
646 lev = pd->final_lev[proto_index];
648 /* No level created for this prototype, goto next. */
650 return place_level(proto_index + 1, pd);
652 npossible = possible_places(proto_index, map, pd);
654 for (; npossible; --npossible) {
655 lev->dlevel.dlevel = pick_level(map, rn2(npossible));
657 indent(proto_index - pd->start);
658 fprintf(stderr, "%s: trying %d [ ", lev->proto, lev->dlevel.dlevel);
659 for (i = 1; i <= MAXLEVEL; i++)
661 fprintf(stderr, "%d ", i);
662 fprintf(stderr, "]\n");
664 if (place_level(proto_index + 1, pd))
666 map[lev->dlevel.dlevel] = FALSE; /* this choice didn't work */
669 indent(proto_index - pd->start);
670 fprintf(stderr, "%s: failed\n", lev->proto);
676 const char *lev_name;
678 } level_map[] = { { "air", &air_level },
679 { "asmodeus", &asmodeus_level },
680 { "astral", &astral_level },
681 { "baalz", &baalzebub_level },
682 { "bigrm", &bigroom_level },
683 { "castle", &stronghold_level },
684 { "earth", &earth_level },
685 { "fakewiz1", &portal_level },
686 { "fire", &fire_level },
687 { "juiblex", &juiblex_level },
688 { "knox", &knox_level },
689 { "medusa", &medusa_level },
690 { "oracle", &oracle_level },
691 { "orcus", &orcus_level },
692 { "rogue", &rogue_level },
693 { "sanctum", &sanctum_level },
694 { "valley", &valley_level },
695 { "water", &water_level },
696 { "wizard1", &wiz1_level },
697 { "wizard2", &wiz2_level },
698 { "wizard3", &wiz3_level },
699 { "minend", &mineend_level },
700 { "soko1", &sokoend_level },
701 { X_START, &qstart_level },
702 { X_LOCATE, &qlocate_level },
703 { X_GOAL, &nemesis_level },
704 { "", (d_level *) 0 } };
706 /* initialize the "dungeon" structs */
711 register int i, cl = 0, cb = 0;
713 struct proto_dungeon pd;
714 struct level_map *lev_map;
715 struct version_info vers_info;
717 pd.n_levs = pd.n_brs = 0;
719 dgn_file = dlb_fopen(DUNGEON_FILE, RDBMODE);
722 Sprintf(tbuf, "Cannot open dungeon description - \"%s", DUNGEON_FILE);
723 #ifdef DLBRSRC /* using a resource from the executable */
724 Strcat(tbuf, "\" resource!");
725 #else /* using a file or DLB file */
727 Strcat(tbuf, "\" from ");
728 #ifdef PREFIXES_IN_USE
729 Strcat(tbuf, "\n\"");
730 if (fqn_prefix[DATAPREFIX])
731 Strcat(tbuf, fqn_prefix[DATAPREFIX]);
735 Strcat(tbuf, DLBFILE);
737 Strcat(tbuf, "\" file!");
740 interject_assistance(1, INTERJECT_PANIC, (genericptr_t) tbuf,
741 (genericptr_t) fqn_prefix[DATAPREFIX]);
746 /* validate the data's version against the program's version */
747 Fread((genericptr_t) &vers_info, sizeof vers_info, 1, dgn_file);
748 /* we'd better clear the screen now, since when error messages come from
749 * check_version() they will be printed using pline(), which doesn't
750 * mix with the raw messages that might be already on the screen
752 if (iflags.window_inited)
753 clear_nhwindow(WIN_MAP);
754 if (!check_version(&vers_info, DUNGEON_FILE, TRUE))
755 panic("Dungeon description not valid.");
758 * Read in each dungeon and transfer the results to the internal
761 sp_levchn = (s_level *) 0;
762 Fread((genericptr_t) &n_dgns, sizeof(int), 1, dgn_file);
763 if (n_dgns >= MAXDUNGEON)
764 panic("init_dungeons: too many dungeons");
766 for (i = 0; i < n_dgns; i++) {
767 Fread((genericptr_t) &pd.tmpdungeon[i], sizeof(struct tmpdungeon), 1,
769 if (!wizard && pd.tmpdungeon[i].chance
770 && (pd.tmpdungeon[i].chance <= rn2(100))) {
773 /* skip over any levels or branches */
774 for (j = 0; j < pd.tmpdungeon[i].levels; j++)
775 Fread((genericptr_t) &pd.tmplevel[cl],
776 sizeof(struct tmplevel), 1, dgn_file);
778 for (j = 0; j < pd.tmpdungeon[i].branches; j++)
779 Fread((genericptr_t) &pd.tmpbranch[cb],
780 sizeof(struct tmpbranch), 1, dgn_file);
786 Strcpy(dungeons[i].dname, pd.tmpdungeon[i].name);
787 Strcpy(dungeons[i].proto, pd.tmpdungeon[i].protoname);
788 dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
790 if (pd.tmpdungeon[i].lev.rand)
791 dungeons[i].num_dunlevs = (xchar) rn1(pd.tmpdungeon[i].lev.rand,
792 pd.tmpdungeon[i].lev.base);
794 dungeons[i].num_dunlevs = (xchar) pd.tmpdungeon[i].lev.base;
797 dungeons[i].ledger_start = 0;
798 dungeons[i].depth_start = 1;
799 dungeons[i].dunlev_ureached = 1;
801 dungeons[i].ledger_start =
802 dungeons[i - 1].ledger_start + dungeons[i - 1].num_dunlevs;
803 dungeons[i].dunlev_ureached = 0;
806 dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH);
807 dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE);
808 dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE);
809 dungeons[i].flags.align =
810 ((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4);
812 * Set the entry level for this dungeon. The pd.tmpdungeon entry
814 * < 0 from bottom (-1 == bottom level)
816 * > 0 actual level (1 = top)
818 * Note that the entry_lev field in the dungeon structure is
819 * redundant. It is used only here and in print_dungeon().
821 if (pd.tmpdungeon[i].entry_lev < 0) {
822 dungeons[i].entry_lev =
823 dungeons[i].num_dunlevs + pd.tmpdungeon[i].entry_lev + 1;
824 if (dungeons[i].entry_lev <= 0)
825 dungeons[i].entry_lev = 1;
826 } else if (pd.tmpdungeon[i].entry_lev > 0) {
827 dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
828 if (dungeons[i].entry_lev > dungeons[i].num_dunlevs)
829 dungeons[i].entry_lev = dungeons[i].num_dunlevs;
830 } else { /* default */
831 dungeons[i].entry_lev = 1; /* defaults to top level */
834 if (i) { /* set depth */
839 br = add_branch(i, dungeons[i].entry_lev, &pd);
841 /* Get the depth of the connecting end. */
842 if (br->end1.dnum == i) {
843 from_depth = depth(&br->end2);
844 from_up = !br->end1_up;
846 from_depth = depth(&br->end1);
847 from_up = br->end1_up;
851 * Calculate the depth of the top of the dungeon via
852 * its branch. First, the depth of the entry point:
854 * depth of branch from "parent" dungeon
855 * + -1 or 1 depending on a up or down stair or
858 * Followed by the depth of the top of the dungeon:
860 * - (entry depth - 1)
862 * We'll say that portals stay on the same depth.
864 dungeons[i].depth_start =
865 from_depth + (br->type == BR_PORTAL ? 0 : (from_up ? -1 : 1))
866 - (dungeons[i].entry_lev - 1);
869 /* this is redundant - it should have been flagged by dgn_comp */
870 if (dungeons[i].num_dunlevs > MAXLEVEL)
871 dungeons[i].num_dunlevs = MAXLEVEL;
873 pd.start = pd.n_levs; /* save starting point */
874 pd.n_levs += pd.tmpdungeon[i].levels;
875 if (pd.n_levs > LEV_LIMIT)
876 panic("init_dungeon: too many special levels");
878 * Read in the prototype special levels. Don't add generated
879 * special levels until they are all placed.
881 for (; cl < pd.n_levs; cl++) {
882 Fread((genericptr_t) &pd.tmplevel[cl], sizeof(struct tmplevel), 1,
884 init_level(i, cl, &pd);
887 * Recursively place the generated levels for this dungeon. This
888 * routine will attempt all possible combinations before giving
891 if (!place_level(pd.start, &pd))
892 panic("init_dungeon: couldn't place levels");
894 fprintf(stderr, "--- end of dungeon %d ---\n", i);
898 for (; pd.start < pd.n_levs; pd.start++)
899 if (pd.final_lev[pd.start])
900 add_level(pd.final_lev[pd.start]);
902 pd.n_brs += pd.tmpdungeon[i].branches;
903 if (pd.n_brs > BRANCH_LIMIT)
904 panic("init_dungeon: too many branches");
905 for (; cb < pd.n_brs; cb++)
906 Fread((genericptr_t) &pd.tmpbranch[cb], sizeof(struct tmpbranch),
909 (void) dlb_fclose(dgn_file);
911 for (i = 0; i < 5; i++)
912 tune[i] = 'A' + rn2(7);
916 * Find most of the special levels and dungeons so we can access their
919 for (lev_map = level_map; lev_map->lev_name[0]; lev_map++) {
920 x = find_level(lev_map->lev_name);
922 assign_level(lev_map->lev_spec, &x->dlevel);
923 if (!strncmp(lev_map->lev_name, "x-", 2)) {
924 /* This is where the name substitution on the
925 * levels of the quest dungeon occur.
927 Sprintf(x->proto, "%s%s", urole.filecode,
928 &lev_map->lev_name[1]);
929 } else if (lev_map->lev_spec == &knox_level) {
932 * Kludge to allow floating Knox entrance. We
933 * specify a floating entrance by the fact that
934 * its entrance (end1) has a bogus dnum, namely
937 for (br = branches; br; br = br->next)
938 if (on_level(&br->end2, &knox_level))
942 br->end1.dnum = n_dgns;
943 /* adjust the branch's position on the list */
944 insert_branch(br, TRUE);
949 * I hate hardwiring these names. :-(
952 quest_dnum = dname_to_dnum("The Quest");
954 quest_dnum = dname_to_dnum("
\83N
\83G
\83X
\83g");
956 sokoban_dnum = dname_to_dnum("Sokoban");
958 sokoban_dnum = dname_to_dnum("
\91q
\8cÉ
\94Ô");
960 mines_dnum = dname_to_dnum("The Gnomish Mines");
962 mines_dnum = dname_to_dnum("
\83m
\81[
\83\80\82Ì
\8dz
\8eR");
964 tower_dnum = dname_to_dnum("Vlad's Tower");
966 tower_dnum = dname_to_dnum("
\83\94\83\89\83h
\8cò
\82Ì
\93\83");
968 /* one special fixup for dummy surface level */
969 if ((x = find_level("dummy")) != 0) {
971 /* the code above puts earth one level above dungeon level #1,
972 making the dummy level overlay level 1; but the whole reason
973 for having the dummy level is to make earth have depth -1
974 instead of 0, so adjust the start point to shift endgame up */
975 if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
976 dungeons[i].depth_start -= 1;
977 /* TO DO: strip "dummy" out all the way here,
978 so that it's hidden from <ctrl/O> feedback. */
986 /* return the level number for lev in *this* dungeon */
994 /* return the lowest level number for *this* dungeon */
996 dunlevs_in_dungeon(lev)
999 return dungeons[lev->dnum].num_dunlevs;
1002 /* return the lowest level explored in the game*/
1004 deepest_lev_reached(noquest)
1007 /* this function is used for three purposes: to provide a factor
1008 * of difficulty in monster generation; to provide a factor of
1009 * difficulty in experience calculations (botl.c and end.c); and
1010 * to insert the deepest level reached in the game in the topten
1011 * display. the 'noquest' arg switch is required for the latter.
1013 * from the player's point of view, going into the Quest is _not_
1014 * going deeper into the dungeon -- it is going back "home", where
1015 * the dungeon starts at level 1. given the setup in dungeon.def,
1016 * the depth of the Quest (thought of as starting at level 1) is
1017 * never lower than the level of entry into the Quest, so we exclude
1018 * the Quest from the topten "deepest level reached" display
1019 * calculation. _However_ the Quest is a difficult dungeon, so we
1020 * include it in the factor of difficulty calculations.
1024 register schar ret = 0;
1026 for (i = 0; i < n_dgns; i++) {
1027 if (noquest && i == quest_dnum)
1029 tmp.dlevel = dungeons[i].dunlev_ureached;
1030 if (tmp.dlevel == 0)
1033 if (depth(&tmp) > ret)
1039 /* return a bookkeeping level number for purpose of comparisons and
1045 return (xchar) (lev->dlevel + dungeons[lev->dnum].ledger_start);
1049 * The last level in the bookkeeping list of level is the bottom of the last
1050 * dungeon in the dungeons[] array.
1052 * Maxledgerno() -- which is the max number of levels in the bookkeeping
1053 * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1054 * returns the max number of levels in lev's dungeon, and both should
1055 * not be confused with deepest_lev_reached() -- which returns the lowest
1056 * depth visited by the player.
1061 return (xchar) (dungeons[n_dgns - 1].ledger_start
1062 + dungeons[n_dgns - 1].num_dunlevs);
1065 /* return the dungeon that this ledgerno exists in */
1067 ledger_to_dnum(ledgerno)
1072 /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1073 for (i = 0; i < n_dgns; i++)
1074 if (dungeons[i].ledger_start < ledgerno
1075 && ledgerno <= dungeons[i].ledger_start + dungeons[i].num_dunlevs)
1078 panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno);
1083 /* return the level of the dungeon this ledgerno exists in */
1085 ledger_to_dlev(ledgerno)
1088 return (xchar) (ledgerno
1089 - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
1092 /* returns the depth of a level, in floors below the surface
1093 (note levels in different dungeons can have the same depth) */
1098 return (schar) (dungeons[lev->dnum].depth_start + lev->dlevel - 1);
1101 /* are "lev1" and "lev2" actually the same? */
1103 on_level(lev1, lev2)
1104 d_level *lev1, *lev2;
1106 return (boolean) (lev1->dnum == lev2->dnum
1107 && lev1->dlevel == lev2->dlevel);
1110 /* is this level referenced in the special level chain? */
1117 for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
1118 if (on_level(lev, &levtmp->dlevel))
1121 return (s_level *) 0;
1125 * Is this a multi-dungeon branch level? If so, return a pointer to the
1126 * branch. Otherwise, return null.
1134 for (curr = branches; curr; curr = curr->next) {
1135 if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
1138 return (branch *) 0;
1141 /* returns True iff the branch 'lev' is in a branch which builds up */
1146 dungeon *dptr = &dungeons[lev->dnum];
1148 * FIXME: this misclassifies a single level branch reached via stairs
1149 * from below. Saving grace is that no such branches currently exist.
1151 return (boolean) (dptr->num_dunlevs > 1
1152 && dptr->entry_lev == dptr->num_dunlevs);
1155 /* goto the next level (or appropriate dungeon) */
1157 next_level(at_stairs)
1160 if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1161 /* Taking a down dungeon branch. */
1162 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1164 /* Going down a stairs or jump in a trap door. */
1167 newlevel.dnum = u.uz.dnum;
1168 newlevel.dlevel = u.uz.dlevel + 1;
1169 goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
1173 /* goto the previous level (or appropriate dungeon) */
1175 prev_level(at_stairs)
1178 if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1179 /* Taking an up dungeon branch. */
1180 /* KMH -- Upwards branches are okay if not level 1 */
1181 /* (Just make sure it doesn't go above depth 1) */
1182 if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
1185 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1187 /* Going up a stairs or rising through the ceiling. */
1189 newlevel.dnum = u.uz.dnum;
1190 newlevel.dlevel = u.uz.dlevel - 1;
1191 goto_level(&newlevel, at_stairs, FALSE, FALSE);
1202 cliparound(u.ux, u.uy);
1204 /* ridden steed always shares hero's location */
1206 u.usteed->mx = u.ux, u.usteed->my = u.uy;
1207 /* when changing levels, don't leave old position set with
1208 stale values from previous level */
1209 if (!on_level(&u.uz, &u.uz0))
1210 u.ux0 = u.ux, u.uy0 = u.uy;
1213 /* place you on a random location */
1215 u_on_rndspot(upflag)
1218 int up = (upflag & 1), was_in_W_tower = (upflag & 2);
1221 * Place the hero at a random location within the relevant region.
1222 * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1223 * Unspecified region (.lx == 0) defaults to entire level.
1225 if (was_in_W_tower && On_W_tower_level(&u.uz))
1226 /* Stay inside the Wizard's tower when feasible.
1227 We use the W Tower's exclusion region for the
1228 destination instead of its enclosing region.
1229 Note: up vs down doesn't matter in this case
1230 because both specify the same exclusion area. */
1231 place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy, 0, 0, 0,
1232 0, LR_DOWNTELE, (d_level *) 0);
1234 place_lregion(updest.lx, updest.ly, updest.hx, updest.hy, updest.nlx,
1235 updest.nly, updest.nhx, updest.nhy, LR_UPTELE,
1238 place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy, dndest.nlx,
1239 dndest.nly, dndest.nhx, dndest.nhy, LR_DOWNTELE,
1243 /* place you on the special staircase */
1245 u_on_sstairs(upflag)
1249 u_on_newpos(sstairs.sx, sstairs.sy);
1251 u_on_rndspot(upflag);
1254 /* place you on upstairs (or special equivalent) */
1259 u_on_newpos(xupstair, yupstair);
1261 u_on_sstairs(0); /* destination upstairs implies moving down */
1264 /* place you on dnstairs (or special equivalent) */
1269 u_on_newpos(xdnstair, ydnstair);
1271 u_on_sstairs(1); /* destination dnstairs implies moving up */
1278 return (boolean) ((x == xupstair && y == yupstair)
1279 || (x == xdnstair && y == ydnstair)
1280 || (x == xdnladder && y == ydnladder)
1281 || (x == xupladder && y == yupladder)
1282 || (x == sstairs.sx && y == sstairs.sy));
1289 return (boolean) (lev->dlevel == dungeons[lev->dnum].num_dunlevs);
1296 return (boolean) (!level.flags.hardfloor
1297 && !Is_botlevel(lev)
1298 && !Invocation_lev(lev));
1302 * Like Can_dig_down (above), but also allows falling through on the
1303 * stronghold level. Normally, the bottom level of a dungeon resists
1304 * both digging and falling.
1310 return (boolean) (Can_dig_down(lev) || Is_stronghold(lev));
1314 * True if one can rise up a level (e.g. cursed gain level).
1315 * This happens on intermediate dungeon levels or on any top dungeon
1316 * level that has a stairwell style branch to the next higher dungeon.
1317 * Checks for amulets and such must be done elsewhere.
1320 Can_rise_up(x, y, lev)
1324 /* can't rise up from inside the top of the Wizard's tower */
1325 /* KMH -- or in sokoban */
1326 if (In_endgame(lev) || In_sokoban(lev)
1327 || (Is_wiz1_level(lev) && In_W_tower(x, y, lev)))
1329 return (boolean) (lev->dlevel > 1
1330 || (dungeons[lev->dnum].entry_lev == 1
1331 && ledger_no(lev) != 1
1332 && sstairs.sx && sstairs.up));
1339 /* [what about level 1 of the quest?] */
1340 return (boolean) (!Is_airlevel(lev) && !Is_waterlevel(lev));
1344 * It is expected that the second argument of get_level is a depth value,
1345 * either supplied by the user (teleport control) or randomly generated.
1346 * But more than one level can be at the same depth. If the target level
1347 * is "above" the present depth location, get_level must trace "up" from
1348 * the player's location (through the ancestors dungeons) the dungeon
1349 * within which the target level is located. With only one exception
1350 * which does not pass through this routine (see level_tele), teleporting
1351 * "down" is confined to the current dungeon. At present, level teleport
1352 * in dungeons that build up is confined within them.
1355 get_level(newlevel, levnum)
1360 xchar dgn = u.uz.dnum;
1363 /* can only currently happen in endgame */
1364 levnum = u.uz.dlevel;
1366 > dungeons[dgn].depth_start + dungeons[dgn].num_dunlevs - 1) {
1367 /* beyond end of dungeon, jump to last level */
1368 levnum = dungeons[dgn].num_dunlevs;
1370 /* The desired level is in this dungeon or a "higher" one. */
1373 * Branch up the tree until we reach a dungeon that contains the
1376 if (levnum < dungeons[dgn].depth_start) {
1379 * Find the parent dungeon of this dungeon.
1381 * This assumes that end2 is always the "child" and it is
1384 for (br = branches; br; br = br->next)
1385 if (br->end2.dnum == dgn)
1388 panic("get_level: can't find parent dungeon");
1390 dgn = br->end1.dnum;
1391 } while (levnum < dungeons[dgn].depth_start);
1394 /* We're within the same dungeon; calculate the level. */
1395 levnum = levnum - dungeons[dgn].depth_start + 1;
1398 newlevel->dnum = dgn;
1399 newlevel->dlevel = levnum;
1402 /* are you in the quest dungeon? */
1407 return (boolean) (lev->dnum == quest_dnum);
1410 /* are you in the mines dungeon? */
1415 return (boolean) (lev->dnum == mines_dnum);
1419 * Return the branch for the given dungeon.
1421 * This function assumes:
1422 * + This is not called with "Dungeons of Doom".
1423 * + There is only _one_ branch to a given dungeon.
1424 * + Field end2 is the "child" dungeon.
1433 dnum = dname_to_dnum(s);
1435 /* Find the branch that connects to dungeon i's branch. */
1436 for (br = branches; br; br = br->next)
1437 if (br->end2.dnum == dnum)
1441 panic("dgn_entrance: can't find entrance to %s", s);
1447 * This returns true if the hero is on the same level as the entrance to
1448 * the named dungeon.
1450 * Called from do.c and mklev.c.
1452 * Assumes that end1 is always the "parent".
1460 br = dungeon_branch(s);
1461 return on_level(&u.uz, &br->end1) ? TRUE : FALSE;
1464 /* is `lev' part of Vlad's tower? */
1469 return (boolean) (lev->dnum == tower_dnum);
1472 /* is `lev' a level containing the Wizard's tower? */
1474 On_W_tower_level(lev)
1477 return (boolean) (Is_wiz1_level(lev)
1478 || Is_wiz2_level(lev)
1479 || Is_wiz3_level(lev));
1482 /* is <x,y> of `lev' inside the Wizard's tower? */
1484 In_W_tower(x, y, lev)
1488 if (!On_W_tower_level(lev))
1491 * Both of the exclusion regions for arriving via level teleport
1492 * (from above or below) define the tower's boundary.
1493 * assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1496 return (boolean) within_bounded_area(x, y, dndest.nlx, dndest.nly,
1497 dndest.nhx, dndest.nhy);
1499 impossible("No boundary for Wizard's Tower?");
1503 /* are you in one of the Hell levels? */
1508 return (boolean) (dungeons[lev->dnum].flags.hellish);
1511 /* sets *lev to be the gateway to Gehennom... */
1516 lev->dnum = valley_level.dnum;
1520 /* go directly to hell... */
1522 goto_hell(at_stairs, falling)
1523 boolean at_stairs, falling;
1528 goto_level(&lev, at_stairs, falling, FALSE);
1531 /* equivalent to dest = source */
1533 assign_level(dest, src)
1534 d_level *dest, *src;
1536 dest->dnum = src->dnum;
1537 dest->dlevel = src->dlevel;
1540 /* dest = src + rn1(range) */
1542 assign_rnd_level(dest, src, range)
1543 d_level *dest, *src;
1546 dest->dnum = src->dnum;
1547 dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range));
1549 if (dest->dlevel > dunlevs_in_dungeon(dest))
1550 dest->dlevel = dunlevs_in_dungeon(dest);
1551 else if (dest->dlevel < 1)
1559 s_level *lev = Is_special(&u.uz);
1562 if (lev && lev->flags.align)
1564 return lev->flags.align;
1566 if (dungeons[u.uz.dnum].flags.align)
1568 return dungeons[u.uz.dnum].flags.align;
1571 return Align2amask(al);
1578 return (boolean) (In_hell(lev)
1579 && lev->dlevel == dungeons[lev->dnum].num_dunlevs - 1);
1582 /* use instead of depth() wherever a degree of difficulty is made
1583 * dependent on the location in the dungeon (eg. monster creation).
1590 if (In_endgame(&u.uz)) {
1591 res = depth(&sanctum_level) + u.ulevel / 2;
1592 } else if (u.uhave.amulet) {
1593 res = deepest_lev_reached(FALSE);
1596 /* depth() is the number of elevation units (levels) below
1597 the theoretical surface; in a builds-up branch, that value
1598 ends up making the harder to reach levels be treated as if
1599 they were easier; adjust for the extra effort involved in
1600 going down to the entrance and then up to the location */
1601 if (builds_up(&u.uz))
1602 res += 2 * (dungeons[u.uz.dnum].entry_lev - u.uz.dlevel + 1);
1604 * 'Proof' by example: suppose the entrance to sokoban is
1605 * on dungeon level 9, leading up to bottom sokoban level
1606 * of 8 [entry_lev]. When the hero is on sokoban level 8
1607 * [uz.dlevel], depth() yields eight but he has ventured
1608 * one level beyond 9, so difficulty depth should be 10:
1609 * 8 + 2 * (8 - 8 + 1) => 10.
1610 * Going up to 7, depth is 7 but hero will be two beyond 9:
1611 * 7 + 2 * (8 - 7 + 1) => 11.
1612 * When he goes up to level 6, three levels beyond 9:
1613 * 6 + 2 * (8 - 6 + 1) => 12.
1614 * And the top level of sokoban at 5, four levels beyond 9:
1615 * 5 + 2 * (8 - 5 + 1) => 13.
1616 * The same applies to Vlad's Tower, although the increment
1617 * there is inconsequential compared to overall depth.
1623 /* Take one word and try to match it to a level.
1624 * Recognized levels are as shown by print_dungeon().
1637 /* allow strings like "the oracle level" to find "oracle" */
1638 if (!strncmpi(nam, "the ", 4))
1640 if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
1641 nam = strcpy(buf, nam);
1642 *(eos(buf) - 6) = '\0';
1644 /* hell is the old name, and wouldn't match; gehennom would match its
1645 branch, yielding the castle level instead of the valley of the dead */
1646 if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1647 if (In_V_tower(&u.uz))
1648 nam = " to Vlad's tower"; /* branch to... */
1653 if ((slev = find_level(nam)) != 0) {
1654 dlev = slev->dlevel;
1655 idx = ledger_no(&dlev);
1656 if ((dlev.dnum == u.uz.dnum
1657 /* within same branch, or else main dungeon <-> gehennom */
1658 || (u.uz.dnum == valley_level.dnum
1659 && dlev.dnum == medusa_level.dnum)
1660 || (u.uz.dnum == medusa_level.dnum
1661 && dlev.dnum == valley_level.dnum))
1662 && (/* either wizard mode or else seen and not forgotten */
1664 || (level_info[idx].flags & (FORGOTTEN | VISITED))
1666 lev = depth(&slev->dlevel);
1668 } else { /* not a specific level; try branch names */
1669 idx = find_branch(nam, (struct proto_dungeon *) 0);
1670 /* "<branch> to Xyzzy" */
1671 if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1672 idx = find_branch(p + 4, (struct proto_dungeon *) 0);
1675 idxtoo = (idx >> 8) & 0x00FF;
1677 if (/* either wizard mode, or else _both_ sides of branch seen */
1679 || ((level_info[idx].flags & (FORGOTTEN | VISITED)) == VISITED
1680 && (level_info[idxtoo].flags & (FORGOTTEN | VISITED))
1682 if (ledger_to_dnum(idxtoo) == u.uz.dnum)
1684 dlev.dnum = ledger_to_dnum(idx);
1685 dlev.dlevel = ledger_to_dlev(idx);
1694 unplaced_floater(dptr)
1695 struct dungeon *dptr;
1698 int idx = (int) (dptr - dungeons);
1700 /* if other floating branches are added, this will need to change */
1701 if (idx != knox_level.dnum)
1703 for (br = branches; br; br = br->next)
1704 if (br->end1.dnum == n_dgns && br->end2.dnum == idx)
1710 unreachable_level(lvl_p, unplaced)
1718 if (In_endgame(&u.uz) && !In_endgame(lvl_p))
1720 if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
1726 tport_menu(win, entry, lchoices, lvl_p, unreachable)
1729 struct lchoice *lchoices;
1731 boolean unreachable;
1736 lchoices->lev[lchoices->idx] = lvl_p->dlevel;
1737 lchoices->dgn[lchoices->idx] = lvl_p->dnum;
1738 lchoices->playerlev[lchoices->idx] = depth(lvl_p);
1741 /* not selectable, but still consumes next menuletter;
1742 prepend padding in place of missing menu selector */
1743 Sprintf(tmpbuf, " %s", entry);
1746 any.a_int = lchoices->idx + 1;
1748 add_menu(win, NO_GLYPH, &any, lchoices->menuletter, 0, ATR_NONE, entry,
1750 /* this assumes there are at most 52 interesting levels */
1751 if (lchoices->menuletter == 'z')
1752 lchoices->menuletter = 'A';
1754 lchoices->menuletter++;
1759 /* Convert a branch type to a string usable by print_dungeon(). */
1760 STATIC_OVL const char *
1768 return "Connection";
1770 return "One way stair";
1774 return " (unknown)";
1777 /* Print all child branches between the lower and upper bounds. */
1779 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
1785 struct lchoice *lchoices_p;
1790 /* This assumes that end1 is the "parent". */
1791 for (br = branches; br; br = br->next) {
1792 if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
1793 && br->end1.dlevel <= upper_bound) {
1794 Sprintf(buf, " %s to %s: %d", br_string(br->type),
1795 dungeons[br->end2.dnum].dname, depth(&br->end1));
1797 tport_menu(win, buf, lchoices_p, &br->end1,
1798 unreachable_level(&br->end1, FALSE));
1800 putstr(win, 0, buf);
1805 /* Print available dungeon information. */
1807 print_dungeon(bymenu, rlev, rdgn)
1812 int i, last_level, nlev;
1815 boolean first, unplaced;
1820 struct lchoice lchoices;
1822 winid win = create_nhwindow(NHW_MENU);
1826 lchoices.menuletter = 'a';
1829 for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1830 if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum)
1832 unplaced = unplaced_floater(dptr);
1833 descr = unplaced ? "depth" : "level";
1834 nlev = dptr->num_dunlevs;
1836 Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
1837 dptr->depth_start, dptr->depth_start + nlev - 1);
1839 Sprintf(buf, "%s: %s %d", dptr->dname, descr, dptr->depth_start);
1841 /* Most entrances are uninteresting. */
1842 if (dptr->entry_lev != 1) {
1843 if (dptr->entry_lev == nlev)
1844 Strcat(buf, ", entrance from below");
1846 Sprintf(eos(buf), ", entrance on %d",
1847 dptr->depth_start + dptr->entry_lev - 1);
1851 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
1854 putstr(win, 0, buf);
1857 * Circle through the special levels to find levels that are in
1860 for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1861 if (slev->dlevel.dnum != i)
1864 /* print any branches before this level */
1865 print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
1868 Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel));
1869 if (Is_stronghold(&slev->dlevel))
1870 Sprintf(eos(buf), " (tune %s)", tune);
1872 tport_menu(win, buf, &lchoices, &slev->dlevel,
1873 unreachable_level(&slev->dlevel, unplaced));
1875 putstr(win, 0, buf);
1877 last_level = slev->dlevel.dlevel;
1879 /* print branches after the last special level */
1880 print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1885 menu_item *selected;
1888 end_menu(win, "Level teleport to where:");
1889 n = select_menu(win, PICK_ONE, &selected);
1890 destroy_nhwindow(win);
1892 idx = selected[0].item.a_int - 1;
1893 free((genericptr_t) selected);
1895 *rlev = lchoices.lev[idx];
1896 *rdgn = lchoices.dgn[idx];
1897 return lchoices.playerlev[idx];
1903 /* Print out floating branches (if any). */
1904 for (first = TRUE, br = branches; br; br = br->next) {
1905 if (br->end1.dnum == n_dgns) {
1908 putstr(win, 0, "Floating branches");
1911 Sprintf(buf, " %s to %s", br_string(br->type),
1912 dungeons[br->end2.dnum].dname);
1913 putstr(win, 0, buf);
1917 /* I hate searching for the invocation pos while debugging. -dean */
1918 if (Invocation_lev(&u.uz)) {
1920 Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1921 inv_pos.x, inv_pos.y, u.ux, u.uy);
1922 putstr(win, 0, buf);
1925 * The following is based on the assumption that the inter-level portals
1926 * created by the level compiler (not the dungeon compiler) only exist
1927 * one per level (currently true, of course).
1929 else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
1930 || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
1932 for (trap = ftrap; trap; trap = trap->ntrap)
1933 if (trap->ttyp == MAGIC_PORTAL)
1938 Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)", trap->tx,
1939 trap->ty, u.ux, u.uy);
1941 Sprintf(buf, "No portal found.");
1942 putstr(win, 0, buf);
1945 display_nhwindow(win, TRUE);
1946 destroy_nhwindow(win);
1950 /* Record that the player knows about a branch from a level. This function
1951 * will determine whether or not it was a "real" branch that was taken.
1952 * This function should not be called for a transition done via level
1953 * teleport or via the Eye.
1956 recbranch_mapseen(source, dest)
1964 if (source->dnum == dest->dnum)
1967 /* we only care about forward branches */
1968 for (br = branches; br; br = br->next) {
1969 if (on_level(source, &br->end1) && on_level(dest, &br->end2))
1971 if (on_level(source, &br->end2) && on_level(dest, &br->end1))
1975 /* branch not found, so not a real branch. */
1979 if ((mptr = find_mapseen(source)) != 0) {
1980 if (mptr->br && br != mptr->br)
1981 impossible("Two branches on the same level?");
1984 impossible("Can't note branch for unseen level (%d, %d)",
1985 source->dnum, source->dlevel);
1995 if ((mptr = find_mapseen(lev)))
1996 return mptr->custom;
2000 /* #annotate command - add a custom name to the current level */
2005 char nbuf[BUFSZ]; /* Buffer for response */
2007 if (!(mptr = find_mapseen(&u.uz)))
2012 Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
2013 strlen(mptr->custom) > 30 ? "..." : "");
2014 getlin(tmpbuf, nbuf);
2016 getlin("What do you want to call this dungeon level?", nbuf);
2017 if (index(nbuf, '\033'))
2019 (void) mungspaces(nbuf);
2021 /* discard old annotation, if any */
2023 free((genericptr_t) mptr->custom);
2024 mptr->custom = (char *) 0;
2025 mptr->custom_lth = 0;
2027 /* add new annotation, unless it's empty or a single space */
2028 if (*nbuf && strcmp(nbuf, " ")) {
2029 mptr->custom = dupstr(nbuf);
2030 mptr->custom_lth = strlen(mptr->custom);
2035 /* find the particular mapseen object in the chain; may return null */
2036 STATIC_OVL mapseen *
2042 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2043 if (on_level(&(mptr->lev), lev))
2050 forget_mapseen(ledger_num)
2054 struct cemetery *bp;
2056 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2057 if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
2061 /* if not found, then nothing to forget */
2063 mptr->flags.forgot = 1;
2064 mptr->br = (branch *) 0;
2066 /* custom names are erased, not just forgotten until revisited */
2068 mptr->custom_lth = 0;
2069 free((genericptr_t) mptr->custom);
2070 mptr->custom = (char *) 0;
2072 (void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
2073 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2074 bp->bonesknown = FALSE;
2079 save_mapseen(fd, mptr)
2086 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2087 if (curr == mptr->br)
2089 bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
2091 bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
2092 bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
2093 bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
2094 bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
2095 if (mptr->custom_lth)
2096 bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
2097 bwrite(fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
2098 savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
2101 STATIC_OVL mapseen *
2105 int branchnum, brindx;
2109 load = (mapseen *) alloc(sizeof *load);
2111 mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
2112 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2113 if (brindx == branchnum)
2117 mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
2118 mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
2119 mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
2120 mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
2121 if (load->custom_lth) {
2122 /* length doesn't include terminator (which isn't saved & restored) */
2123 load->custom = (char *) alloc(load->custom_lth + 1);
2124 mread(fd, (genericptr_t) load->custom, load->custom_lth);
2125 load->custom[load->custom_lth] = '\0';
2128 mread(fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
2129 restcemetery(fd, &load->final_resting_place);
2134 /* Remove all mapseen objects for a particular dnum.
2135 * Useful during quest expulsion to remove quest levels.
2136 * [No longer deleted, just marked as unreachable. #overview will
2137 * ignore such levels, end of game disclosure will include them.]
2140 remdun_mapseen(dnum)
2143 mapseen *mptr, **mptraddr;
2145 mptraddr = &mapseenchn;
2146 while ((mptr = *mptraddr) != 0) {
2147 if (mptr->lev.dnum == dnum) {
2148 #if 1 /* use this... */
2149 mptr->flags.unreachable = 1;
2151 #else /* old deletion code */
2152 *mptraddr = mptr->next;
2154 free((genericptr_t) mptr->custom);
2155 if (mptr->final_resting_place)
2156 savecemetery(-1, FREE_SAVE, &mptr->final_resting_place);
2157 free((genericptr_t) mptr);
2160 mptraddr = &mptr->next;
2168 /* Create a level and insert in "sorted" order. This is an insertion
2169 * sort first by dungeon (in order of discovery) and then by level number.
2171 mapseen *mptr, *init, *prev;
2173 init = (mapseen *) alloc(sizeof *init);
2174 (void) memset((genericptr_t) init, 0, sizeof *init);
2175 /* memset is fine for feature bits, flags, and rooms array;
2176 explicitly initialize pointers to null */
2177 init->next = 0, init->br = 0, init->custom = 0;
2178 init->final_resting_place = 0;
2179 /* lastseentyp[][] is reused for each level, so get rid of
2180 previous level's data */
2181 (void) memset((genericptr_t) lastseentyp, 0, sizeof lastseentyp);
2183 init->lev.dnum = lev->dnum;
2184 init->lev.dlevel = lev->dlevel;
2186 /* walk until we get to the place where we should insert init */
2187 for (mptr = mapseenchn, prev = 0; mptr; prev = mptr, mptr = mptr->next)
2188 if (mptr->lev.dnum > init->lev.dnum
2189 || (mptr->lev.dnum == init->lev.dnum
2190 && mptr->lev.dlevel > init->lev.dlevel))
2193 init->next = mapseenchn;
2202 #define INTEREST(feat) \
2203 ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2204 || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2205 /* || (feat).water || (feat).ice || (feat).lava */
2207 /* returns true if this level has something interesting to print out */
2209 interest_mapseen(mptr)
2212 if (on_level(&u.uz, &mptr->lev))
2214 if (mptr->flags.unreachable || mptr->flags.forgot)
2216 /* level is of interest if it has an auto-generated annotation */
2217 if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
2218 || mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
2219 || mptr->flags.quest_summons || mptr->flags.questing)
2221 /* when in Sokoban, list all sokoban levels visited; when not in it,
2222 list any visited Sokoban level which remains unsolved (will usually
2223 only be furthest one reached, but it's possible to enter pits and
2224 climb out on the far side on the first Sokoban level; also, wizard
2225 mode overrides teleport restrictions) */
2226 if (In_sokoban(&mptr->lev)
2227 && (In_sokoban(&u.uz) || !mptr->flags.sokosolved))
2229 /* when in the endgame, list all endgame levels visited, whether they
2230 have annotations or not, so that #overview doesn't become extremely
2231 sparse once the rest of the dungeon has been flagged as unreachable */
2232 if (In_endgame(&u.uz))
2233 return (boolean) In_endgame(&mptr->lev);
2234 /* level is of interest if it has non-zero feature count or known bones
2235 or user annotation or known connection to another dungeon branch
2236 or is the furthest level reached in its branch */
2237 return (boolean) (INTEREST(mptr->feat)
2238 || (mptr->final_resting_place
2239 && (mptr->flags.knownbones || wizard))
2240 || mptr->custom || mptr->br
2241 || (mptr->lev.dlevel
2242 == dungeons[mptr->lev.dnum].dunlev_ureached));
2245 /* recalculate mapseen for the current level */
2251 struct cemetery *bp, **bonesaddr;
2253 int x, y, ltyp, count, atmp;
2255 /* Should not happen in general, but possible if in the process
2256 * of being booted from the quest. The mapseen object gets
2257 * removed during the expulsion but prior to leaving the level
2258 * [Since quest expulsion no longer deletes quest mapseen data,
2259 * null return from find_mapseen() should now be impossible.]
2261 if (!(mptr = find_mapseen(&u.uz)))
2264 /* reset all features; mptr->feat.* = 0; */
2265 (void) memset((genericptr_t) &mptr->feat, 0, sizeof mptr->feat);
2266 /* reset most flags; some level-specific ones are left as-is */
2267 if (mptr->flags.unreachable) {
2268 mptr->flags.unreachable = 0; /* reached it; Eye of the Aethiopica? */
2269 if (In_quest(&u.uz)) {
2270 mapseen *mptrtmp = mapseenchn;
2272 /* when quest was unreachable due to ejection and portal removal,
2273 getting back to it via arti-invoke should revive annotation
2274 data for all quest levels, not just the one we're on now */
2276 if (mptrtmp->lev.dnum == mptr->lev.dnum)
2277 mptrtmp->flags.unreachable = 0;
2278 mptrtmp = mptrtmp->next;
2282 mptr->flags.knownbones = 0;
2283 mptr->flags.sokosolved = In_sokoban(&u.uz) && !Sokoban;
2284 /* mptr->flags.bigroom retains previous value when hero can't see */
2286 mptr->flags.bigroom = Is_bigroom(&u.uz);
2287 else if (mptr->flags.forgot)
2288 mptr->flags.bigroom = 0;
2289 mptr->flags.roguelevel = Is_rogue_level(&u.uz);
2290 mptr->flags.oracle = 0; /* recalculated during room traversal below */
2291 mptr->flags.castletune = 0;
2292 /* flags.castle, flags.valley, flags.msanctum retain previous value */
2293 mptr->flags.forgot = 0;
2294 /* flags.quest_summons disabled once quest finished */
2296 mptr->flags.quest_summons = (at_dgn_entrance("The Quest")
2298 mptr->flags.quest_summons = (at_dgn_entrance("
\83N
\83G
\83X
\83g")
2300 && !(u.uevent.qcompleted
2301 || u.uevent.qexpelled
2302 || quest_status.leader_is_dead));
2303 mptr->flags.questing = (on_level(&u.uz, &qstart_level)
2304 && quest_status.got_quest);
2306 /* track rooms the hero is in */
2307 for (i = 0; i < SIZE(u.urooms); ++i) {
2311 ridx = u.urooms[i] - ROOMOFFSET;
2312 mptr->msrooms[ridx].seen = 1;
2313 mptr->msrooms[ridx].untended =
2314 (rooms[ridx].rtype >= SHOPBASE)
2315 ? (!(mtmp = shop_keeper(u.urooms[i])) || !inhishop(mtmp))
2316 : (rooms[ridx].rtype == TEMPLE)
2317 ? (!(mtmp = findpriest(u.urooms[i]))
2318 || !inhistemple(mtmp))
2322 /* recalculate room knowledge: for now, just shops and temples
2323 * this could be extended to an array of 0..SHOPBASE
2325 for (i = 0; i < SIZE(mptr->msrooms); ++i) {
2326 if (mptr->msrooms[i].seen) {
2327 if (rooms[i].rtype >= SHOPBASE) {
2328 if (mptr->msrooms[i].untended)
2329 mptr->feat.shoptype = SHOPBASE - 1;
2330 else if (!mptr->feat.nshop)
2331 mptr->feat.shoptype = rooms[i].rtype;
2332 else if (mptr->feat.shoptype != (unsigned) rooms[i].rtype)
2333 mptr->feat.shoptype = 0;
2334 count = mptr->feat.nshop + 1;
2336 mptr->feat.nshop = count;
2337 } else if (rooms[i].rtype == TEMPLE) {
2338 /* altar and temple alignment handled below */
2339 count = mptr->feat.ntemple + 1;
2341 mptr->feat.ntemple = count;
2342 } else if (rooms[i].orig_rtype == DELPHI) {
2343 mptr->flags.oracle = 1;
2348 /* Update lastseentyp with typ if and only if it is in sight or the
2349 * hero can feel it on their current location (i.e. not levitating).
2350 * This *should* give the "last known typ" for each dungeon location.
2351 * (At the very least, it's a better assumption than determining what
2352 * the player knows from the glyph and the typ (which is isn't quite
2353 * enough information in some cases)).
2355 * It was reluctantly added to struct rm to track. Alternatively
2356 * we could track "features" and then update them all here, and keep
2357 * track of when new features are created or destroyed, but this
2358 * seemed the most elegant, despite adding more data to struct rm.
2359 * [3.6.0: we're using lastseentyp[][] rather than level.locations
2360 * to track the features seen.]
2362 * Although no current windowing systems (can) do this, this would add
2363 * the ability to have non-dungeon glyphs float above the last known
2364 * dungeon glyph (i.e. items on fountains).
2366 for (x = 1; x < COLNO; x++) {
2367 for (y = 0; y < ROWNO; y++) {
2368 if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
2369 ltyp = levl[x][y].typ;
2370 if (ltyp == DRAWBRIDGE_UP)
2371 ltyp = db_under_typ(levl[x][y].drawbridgemask);
2372 if ((mtmp = m_at(x, y)) != 0
2373 && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
2374 ltyp = cmap_to_type(mtmp->mappearance);
2375 lastseentyp[x][y] = ltyp;
2378 switch (lastseentyp[x][y]) {
2381 count = mptr->feat.ice + 1;
2383 mptr->feat.ice = count;
2388 count = mptr->feat.water + 1;
2390 mptr->feat.water = count;
2393 count = mptr->feat.lava + 1;
2395 mptr->feat.lava = count;
2399 count = mptr->feat.ntree + 1;
2401 mptr->feat.ntree = count;
2404 count = mptr->feat.nfount + 1;
2406 mptr->feat.nfount = count;
2409 count = mptr->feat.nthrone + 1;
2411 mptr->feat.nthrone = count;
2414 count = mptr->feat.nsink + 1;
2416 mptr->feat.nsink = count;
2419 count = mptr->feat.ngrave + 1;
2421 mptr->feat.ngrave = count;
2424 atmp = (Is_astralevel(&u.uz)
2425 && (levl[x][y].seenv & SVALL) != SVALL)
2427 : Amask2msa(levl[x][y].altarmask);
2428 if (!mptr->feat.naltar)
2429 mptr->feat.msalign = atmp;
2430 else if (mptr->feat.msalign != atmp)
2431 mptr->feat.msalign = MSA_NONE;
2432 count = mptr->feat.naltar + 1;
2434 mptr->feat.naltar = count;
2436 /* An automatic annotation is added to the Castle and
2437 * to Fort Ludios once their structure's main entrance
2438 * has been seen (in person or via magic mapping).
2439 * DOOR: possibly a lowered drawbridge's open portcullis;
2440 * DBWALL: a raised drawbridge's "closed door";
2441 * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2442 * with moat or other terrain hidden underneath;
2443 * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2444 * not recognizable as a bridge location unless/until
2445 * the adjacent DBWALL has been seen.
2448 if (is_drawbridge_wall(x, y) < 0)
2452 case DRAWBRIDGE_DOWN:
2453 if (Is_stronghold(&u.uz))
2454 mptr->flags.castle = 1, mptr->flags.castletune = 1;
2455 else if (Is_knox(&u.uz))
2456 mptr->flags.ludios = 1;
2464 if (level.bonesinfo && !mptr->final_resting_place) {
2465 /* clone the bonesinfo so we aren't dependent upon this
2466 level being in memory */
2467 bonesaddr = &mptr->final_resting_place;
2468 bp = level.bonesinfo;
2470 *bonesaddr = (struct cemetery *) alloc(sizeof **bonesaddr);
2473 bonesaddr = &(*bonesaddr)->next;
2477 /* decide which past hero deaths have become known; there's no
2478 guarantee of either a grave or a ghost, so we go by whether the
2479 current hero has seen the map location where each old one died */
2480 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2481 if (lastseentyp[bp->frpx][bp->frpy]) {
2482 bp->bonesknown = TRUE;
2483 mptr->flags.knownbones = 1;
2488 /* valley and sanctum levels get automatic annotation once temple is entered
2491 mapseen_temple(priest)
2492 struct monst *priest UNUSED; /* currently unused; might be useful someday */
2494 mapseen *mptr = find_mapseen(&u.uz);
2496 if (Is_valley(&u.uz))
2497 mptr->flags.valley = 1;
2498 else if (Is_sanctum(&u.uz))
2499 mptr->flags.msanctum = 1;
2502 /* room entry message has just been delivered so learn room even if blind */
2504 room_discovered(roomno)
2507 mapseen *mptr = find_mapseen(&u.uz);
2509 mptr->msrooms[roomno].seen = 1;
2512 /* #overview command */
2516 show_overview(0, 0);
2520 /* called for #overview or for end of game disclosure */
2522 show_overview(why, reason)
2523 int why; /* 0 => #overview command,
2524 1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2525 int reason; /* how hero died; used when disclosing end-of-game level */
2530 /* lazy initialization */
2531 (void) recalc_mapseen();
2533 win = create_nhwindow(NHW_MENU);
2534 /* show the endgame levels before the rest of the dungeon,
2535 so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2536 if (In_endgame(&u.uz))
2537 traverse_mapseenchn(TRUE, win, why, reason, &lastdun);
2538 /* if game is over or we're not in the endgame yet, show the dungeon */
2539 if (why > 0 || !In_endgame(&u.uz))
2540 traverse_mapseenchn(FALSE, win, why, reason, &lastdun);
2541 display_nhwindow(win, TRUE);
2542 destroy_nhwindow(win);
2545 /* display endgame levels or non-endgame levels, not both */
2547 traverse_mapseenchn(viewendgame, win, why, reason, lastdun_p)
2548 boolean viewendgame;
2550 int why, reason, *lastdun_p;
2555 for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2556 if (viewendgame ^ In_endgame(&mptr->lev))
2559 /* only print out info for a level or a dungeon if interest */
2560 if (why > 0 || interest_mapseen(mptr)) {
2561 showheader = (boolean) (mptr->lev.dnum != *lastdun_p);
2562 print_mapseen(win, mptr, why, reason, showheader);
2563 *lastdun_p = mptr->lev.dnum;
2568 STATIC_OVL const char *
2573 /* players are computer scientists: 0, 1, 2, n */
2577 /* an() returns too much. index is ok in this case */
2579 return index(vowels, *obj) ? "an" : "a";
2589 /* better br_string */
2590 STATIC_OVL const char *
2594 /* Special case: quest portal says closed if kicked from quest */
2595 boolean closed_portal = (br->end2.dnum == quest_dnum
2596 && u.uevent.qexpelled);
2600 return closed_portal ? "Sealed portal" : "Portal";
2602 return "Connection";
2604 return br->end1_up ? "One way stairs up" : "One way stairs down";
2606 return br->end1_up ? "Stairs up" : "Stairs down";
2612 /* get the name of an endgame level; topten.c does something similar */
2613 STATIC_OVL const char *
2614 endgamelevelname(outbuf, indx)
2618 const char *planename = 0;
2623 Strcpy(outbuf, "Astral Plane");
2626 planename = "Water";
2635 planename = "Earth";
2639 Sprintf(outbuf, "Plane of %s", planename);
2641 Sprintf(outbuf, "unknown plane #%d", indx);
2645 STATIC_OVL const char *
2649 const char *str = "shop"; /* catchall */
2651 /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2654 str = "untended shop";
2655 break; /* see recalc_mapseen */
2657 str = "general store";
2663 str = "scroll shop";
2666 str = "potion shop";
2669 str = "weapon shop";
2672 str = "delicatessen";
2684 str = "health food store";
2687 str = "lighting shop";
2695 /* if player knows about the mastermind tune, append it to Castle annotation;
2696 if drawbridge has been destroyed, flags.castletune will be zero */
2698 tunesuffix(mptr, outbuf)
2703 if (mptr->flags.castletune && u.uevent.uheard_tune) {
2706 if (u.uevent.uheard_tune == 2)
2707 Sprintf(tmp, "notes \"%s\"", tune);
2709 Strcpy(tmp, "5-note tune");
2710 Sprintf(outbuf, " (play %s to open or close drawbridge)", tmp);
2715 /* some utility macros for print_mapseen */
2716 #define TAB " " /* three spaces */
2718 #define BULLET "" /* empty; otherwise output becomes cluttered */
2719 #define PREFIX TAB TAB BULLET
2721 /* K&R: don't require support for concatenation of adjacent string literals */
2722 #define PREFIX " " /* two TABs + empty BULLET: six spaces */
2724 #define COMMA (i++ > 0 ? ", " : PREFIX)
2725 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2726 #define ADDNTOBUF(nam, var) \
2729 Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2730 (nam), plur(var)); \
2732 #define ADDTOBUF(nam, var) \
2735 Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
2739 print_mapseen(win, mptr, final, how, printdun)
2742 int final; /* 0: not final; 1: game over, alive; 2: game over, dead */
2743 int how; /* cause of death; only used if final==2 and mptr->lev==u.uz */
2746 char buf[BUFSZ], tmpbuf[BUFSZ];
2747 int i, depthstart, dnum;
2748 boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
2750 /* Damnable special cases */
2751 /* The quest and knox should appear to be level 1 to match
2754 dnum = mptr->lev.dnum;
2755 if (dnum == quest_dnum || dnum == knox_level.dnum)
2758 depthstart = dungeons[dnum].depth_start;
2761 if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
2762 /* suppress the negative numbers in the endgame */
2763 || In_endgame(&mptr->lev))
2764 Sprintf(buf, "%s:", dungeons[dnum].dname);
2765 else if (builds_up(&mptr->lev))
2766 Sprintf(buf, "%s: levels %d up to %d",
2767 dungeons[dnum].dname,
2768 depthstart + dungeons[dnum].entry_lev - 1,
2769 depthstart + dungeons[dnum].dunlev_ureached - 1);
2771 Sprintf(buf, "%s: levels %d to %d",
2772 dungeons[dnum].dname, depthstart,
2773 depthstart + dungeons[dnum].dunlev_ureached - 1);
2774 putstr(win, !final ? ATR_INVERSE : 0, buf);
2777 /* calculate level number */
2778 i = depthstart + mptr->lev.dlevel - 1;
2779 if (In_endgame(&mptr->lev))
2780 Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
2782 /* FIXME: when this branch has only one level (Ft.Ludios),
2783 * listing "Level 1:" for it might confuse inexperienced
2784 * players into thinking there's more than one.
2786 Sprintf(buf, "%sLevel %d:", TAB, i);
2788 /* wizmode prints out proto dungeon names for clarity */
2792 if ((slev = Is_special(&mptr->lev)) != 0)
2793 Sprintf(eos(buf), " [%s]", slev->proto);
2795 /* [perhaps print custom annotation on its own line when it's long] */
2797 Sprintf(eos(buf), " (%s)", mptr->custom);
2798 if (on_level(&u.uz, &mptr->lev))
2799 Sprintf(eos(buf), " <- You %s here.",
2800 (!final || (final == 1 && how == ASCENDED)) ? "are" : "were");
2801 putstr(win, !final ? ATR_BOLD : 0, buf);
2803 if (mptr->flags.forgot)
2806 if (INTEREST(mptr->feat)) {
2809 i = 0; /* interest counter */
2810 /* List interests in an order vaguely corresponding to
2811 * how important they are.
2813 if (mptr->feat.nshop > 0) {
2814 if (mptr->feat.nshop > 1)
2815 ADDNTOBUF("shop", mptr->feat.nshop);
2817 Sprintf(eos(buf), "%s%s", COMMA,
2818 an(shop_string(mptr->feat.shoptype)));
2820 if (mptr->feat.naltar > 0) {
2821 /* Temples + non-temple altars get munged into just "altars" */
2822 if (mptr->feat.ntemple != mptr->feat.naltar)
2823 ADDNTOBUF("altar", mptr->feat.naltar);
2825 ADDNTOBUF("temple", mptr->feat.ntemple);
2827 /* only print out altar's god if they are all to your god */
2828 if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
2829 Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
2831 ADDNTOBUF("throne", mptr->feat.nthrone);
2832 ADDNTOBUF("fountain", mptr->feat.nfount);
2833 ADDNTOBUF("sink", mptr->feat.nsink);
2834 ADDNTOBUF("grave", mptr->feat.ngrave);
2835 ADDNTOBUF("tree", mptr->feat.ntree);
2837 ADDTOBUF("water", mptr->feat.water);
2838 ADDTOBUF("lava", mptr->feat.lava);
2839 ADDTOBUF("ice", mptr->feat.ice);
2841 /* capitalize afterwards */
2843 buf[i] = highc(buf[i]);
2844 /* capitalizing it makes it a sentence; terminate with '.' */
2846 putstr(win, 0, buf);
2849 /* we assume that these are mutually exclusive */
2851 if (mptr->flags.oracle) {
2852 Sprintf(buf, "%sOracle of Delphi.", PREFIX);
2853 } else if (In_sokoban(&mptr->lev)) {
2854 Sprintf(buf, "%s%s.", PREFIX,
2855 mptr->flags.sokosolved ? "Solved" : "Unsolved");
2856 } else if (mptr->flags.bigroom) {
2857 Sprintf(buf, "%sA very big room.", PREFIX);
2858 } else if (mptr->flags.roguelevel) {
2859 Sprintf(buf, "%sA primitive area.", PREFIX);
2860 } else if (mptr->flags.quest_summons) {
2861 Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
2862 } else if (on_level(&mptr->lev, &qstart_level)) {
2863 Sprintf(buf, "%sHome%s.", PREFIX,
2864 mptr->flags.unreachable ? " (no way back...)" : "");
2865 if (u.uevent.qcompleted)
2866 Sprintf(buf, "%sCompleted quest for %s.", PREFIX, ldrname());
2867 else if (mptr->flags.questing)
2868 Sprintf(buf, "%sGiven quest by %s.", PREFIX, ldrname());
2869 } else if (mptr->flags.ludios) {
2870 /* presence of the ludios branch in #overview output indicates that
2871 the player has made it onto the level; presence of this annotation
2872 indicates that the fort's entrance has been seen (or mapped) */
2873 Sprintf(buf, "%sFort Ludios.", PREFIX);
2874 } else if (mptr->flags.castle) {
2875 Sprintf(buf, "%sThe castle%s.", PREFIX, tunesuffix(mptr, tmpbuf));
2876 } else if (mptr->flags.valley) {
2877 Sprintf(buf, "%sValley of the Dead.", PREFIX);
2878 } else if (mptr->flags.msanctum) {
2879 Sprintf(buf, "%sMoloch's Sanctum.", PREFIX);
2882 putstr(win, 0, buf);
2884 /* print out branches */
2886 Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br),
2887 dungeons[mptr->br->end2.dnum].dname);
2889 /* Since mapseen objects are printed out in increasing order
2890 * of dlevel, clarify which level this branch is going to
2891 * if the branch goes upwards. Unless it's the end game.
2893 if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
2894 Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
2896 putstr(win, 0, buf);
2899 /* maybe print out bones details */
2900 if (mptr->final_resting_place || final) {
2901 struct cemetery *bp;
2902 int kncnt = !died_here ? 0 : 1;
2904 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2905 if (bp->bonesknown || wizard || final)
2908 Sprintf(buf, "%s%s", PREFIX, "Final resting place for");
2909 putstr(win, 0, buf);
2911 /* disclosure occurs before bones creation, so listing dead
2912 hero here doesn't give away whether bones are produced */
2913 formatkiller(tmpbuf, sizeof tmpbuf, how);
2914 /* rephrase a few death reasons to work with "you" */
2915 (void) strsubst(tmpbuf, " himself", " yourself");
2916 (void) strsubst(tmpbuf, " herself", " yourself");
2917 (void) strsubst(tmpbuf, " his ", " your ");
2918 (void) strsubst(tmpbuf, " her ", " your ");
2919 Sprintf(buf, "%s%syou, %s%c", PREFIX, TAB, tmpbuf,
2920 --kncnt ? ',' : '.');
2921 putstr(win, 0, buf);
2923 for (bp = mptr->final_resting_place; bp; bp = bp->next) {
2924 if (bp->bonesknown || wizard || final) {
2925 Sprintf(buf, "%s%s%s, %s%c", PREFIX, TAB, bp->who,
2926 bp->how, --kncnt ? ',' : '.');
2927 putstr(win, 0, buf);