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. :-(
951 quest_dnum = dname_to_dnum("The Quest");
952 sokoban_dnum = dname_to_dnum("Sokoban");
953 mines_dnum = dname_to_dnum("The Gnomish Mines");
954 tower_dnum = dname_to_dnum("Vlad's Tower");
956 /* one special fixup for dummy surface level */
957 if ((x = find_level("dummy")) != 0) {
959 /* the code above puts earth one level above dungeon level #1,
960 making the dummy level overlay level 1; but the whole reason
961 for having the dummy level is to make earth have depth -1
962 instead of 0, so adjust the start point to shift endgame up */
963 if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
964 dungeons[i].depth_start -= 1;
965 /* TO DO: strip "dummy" out all the way here,
966 so that it's hidden from <ctrl/O> feedback. */
974 /* return the level number for lev in *this* dungeon */
982 /* return the lowest level number for *this* dungeon */
984 dunlevs_in_dungeon(lev)
987 return dungeons[lev->dnum].num_dunlevs;
990 /* return the lowest level explored in the game*/
992 deepest_lev_reached(noquest)
995 /* this function is used for three purposes: to provide a factor
996 * of difficulty in monster generation; to provide a factor of
997 * difficulty in experience calculations (botl.c and end.c); and
998 * to insert the deepest level reached in the game in the topten
999 * display. the 'noquest' arg switch is required for the latter.
1001 * from the player's point of view, going into the Quest is _not_
1002 * going deeper into the dungeon -- it is going back "home", where
1003 * the dungeon starts at level 1. given the setup in dungeon.def,
1004 * the depth of the Quest (thought of as starting at level 1) is
1005 * never lower than the level of entry into the Quest, so we exclude
1006 * the Quest from the topten "deepest level reached" display
1007 * calculation. _However_ the Quest is a difficult dungeon, so we
1008 * include it in the factor of difficulty calculations.
1012 register schar ret = 0;
1014 for (i = 0; i < n_dgns; i++) {
1015 if (noquest && i == quest_dnum)
1017 tmp.dlevel = dungeons[i].dunlev_ureached;
1018 if (tmp.dlevel == 0)
1021 if (depth(&tmp) > ret)
1027 /* return a bookkeeping level number for purpose of comparisons and
1033 return (xchar) (lev->dlevel + dungeons[lev->dnum].ledger_start);
1037 * The last level in the bookkeeping list of level is the bottom of the last
1038 * dungeon in the dungeons[] array.
1040 * Maxledgerno() -- which is the max number of levels in the bookkeeping
1041 * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1042 * returns the max number of levels in lev's dungeon, and both should
1043 * not be confused with deepest_lev_reached() -- which returns the lowest
1044 * depth visited by the player.
1049 return (xchar) (dungeons[n_dgns - 1].ledger_start
1050 + dungeons[n_dgns - 1].num_dunlevs);
1053 /* return the dungeon that this ledgerno exists in */
1055 ledger_to_dnum(ledgerno)
1060 /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1061 for (i = 0; i < n_dgns; i++)
1062 if (dungeons[i].ledger_start < ledgerno
1063 && ledgerno <= dungeons[i].ledger_start + dungeons[i].num_dunlevs)
1066 panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno);
1071 /* return the level of the dungeon this ledgerno exists in */
1073 ledger_to_dlev(ledgerno)
1076 return (xchar) (ledgerno
1077 - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
1080 /* returns the depth of a level, in floors below the surface
1081 (note levels in different dungeons can have the same depth) */
1086 return (schar) (dungeons[lev->dnum].depth_start + lev->dlevel - 1);
1089 /* are "lev1" and "lev2" actually the same? */
1091 on_level(lev1, lev2)
1092 d_level *lev1, *lev2;
1094 return (boolean) (lev1->dnum == lev2->dnum
1095 && lev1->dlevel == lev2->dlevel);
1098 /* is this level referenced in the special level chain? */
1105 for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
1106 if (on_level(lev, &levtmp->dlevel))
1109 return (s_level *) 0;
1113 * Is this a multi-dungeon branch level? If so, return a pointer to the
1114 * branch. Otherwise, return null.
1122 for (curr = branches; curr; curr = curr->next) {
1123 if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
1126 return (branch *) 0;
1129 /* returns True iff the branch 'lev' is in a branch which builds up */
1134 dungeon *dptr = &dungeons[lev->dnum];
1136 * FIXME: this misclassifies a single level branch reached via stairs
1137 * from below. Saving grace is that no such branches currently exist.
1139 return (boolean) (dptr->num_dunlevs > 1
1140 && dptr->entry_lev == dptr->num_dunlevs);
1143 /* goto the next level (or appropriate dungeon) */
1145 next_level(at_stairs)
1148 if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1149 /* Taking a down dungeon branch. */
1150 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1152 /* Going down a stairs or jump in a trap door. */
1155 newlevel.dnum = u.uz.dnum;
1156 newlevel.dlevel = u.uz.dlevel + 1;
1157 goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
1161 /* goto the previous level (or appropriate dungeon) */
1163 prev_level(at_stairs)
1166 if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1167 /* Taking an up dungeon branch. */
1168 /* KMH -- Upwards branches are okay if not level 1 */
1169 /* (Just make sure it doesn't go above depth 1) */
1170 if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
1173 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1175 /* Going up a stairs or rising through the ceiling. */
1177 newlevel.dnum = u.uz.dnum;
1178 newlevel.dlevel = u.uz.dlevel - 1;
1179 goto_level(&newlevel, at_stairs, FALSE, FALSE);
1190 cliparound(u.ux, u.uy);
1192 /* ridden steed always shares hero's location */
1194 u.usteed->mx = u.ux, u.usteed->my = u.uy;
1195 /* when changing levels, don't leave old position set with
1196 stale values from previous level */
1197 if (!on_level(&u.uz, &u.uz0))
1198 u.ux0 = u.ux, u.uy0 = u.uy;
1201 /* place you on a random location */
1203 u_on_rndspot(upflag)
1206 int up = (upflag & 1), was_in_W_tower = (upflag & 2);
1209 * Place the hero at a random location within the relevant region.
1210 * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1211 * Unspecified region (.lx == 0) defaults to entire level.
1213 if (was_in_W_tower && On_W_tower_level(&u.uz))
1214 /* Stay inside the Wizard's tower when feasible.
1215 We use the W Tower's exclusion region for the
1216 destination instead of its enclosing region.
1217 Note: up vs down doesn't matter in this case
1218 because both specify the same exclusion area. */
1219 place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy, 0, 0, 0,
1220 0, LR_DOWNTELE, (d_level *) 0);
1222 place_lregion(updest.lx, updest.ly, updest.hx, updest.hy, updest.nlx,
1223 updest.nly, updest.nhx, updest.nhy, LR_UPTELE,
1226 place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy, dndest.nlx,
1227 dndest.nly, dndest.nhx, dndest.nhy, LR_DOWNTELE,
1231 /* place you on the special staircase */
1233 u_on_sstairs(upflag)
1237 u_on_newpos(sstairs.sx, sstairs.sy);
1239 u_on_rndspot(upflag);
1242 /* place you on upstairs (or special equivalent) */
1247 u_on_newpos(xupstair, yupstair);
1249 u_on_sstairs(0); /* destination upstairs implies moving down */
1252 /* place you on dnstairs (or special equivalent) */
1257 u_on_newpos(xdnstair, ydnstair);
1259 u_on_sstairs(1); /* destination dnstairs implies moving up */
1266 return (boolean) ((x == xupstair && y == yupstair)
1267 || (x == xdnstair && y == ydnstair)
1268 || (x == xdnladder && y == ydnladder)
1269 || (x == xupladder && y == yupladder)
1270 || (x == sstairs.sx && y == sstairs.sy));
1277 return (boolean) (lev->dlevel == dungeons[lev->dnum].num_dunlevs);
1284 return (boolean) (!level.flags.hardfloor
1285 && !Is_botlevel(lev)
1286 && !Invocation_lev(lev));
1290 * Like Can_dig_down (above), but also allows falling through on the
1291 * stronghold level. Normally, the bottom level of a dungeon resists
1292 * both digging and falling.
1298 return (boolean) (Can_dig_down(lev) || Is_stronghold(lev));
1302 * True if one can rise up a level (e.g. cursed gain level).
1303 * This happens on intermediate dungeon levels or on any top dungeon
1304 * level that has a stairwell style branch to the next higher dungeon.
1305 * Checks for amulets and such must be done elsewhere.
1308 Can_rise_up(x, y, lev)
1312 /* can't rise up from inside the top of the Wizard's tower */
1313 /* KMH -- or in sokoban */
1314 if (In_endgame(lev) || In_sokoban(lev)
1315 || (Is_wiz1_level(lev) && In_W_tower(x, y, lev)))
1317 return (boolean) (lev->dlevel > 1
1318 || (dungeons[lev->dnum].entry_lev == 1
1319 && ledger_no(lev) != 1
1320 && sstairs.sx && sstairs.up));
1327 /* [what about level 1 of the quest?] */
1328 return (boolean) (!Is_airlevel(lev) && !Is_waterlevel(lev));
1332 * It is expected that the second argument of get_level is a depth value,
1333 * either supplied by the user (teleport control) or randomly generated.
1334 * But more than one level can be at the same depth. If the target level
1335 * is "above" the present depth location, get_level must trace "up" from
1336 * the player's location (through the ancestors dungeons) the dungeon
1337 * within which the target level is located. With only one exception
1338 * which does not pass through this routine (see level_tele), teleporting
1339 * "down" is confined to the current dungeon. At present, level teleport
1340 * in dungeons that build up is confined within them.
1343 get_level(newlevel, levnum)
1348 xchar dgn = u.uz.dnum;
1351 /* can only currently happen in endgame */
1352 levnum = u.uz.dlevel;
1354 > dungeons[dgn].depth_start + dungeons[dgn].num_dunlevs - 1) {
1355 /* beyond end of dungeon, jump to last level */
1356 levnum = dungeons[dgn].num_dunlevs;
1358 /* The desired level is in this dungeon or a "higher" one. */
1361 * Branch up the tree until we reach a dungeon that contains the
1364 if (levnum < dungeons[dgn].depth_start) {
1367 * Find the parent dungeon of this dungeon.
1369 * This assumes that end2 is always the "child" and it is
1372 for (br = branches; br; br = br->next)
1373 if (br->end2.dnum == dgn)
1376 panic("get_level: can't find parent dungeon");
1378 dgn = br->end1.dnum;
1379 } while (levnum < dungeons[dgn].depth_start);
1382 /* We're within the same dungeon; calculate the level. */
1383 levnum = levnum - dungeons[dgn].depth_start + 1;
1386 newlevel->dnum = dgn;
1387 newlevel->dlevel = levnum;
1390 /* are you in the quest dungeon? */
1395 return (boolean) (lev->dnum == quest_dnum);
1398 /* are you in the mines dungeon? */
1403 return (boolean) (lev->dnum == mines_dnum);
1407 * Return the branch for the given dungeon.
1409 * This function assumes:
1410 * + This is not called with "Dungeons of Doom".
1411 * + There is only _one_ branch to a given dungeon.
1412 * + Field end2 is the "child" dungeon.
1421 dnum = dname_to_dnum(s);
1423 /* Find the branch that connects to dungeon i's branch. */
1424 for (br = branches; br; br = br->next)
1425 if (br->end2.dnum == dnum)
1429 panic("dgn_entrance: can't find entrance to %s", s);
1435 * This returns true if the hero is on the same level as the entrance to
1436 * the named dungeon.
1438 * Called from do.c and mklev.c.
1440 * Assumes that end1 is always the "parent".
1448 br = dungeon_branch(s);
1449 return on_level(&u.uz, &br->end1) ? TRUE : FALSE;
1452 /* is `lev' part of Vlad's tower? */
1457 return (boolean) (lev->dnum == tower_dnum);
1460 /* is `lev' a level containing the Wizard's tower? */
1462 On_W_tower_level(lev)
1465 return (boolean) (Is_wiz1_level(lev)
1466 || Is_wiz2_level(lev)
1467 || Is_wiz3_level(lev));
1470 /* is <x,y> of `lev' inside the Wizard's tower? */
1472 In_W_tower(x, y, lev)
1476 if (!On_W_tower_level(lev))
1479 * Both of the exclusion regions for arriving via level teleport
1480 * (from above or below) define the tower's boundary.
1481 * assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1484 return (boolean) within_bounded_area(x, y, dndest.nlx, dndest.nly,
1485 dndest.nhx, dndest.nhy);
1487 impossible("No boundary for Wizard's Tower?");
1491 /* are you in one of the Hell levels? */
1496 return (boolean) (dungeons[lev->dnum].flags.hellish);
1499 /* sets *lev to be the gateway to Gehennom... */
1504 lev->dnum = valley_level.dnum;
1508 /* go directly to hell... */
1510 goto_hell(at_stairs, falling)
1511 boolean at_stairs, falling;
1516 goto_level(&lev, at_stairs, falling, FALSE);
1519 /* equivalent to dest = source */
1521 assign_level(dest, src)
1522 d_level *dest, *src;
1524 dest->dnum = src->dnum;
1525 dest->dlevel = src->dlevel;
1528 /* dest = src + rn1(range) */
1530 assign_rnd_level(dest, src, range)
1531 d_level *dest, *src;
1534 dest->dnum = src->dnum;
1535 dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range));
1537 if (dest->dlevel > dunlevs_in_dungeon(dest))
1538 dest->dlevel = dunlevs_in_dungeon(dest);
1539 else if (dest->dlevel < 1)
1547 s_level *lev = Is_special(&u.uz);
1550 if (lev && lev->flags.align)
1552 return lev->flags.align;
1554 if (dungeons[u.uz.dnum].flags.align)
1556 return dungeons[u.uz.dnum].flags.align;
1559 return Align2amask(al);
1566 return (boolean) (In_hell(lev)
1567 && lev->dlevel == dungeons[lev->dnum].num_dunlevs - 1);
1570 /* use instead of depth() wherever a degree of difficulty is made
1571 * dependent on the location in the dungeon (eg. monster creation).
1578 if (In_endgame(&u.uz)) {
1579 res = depth(&sanctum_level) + u.ulevel / 2;
1580 } else if (u.uhave.amulet) {
1581 res = deepest_lev_reached(FALSE);
1584 /* depth() is the number of elevation units (levels) below
1585 the theoretical surface; in a builds-up branch, that value
1586 ends up making the harder to reach levels be treated as if
1587 they were easier; adjust for the extra effort involved in
1588 going down to the entrance and then up to the location */
1589 if (builds_up(&u.uz))
1590 res += 2 * (dungeons[u.uz.dnum].entry_lev - u.uz.dlevel + 1);
1592 * 'Proof' by example: suppose the entrance to sokoban is
1593 * on dungeon level 9, leading up to bottom sokoban level
1594 * of 8 [entry_lev]. When the hero is on sokoban level 8
1595 * [uz.dlevel], depth() yields eight but he has ventured
1596 * one level beyond 9, so difficulty depth should be 10:
1597 * 8 + 2 * (8 - 8 + 1) => 10.
1598 * Going up to 7, depth is 7 but hero will be two beyond 9:
1599 * 7 + 2 * (8 - 7 + 1) => 11.
1600 * When he goes up to level 6, three levels beyond 9:
1601 * 6 + 2 * (8 - 6 + 1) => 12.
1602 * And the top level of sokoban at 5, four levels beyond 9:
1603 * 5 + 2 * (8 - 5 + 1) => 13.
1604 * The same applies to Vlad's Tower, although the increment
1605 * there is inconsequential compared to overall depth.
1611 /* Take one word and try to match it to a level.
1612 * Recognized levels are as shown by print_dungeon().
1625 /* allow strings like "the oracle level" to find "oracle" */
1626 if (!strncmpi(nam, "the ", 4))
1628 if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
1629 nam = strcpy(buf, nam);
1630 *(eos(buf) - 6) = '\0';
1632 /* hell is the old name, and wouldn't match; gehennom would match its
1633 branch, yielding the castle level instead of the valley of the dead */
1634 if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1635 if (In_V_tower(&u.uz))
1636 nam = " to Vlad's tower"; /* branch to... */
1641 if ((slev = find_level(nam)) != 0) {
1642 dlev = slev->dlevel;
1643 idx = ledger_no(&dlev);
1644 if ((dlev.dnum == u.uz.dnum
1645 /* within same branch, or else main dungeon <-> gehennom */
1646 || (u.uz.dnum == valley_level.dnum
1647 && dlev.dnum == medusa_level.dnum)
1648 || (u.uz.dnum == medusa_level.dnum
1649 && dlev.dnum == valley_level.dnum))
1650 && (/* either wizard mode or else seen and not forgotten */
1652 || (level_info[idx].flags & (FORGOTTEN | VISITED))
1654 lev = depth(&slev->dlevel);
1656 } else { /* not a specific level; try branch names */
1657 idx = find_branch(nam, (struct proto_dungeon *) 0);
1658 /* "<branch> to Xyzzy" */
1659 if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1660 idx = find_branch(p + 4, (struct proto_dungeon *) 0);
1663 idxtoo = (idx >> 8) & 0x00FF;
1665 if (/* either wizard mode, or else _both_ sides of branch seen */
1667 || ((level_info[idx].flags & (FORGOTTEN | VISITED)) == VISITED
1668 && (level_info[idxtoo].flags & (FORGOTTEN | VISITED))
1670 if (ledger_to_dnum(idxtoo) == u.uz.dnum)
1672 dlev.dnum = ledger_to_dnum(idx);
1673 dlev.dlevel = ledger_to_dlev(idx);
1682 unplaced_floater(dptr)
1683 struct dungeon *dptr;
1686 int idx = (int) (dptr - dungeons);
1688 /* if other floating branches are added, this will need to change */
1689 if (idx != knox_level.dnum)
1691 for (br = branches; br; br = br->next)
1692 if (br->end1.dnum == n_dgns && br->end2.dnum == idx)
1698 unreachable_level(lvl_p, unplaced)
1706 if (In_endgame(&u.uz) && !In_endgame(lvl_p))
1708 if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
1714 tport_menu(win, entry, lchoices, lvl_p, unreachable)
1717 struct lchoice *lchoices;
1719 boolean unreachable;
1724 lchoices->lev[lchoices->idx] = lvl_p->dlevel;
1725 lchoices->dgn[lchoices->idx] = lvl_p->dnum;
1726 lchoices->playerlev[lchoices->idx] = depth(lvl_p);
1729 /* not selectable, but still consumes next menuletter;
1730 prepend padding in place of missing menu selector */
1731 Sprintf(tmpbuf, " %s", entry);
1734 any.a_int = lchoices->idx + 1;
1736 add_menu(win, NO_GLYPH, &any, lchoices->menuletter, 0, ATR_NONE, entry,
1738 /* this assumes there are at most 52 interesting levels */
1739 if (lchoices->menuletter == 'z')
1740 lchoices->menuletter = 'A';
1742 lchoices->menuletter++;
1747 /* Convert a branch type to a string usable by print_dungeon(). */
1748 STATIC_OVL const char *
1756 return "Connection";
1758 return "One way stair";
1762 return " (unknown)";
1765 /* Print all child branches between the lower and upper bounds. */
1767 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
1773 struct lchoice *lchoices_p;
1778 /* This assumes that end1 is the "parent". */
1779 for (br = branches; br; br = br->next) {
1780 if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
1781 && br->end1.dlevel <= upper_bound) {
1782 Sprintf(buf, " %s to %s: %d", br_string(br->type),
1783 dungeons[br->end2.dnum].dname, depth(&br->end1));
1785 tport_menu(win, buf, lchoices_p, &br->end1,
1786 unreachable_level(&br->end1, FALSE));
1788 putstr(win, 0, buf);
1793 /* Print available dungeon information. */
1795 print_dungeon(bymenu, rlev, rdgn)
1800 int i, last_level, nlev;
1803 boolean first, unplaced;
1808 struct lchoice lchoices;
1810 winid win = create_nhwindow(NHW_MENU);
1814 lchoices.menuletter = 'a';
1817 for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1818 if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum)
1820 unplaced = unplaced_floater(dptr);
1821 descr = unplaced ? "depth" : "level";
1822 nlev = dptr->num_dunlevs;
1824 Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
1825 dptr->depth_start, dptr->depth_start + nlev - 1);
1827 Sprintf(buf, "%s: %s %d", dptr->dname, descr, dptr->depth_start);
1829 /* Most entrances are uninteresting. */
1830 if (dptr->entry_lev != 1) {
1831 if (dptr->entry_lev == nlev)
1832 Strcat(buf, ", entrance from below");
1834 Sprintf(eos(buf), ", entrance on %d",
1835 dptr->depth_start + dptr->entry_lev - 1);
1839 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
1842 putstr(win, 0, buf);
1845 * Circle through the special levels to find levels that are in
1848 for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1849 if (slev->dlevel.dnum != i)
1852 /* print any branches before this level */
1853 print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
1856 Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel));
1857 if (Is_stronghold(&slev->dlevel))
1858 Sprintf(eos(buf), " (tune %s)", tune);
1860 tport_menu(win, buf, &lchoices, &slev->dlevel,
1861 unreachable_level(&slev->dlevel, unplaced));
1863 putstr(win, 0, buf);
1865 last_level = slev->dlevel.dlevel;
1867 /* print branches after the last special level */
1868 print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1873 menu_item *selected;
1876 end_menu(win, "Level teleport to where:");
1877 n = select_menu(win, PICK_ONE, &selected);
1878 destroy_nhwindow(win);
1880 idx = selected[0].item.a_int - 1;
1881 free((genericptr_t) selected);
1883 *rlev = lchoices.lev[idx];
1884 *rdgn = lchoices.dgn[idx];
1885 return lchoices.playerlev[idx];
1891 /* Print out floating branches (if any). */
1892 for (first = TRUE, br = branches; br; br = br->next) {
1893 if (br->end1.dnum == n_dgns) {
1896 putstr(win, 0, "Floating branches");
1899 Sprintf(buf, " %s to %s", br_string(br->type),
1900 dungeons[br->end2.dnum].dname);
1901 putstr(win, 0, buf);
1905 /* I hate searching for the invocation pos while debugging. -dean */
1906 if (Invocation_lev(&u.uz)) {
1908 Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1909 inv_pos.x, inv_pos.y, u.ux, u.uy);
1910 putstr(win, 0, buf);
1913 * The following is based on the assumption that the inter-level portals
1914 * created by the level compiler (not the dungeon compiler) only exist
1915 * one per level (currently true, of course).
1917 else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
1918 || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
1920 for (trap = ftrap; trap; trap = trap->ntrap)
1921 if (trap->ttyp == MAGIC_PORTAL)
1926 Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)", trap->tx,
1927 trap->ty, u.ux, u.uy);
1929 Sprintf(buf, "No portal found.");
1930 putstr(win, 0, buf);
1933 display_nhwindow(win, TRUE);
1934 destroy_nhwindow(win);
1938 /* Record that the player knows about a branch from a level. This function
1939 * will determine whether or not it was a "real" branch that was taken.
1940 * This function should not be called for a transition done via level
1941 * teleport or via the Eye.
1944 recbranch_mapseen(source, dest)
1952 if (source->dnum == dest->dnum)
1955 /* we only care about forward branches */
1956 for (br = branches; br; br = br->next) {
1957 if (on_level(source, &br->end1) && on_level(dest, &br->end2))
1959 if (on_level(source, &br->end2) && on_level(dest, &br->end1))
1963 /* branch not found, so not a real branch. */
1967 if ((mptr = find_mapseen(source)) != 0) {
1968 if (mptr->br && br != mptr->br)
1969 impossible("Two branches on the same level?");
1972 impossible("Can't note branch for unseen level (%d, %d)",
1973 source->dnum, source->dlevel);
1983 if ((mptr = find_mapseen(lev)))
1984 return mptr->custom;
1988 /* #annotate command - add a custom name to the current level */
1993 char nbuf[BUFSZ]; /* Buffer for response */
1995 if (!(mptr = find_mapseen(&u.uz)))
2000 Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
2001 strlen(mptr->custom) > 30 ? "..." : "");
2002 getlin(tmpbuf, nbuf);
2004 getlin("What do you want to call this dungeon level?", nbuf);
2005 if (index(nbuf, '\033'))
2007 (void) mungspaces(nbuf);
2009 /* discard old annotation, if any */
2011 free((genericptr_t) mptr->custom);
2012 mptr->custom = (char *) 0;
2013 mptr->custom_lth = 0;
2015 /* add new annotation, unless it's empty or a single space */
2016 if (*nbuf && strcmp(nbuf, " ")) {
2017 mptr->custom = dupstr(nbuf);
2018 mptr->custom_lth = strlen(mptr->custom);
2023 /* find the particular mapseen object in the chain; may return null */
2024 STATIC_OVL mapseen *
2030 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2031 if (on_level(&(mptr->lev), lev))
2038 forget_mapseen(ledger_num)
2042 struct cemetery *bp;
2044 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2045 if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
2049 /* if not found, then nothing to forget */
2051 mptr->flags.forgot = 1;
2052 mptr->br = (branch *) 0;
2054 /* custom names are erased, not just forgotten until revisited */
2056 mptr->custom_lth = 0;
2057 free((genericptr_t) mptr->custom);
2058 mptr->custom = (char *) 0;
2060 (void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
2061 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2062 bp->bonesknown = FALSE;
2067 save_mapseen(fd, mptr)
2074 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2075 if (curr == mptr->br)
2077 bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
2079 bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
2080 bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
2081 bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
2082 bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
2083 if (mptr->custom_lth)
2084 bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
2085 bwrite(fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
2086 savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
2089 STATIC_OVL mapseen *
2093 int branchnum, brindx;
2097 load = (mapseen *) alloc(sizeof *load);
2099 mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
2100 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2101 if (brindx == branchnum)
2105 mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
2106 mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
2107 mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
2108 mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
2109 if (load->custom_lth) {
2110 /* length doesn't include terminator (which isn't saved & restored) */
2111 load->custom = (char *) alloc(load->custom_lth + 1);
2112 mread(fd, (genericptr_t) load->custom, load->custom_lth);
2113 load->custom[load->custom_lth] = '\0';
2116 mread(fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
2117 restcemetery(fd, &load->final_resting_place);
2122 /* Remove all mapseen objects for a particular dnum.
2123 * Useful during quest expulsion to remove quest levels.
2124 * [No longer deleted, just marked as unreachable. #overview will
2125 * ignore such levels, end of game disclosure will include them.]
2128 remdun_mapseen(dnum)
2131 mapseen *mptr, **mptraddr;
2133 mptraddr = &mapseenchn;
2134 while ((mptr = *mptraddr) != 0) {
2135 if (mptr->lev.dnum == dnum) {
2136 #if 1 /* use this... */
2137 mptr->flags.unreachable = 1;
2139 #else /* old deletion code */
2140 *mptraddr = mptr->next;
2142 free((genericptr_t) mptr->custom);
2143 if (mptr->final_resting_place)
2144 savecemetery(-1, FREE_SAVE, &mptr->final_resting_place);
2145 free((genericptr_t) mptr);
2148 mptraddr = &mptr->next;
2156 /* Create a level and insert in "sorted" order. This is an insertion
2157 * sort first by dungeon (in order of discovery) and then by level number.
2159 mapseen *mptr, *init, *prev;
2161 init = (mapseen *) alloc(sizeof *init);
2162 (void) memset((genericptr_t) init, 0, sizeof *init);
2163 /* memset is fine for feature bits, flags, and rooms array;
2164 explicitly initialize pointers to null */
2165 init->next = 0, init->br = 0, init->custom = 0;
2166 init->final_resting_place = 0;
2167 /* lastseentyp[][] is reused for each level, so get rid of
2168 previous level's data */
2169 (void) memset((genericptr_t) lastseentyp, 0, sizeof lastseentyp);
2171 init->lev.dnum = lev->dnum;
2172 init->lev.dlevel = lev->dlevel;
2174 /* walk until we get to the place where we should insert init */
2175 for (mptr = mapseenchn, prev = 0; mptr; prev = mptr, mptr = mptr->next)
2176 if (mptr->lev.dnum > init->lev.dnum
2177 || (mptr->lev.dnum == init->lev.dnum
2178 && mptr->lev.dlevel > init->lev.dlevel))
2181 init->next = mapseenchn;
2190 #define INTEREST(feat) \
2191 ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2192 || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2193 /* || (feat).water || (feat).ice || (feat).lava */
2195 /* returns true if this level has something interesting to print out */
2197 interest_mapseen(mptr)
2200 if (on_level(&u.uz, &mptr->lev))
2202 if (mptr->flags.unreachable || mptr->flags.forgot)
2204 /* level is of interest if it has an auto-generated annotation */
2205 if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
2206 || mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
2207 || mptr->flags.quest_summons || mptr->flags.questing)
2209 /* when in Sokoban, list all sokoban levels visited; when not in it,
2210 list any visited Sokoban level which remains unsolved (will usually
2211 only be furthest one reached, but it's possible to enter pits and
2212 climb out on the far side on the first Sokoban level; also, wizard
2213 mode overrides teleport restrictions) */
2214 if (In_sokoban(&mptr->lev)
2215 && (In_sokoban(&u.uz) || !mptr->flags.sokosolved))
2217 /* when in the endgame, list all endgame levels visited, whether they
2218 have annotations or not, so that #overview doesn't become extremely
2219 sparse once the rest of the dungeon has been flagged as unreachable */
2220 if (In_endgame(&u.uz))
2221 return (boolean) In_endgame(&mptr->lev);
2222 /* level is of interest if it has non-zero feature count or known bones
2223 or user annotation or known connection to another dungeon branch
2224 or is the furthest level reached in its branch */
2225 return (boolean) (INTEREST(mptr->feat)
2226 || (mptr->final_resting_place
2227 && (mptr->flags.knownbones || wizard))
2228 || mptr->custom || mptr->br
2229 || (mptr->lev.dlevel
2230 == dungeons[mptr->lev.dnum].dunlev_ureached));
2233 /* recalculate mapseen for the current level */
2239 struct cemetery *bp, **bonesaddr;
2241 int x, y, ltyp, count, atmp;
2243 /* Should not happen in general, but possible if in the process
2244 * of being booted from the quest. The mapseen object gets
2245 * removed during the expulsion but prior to leaving the level
2246 * [Since quest expulsion no longer deletes quest mapseen data,
2247 * null return from find_mapseen() should now be impossible.]
2249 if (!(mptr = find_mapseen(&u.uz)))
2252 /* reset all features; mptr->feat.* = 0; */
2253 (void) memset((genericptr_t) &mptr->feat, 0, sizeof mptr->feat);
2254 /* reset most flags; some level-specific ones are left as-is */
2255 if (mptr->flags.unreachable) {
2256 mptr->flags.unreachable = 0; /* reached it; Eye of the Aethiopica? */
2257 if (In_quest(&u.uz)) {
2258 mapseen *mptrtmp = mapseenchn;
2260 /* when quest was unreachable due to ejection and portal removal,
2261 getting back to it via arti-invoke should revive annotation
2262 data for all quest levels, not just the one we're on now */
2264 if (mptrtmp->lev.dnum == mptr->lev.dnum)
2265 mptrtmp->flags.unreachable = 0;
2266 mptrtmp = mptrtmp->next;
2270 mptr->flags.knownbones = 0;
2271 mptr->flags.sokosolved = In_sokoban(&u.uz) && !Sokoban;
2272 /* mptr->flags.bigroom retains previous value when hero can't see */
2274 mptr->flags.bigroom = Is_bigroom(&u.uz);
2275 else if (mptr->flags.forgot)
2276 mptr->flags.bigroom = 0;
2277 mptr->flags.roguelevel = Is_rogue_level(&u.uz);
2278 mptr->flags.oracle = 0; /* recalculated during room traversal below */
2279 mptr->flags.castletune = 0;
2280 /* flags.castle, flags.valley, flags.msanctum retain previous value */
2281 mptr->flags.forgot = 0;
2282 /* flags.quest_summons disabled once quest finished */
2283 mptr->flags.quest_summons = (at_dgn_entrance("The Quest")
2285 && !(u.uevent.qcompleted
2286 || u.uevent.qexpelled
2287 || quest_status.leader_is_dead));
2288 mptr->flags.questing = (on_level(&u.uz, &qstart_level)
2289 && quest_status.got_quest);
2291 /* track rooms the hero is in */
2292 for (i = 0; i < SIZE(u.urooms); ++i) {
2296 ridx = u.urooms[i] - ROOMOFFSET;
2297 mptr->msrooms[ridx].seen = 1;
2298 mptr->msrooms[ridx].untended =
2299 (rooms[ridx].rtype >= SHOPBASE)
2300 ? (!(mtmp = shop_keeper(u.urooms[i])) || !inhishop(mtmp))
2301 : (rooms[ridx].rtype == TEMPLE)
2302 ? (!(mtmp = findpriest(u.urooms[i]))
2303 || !inhistemple(mtmp))
2307 /* recalculate room knowledge: for now, just shops and temples
2308 * this could be extended to an array of 0..SHOPBASE
2310 for (i = 0; i < SIZE(mptr->msrooms); ++i) {
2311 if (mptr->msrooms[i].seen) {
2312 if (rooms[i].rtype >= SHOPBASE) {
2313 if (mptr->msrooms[i].untended)
2314 mptr->feat.shoptype = SHOPBASE - 1;
2315 else if (!mptr->feat.nshop)
2316 mptr->feat.shoptype = rooms[i].rtype;
2317 else if (mptr->feat.shoptype != (unsigned) rooms[i].rtype)
2318 mptr->feat.shoptype = 0;
2319 count = mptr->feat.nshop + 1;
2321 mptr->feat.nshop = count;
2322 } else if (rooms[i].rtype == TEMPLE) {
2323 /* altar and temple alignment handled below */
2324 count = mptr->feat.ntemple + 1;
2326 mptr->feat.ntemple = count;
2327 } else if (rooms[i].orig_rtype == DELPHI) {
2328 mptr->flags.oracle = 1;
2333 /* Update lastseentyp with typ if and only if it is in sight or the
2334 * hero can feel it on their current location (i.e. not levitating).
2335 * This *should* give the "last known typ" for each dungeon location.
2336 * (At the very least, it's a better assumption than determining what
2337 * the player knows from the glyph and the typ (which is isn't quite
2338 * enough information in some cases)).
2340 * It was reluctantly added to struct rm to track. Alternatively
2341 * we could track "features" and then update them all here, and keep
2342 * track of when new features are created or destroyed, but this
2343 * seemed the most elegant, despite adding more data to struct rm.
2344 * [3.6.0: we're using lastseentyp[][] rather than level.locations
2345 * to track the features seen.]
2347 * Although no current windowing systems (can) do this, this would add
2348 * the ability to have non-dungeon glyphs float above the last known
2349 * dungeon glyph (i.e. items on fountains).
2351 for (x = 1; x < COLNO; x++) {
2352 for (y = 0; y < ROWNO; y++) {
2353 if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
2354 ltyp = levl[x][y].typ;
2355 if (ltyp == DRAWBRIDGE_UP)
2356 ltyp = db_under_typ(levl[x][y].drawbridgemask);
2357 if ((mtmp = m_at(x, y)) != 0
2358 && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
2359 ltyp = cmap_to_type(mtmp->mappearance);
2360 lastseentyp[x][y] = ltyp;
2363 switch (lastseentyp[x][y]) {
2366 count = mptr->feat.ice + 1;
2368 mptr->feat.ice = count;
2373 count = mptr->feat.water + 1;
2375 mptr->feat.water = count;
2378 count = mptr->feat.lava + 1;
2380 mptr->feat.lava = count;
2384 count = mptr->feat.ntree + 1;
2386 mptr->feat.ntree = count;
2389 count = mptr->feat.nfount + 1;
2391 mptr->feat.nfount = count;
2394 count = mptr->feat.nthrone + 1;
2396 mptr->feat.nthrone = count;
2399 count = mptr->feat.nsink + 1;
2401 mptr->feat.nsink = count;
2404 count = mptr->feat.ngrave + 1;
2406 mptr->feat.ngrave = count;
2409 atmp = (Is_astralevel(&u.uz)
2410 && (levl[x][y].seenv & SVALL) != SVALL)
2412 : Amask2msa(levl[x][y].altarmask);
2413 if (!mptr->feat.naltar)
2414 mptr->feat.msalign = atmp;
2415 else if (mptr->feat.msalign != atmp)
2416 mptr->feat.msalign = MSA_NONE;
2417 count = mptr->feat.naltar + 1;
2419 mptr->feat.naltar = count;
2421 /* An automatic annotation is added to the Castle and
2422 * to Fort Ludios once their structure's main entrance
2423 * has been seen (in person or via magic mapping).
2424 * DOOR: possibly a lowered drawbridge's open portcullis;
2425 * DBWALL: a raised drawbridge's "closed door";
2426 * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2427 * with moat or other terrain hidden underneath;
2428 * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2429 * not recognizable as a bridge location unless/until
2430 * the adjacent DBWALL has been seen.
2433 if (is_drawbridge_wall(x, y) < 0)
2437 case DRAWBRIDGE_DOWN:
2438 if (Is_stronghold(&u.uz))
2439 mptr->flags.castle = 1, mptr->flags.castletune = 1;
2440 else if (Is_knox(&u.uz))
2441 mptr->flags.ludios = 1;
2449 if (level.bonesinfo && !mptr->final_resting_place) {
2450 /* clone the bonesinfo so we aren't dependent upon this
2451 level being in memory */
2452 bonesaddr = &mptr->final_resting_place;
2453 bp = level.bonesinfo;
2455 *bonesaddr = (struct cemetery *) alloc(sizeof **bonesaddr);
2458 bonesaddr = &(*bonesaddr)->next;
2462 /* decide which past hero deaths have become known; there's no
2463 guarantee of either a grave or a ghost, so we go by whether the
2464 current hero has seen the map location where each old one died */
2465 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2466 if (lastseentyp[bp->frpx][bp->frpy]) {
2467 bp->bonesknown = TRUE;
2468 mptr->flags.knownbones = 1;
2473 /* valley and sanctum levels get automatic annotation once temple is entered
2476 mapseen_temple(priest)
2477 struct monst *priest UNUSED; /* currently unused; might be useful someday */
2479 mapseen *mptr = find_mapseen(&u.uz);
2481 if (Is_valley(&u.uz))
2482 mptr->flags.valley = 1;
2483 else if (Is_sanctum(&u.uz))
2484 mptr->flags.msanctum = 1;
2487 /* room entry message has just been delivered so learn room even if blind */
2489 room_discovered(roomno)
2492 mapseen *mptr = find_mapseen(&u.uz);
2494 mptr->msrooms[roomno].seen = 1;
2497 /* #overview command */
2501 show_overview(0, 0);
2505 /* called for #overview or for end of game disclosure */
2507 show_overview(why, reason)
2508 int why; /* 0 => #overview command,
2509 1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2510 int reason; /* how hero died; used when disclosing end-of-game level */
2515 /* lazy initialization */
2516 (void) recalc_mapseen();
2518 win = create_nhwindow(NHW_MENU);
2519 /* show the endgame levels before the rest of the dungeon,
2520 so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2521 if (In_endgame(&u.uz))
2522 traverse_mapseenchn(TRUE, win, why, reason, &lastdun);
2523 /* if game is over or we're not in the endgame yet, show the dungeon */
2524 if (why > 0 || !In_endgame(&u.uz))
2525 traverse_mapseenchn(FALSE, win, why, reason, &lastdun);
2526 display_nhwindow(win, TRUE);
2527 destroy_nhwindow(win);
2530 /* display endgame levels or non-endgame levels, not both */
2532 traverse_mapseenchn(viewendgame, win, why, reason, lastdun_p)
2533 boolean viewendgame;
2535 int why, reason, *lastdun_p;
2540 for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2541 if (viewendgame ^ In_endgame(&mptr->lev))
2544 /* only print out info for a level or a dungeon if interest */
2545 if (why > 0 || interest_mapseen(mptr)) {
2546 showheader = (boolean) (mptr->lev.dnum != *lastdun_p);
2547 print_mapseen(win, mptr, why, reason, showheader);
2548 *lastdun_p = mptr->lev.dnum;
2553 STATIC_OVL const char *
2558 /* players are computer scientists: 0, 1, 2, n */
2562 /* an() returns too much. index is ok in this case */
2564 return index(vowels, *obj) ? "an" : "a";
2574 /* better br_string */
2575 STATIC_OVL const char *
2579 /* Special case: quest portal says closed if kicked from quest */
2580 boolean closed_portal = (br->end2.dnum == quest_dnum
2581 && u.uevent.qexpelled);
2585 return closed_portal ? "Sealed portal" : "Portal";
2587 return "Connection";
2589 return br->end1_up ? "One way stairs up" : "One way stairs down";
2591 return br->end1_up ? "Stairs up" : "Stairs down";
2597 /* get the name of an endgame level; topten.c does something similar */
2598 STATIC_OVL const char *
2599 endgamelevelname(outbuf, indx)
2603 const char *planename = 0;
2608 Strcpy(outbuf, "Astral Plane");
2611 planename = "Water";
2620 planename = "Earth";
2624 Sprintf(outbuf, "Plane of %s", planename);
2626 Sprintf(outbuf, "unknown plane #%d", indx);
2630 STATIC_OVL const char *
2634 const char *str = "shop"; /* catchall */
2636 /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2639 str = "untended shop";
2640 break; /* see recalc_mapseen */
2642 str = "general store";
2648 str = "scroll shop";
2651 str = "potion shop";
2654 str = "weapon shop";
2657 str = "delicatessen";
2669 str = "health food store";
2672 str = "lighting shop";
2680 /* if player knows about the mastermind tune, append it to Castle annotation;
2681 if drawbridge has been destroyed, flags.castletune will be zero */
2683 tunesuffix(mptr, outbuf)
2688 if (mptr->flags.castletune && u.uevent.uheard_tune) {
2691 if (u.uevent.uheard_tune == 2)
2692 Sprintf(tmp, "notes \"%s\"", tune);
2694 Strcpy(tmp, "5-note tune");
2695 Sprintf(outbuf, " (play %s to open or close drawbridge)", tmp);
2700 /* some utility macros for print_mapseen */
2701 #define TAB " " /* three spaces */
2703 #define BULLET "" /* empty; otherwise output becomes cluttered */
2704 #define PREFIX TAB TAB BULLET
2706 /* K&R: don't require support for concatenation of adjacent string literals */
2707 #define PREFIX " " /* two TABs + empty BULLET: six spaces */
2709 #define COMMA (i++ > 0 ? ", " : PREFIX)
2710 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2711 #define ADDNTOBUF(nam, var) \
2714 Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2715 (nam), plur(var)); \
2717 #define ADDTOBUF(nam, var) \
2720 Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
2724 print_mapseen(win, mptr, final, how, printdun)
2727 int final; /* 0: not final; 1: game over, alive; 2: game over, dead */
2728 int how; /* cause of death; only used if final==2 and mptr->lev==u.uz */
2731 char buf[BUFSZ], tmpbuf[BUFSZ];
2732 int i, depthstart, dnum;
2733 boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
2735 /* Damnable special cases */
2736 /* The quest and knox should appear to be level 1 to match
2739 dnum = mptr->lev.dnum;
2740 if (dnum == quest_dnum || dnum == knox_level.dnum)
2743 depthstart = dungeons[dnum].depth_start;
2746 if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
2747 /* suppress the negative numbers in the endgame */
2748 || In_endgame(&mptr->lev))
2749 Sprintf(buf, "%s:", dungeons[dnum].dname);
2750 else if (builds_up(&mptr->lev))
2751 Sprintf(buf, "%s: levels %d up to %d",
2752 dungeons[dnum].dname,
2753 depthstart + dungeons[dnum].entry_lev - 1,
2754 depthstart + dungeons[dnum].dunlev_ureached - 1);
2756 Sprintf(buf, "%s: levels %d to %d",
2757 dungeons[dnum].dname, depthstart,
2758 depthstart + dungeons[dnum].dunlev_ureached - 1);
2759 putstr(win, !final ? ATR_INVERSE : 0, buf);
2762 /* calculate level number */
2763 i = depthstart + mptr->lev.dlevel - 1;
2764 if (In_endgame(&mptr->lev))
2765 Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
2767 /* FIXME: when this branch has only one level (Ft.Ludios),
2768 * listing "Level 1:" for it might confuse inexperienced
2769 * players into thinking there's more than one.
2771 Sprintf(buf, "%sLevel %d:", TAB, i);
2773 /* wizmode prints out proto dungeon names for clarity */
2777 if ((slev = Is_special(&mptr->lev)) != 0)
2778 Sprintf(eos(buf), " [%s]", slev->proto);
2780 /* [perhaps print custom annotation on its own line when it's long] */
2782 Sprintf(eos(buf), " (%s)", mptr->custom);
2783 if (on_level(&u.uz, &mptr->lev))
2784 Sprintf(eos(buf), " <- You %s here.",
2785 (!final || (final == 1 && how == ASCENDED)) ? "are" : "were");
2786 putstr(win, !final ? ATR_BOLD : 0, buf);
2788 if (mptr->flags.forgot)
2791 if (INTEREST(mptr->feat)) {
2794 i = 0; /* interest counter */
2795 /* List interests in an order vaguely corresponding to
2796 * how important they are.
2798 if (mptr->feat.nshop > 0) {
2799 if (mptr->feat.nshop > 1)
2800 ADDNTOBUF("shop", mptr->feat.nshop);
2802 Sprintf(eos(buf), "%s%s", COMMA,
2803 an(shop_string(mptr->feat.shoptype)));
2805 if (mptr->feat.naltar > 0) {
2806 /* Temples + non-temple altars get munged into just "altars" */
2807 if (mptr->feat.ntemple != mptr->feat.naltar)
2808 ADDNTOBUF("altar", mptr->feat.naltar);
2810 ADDNTOBUF("temple", mptr->feat.ntemple);
2812 /* only print out altar's god if they are all to your god */
2813 if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
2814 Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
2816 ADDNTOBUF("throne", mptr->feat.nthrone);
2817 ADDNTOBUF("fountain", mptr->feat.nfount);
2818 ADDNTOBUF("sink", mptr->feat.nsink);
2819 ADDNTOBUF("grave", mptr->feat.ngrave);
2820 ADDNTOBUF("tree", mptr->feat.ntree);
2822 ADDTOBUF("water", mptr->feat.water);
2823 ADDTOBUF("lava", mptr->feat.lava);
2824 ADDTOBUF("ice", mptr->feat.ice);
2826 /* capitalize afterwards */
2828 buf[i] = highc(buf[i]);
2829 /* capitalizing it makes it a sentence; terminate with '.' */
2831 putstr(win, 0, buf);
2834 /* we assume that these are mutually exclusive */
2836 if (mptr->flags.oracle) {
2837 Sprintf(buf, "%sOracle of Delphi.", PREFIX);
2838 } else if (In_sokoban(&mptr->lev)) {
2839 Sprintf(buf, "%s%s.", PREFIX,
2840 mptr->flags.sokosolved ? "Solved" : "Unsolved");
2841 } else if (mptr->flags.bigroom) {
2842 Sprintf(buf, "%sA very big room.", PREFIX);
2843 } else if (mptr->flags.roguelevel) {
2844 Sprintf(buf, "%sA primitive area.", PREFIX);
2845 } else if (mptr->flags.quest_summons) {
2846 Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
2847 } else if (on_level(&mptr->lev, &qstart_level)) {
2848 Sprintf(buf, "%sHome%s.", PREFIX,
2849 mptr->flags.unreachable ? " (no way back...)" : "");
2850 if (u.uevent.qcompleted)
2851 Sprintf(buf, "%sCompleted quest for %s.", PREFIX, ldrname());
2852 else if (mptr->flags.questing)
2853 Sprintf(buf, "%sGiven quest by %s.", PREFIX, ldrname());
2854 } else if (mptr->flags.ludios) {
2855 /* presence of the ludios branch in #overview output indicates that
2856 the player has made it onto the level; presence of this annotation
2857 indicates that the fort's entrance has been seen (or mapped) */
2858 Sprintf(buf, "%sFort Ludios.", PREFIX);
2859 } else if (mptr->flags.castle) {
2860 Sprintf(buf, "%sThe castle%s.", PREFIX, tunesuffix(mptr, tmpbuf));
2861 } else if (mptr->flags.valley) {
2862 Sprintf(buf, "%sValley of the Dead.", PREFIX);
2863 } else if (mptr->flags.msanctum) {
2864 Sprintf(buf, "%sMoloch's Sanctum.", PREFIX);
2867 putstr(win, 0, buf);
2869 /* print out branches */
2871 Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br),
2872 dungeons[mptr->br->end2.dnum].dname);
2874 /* Since mapseen objects are printed out in increasing order
2875 * of dlevel, clarify which level this branch is going to
2876 * if the branch goes upwards. Unless it's the end game.
2878 if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
2879 Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
2881 putstr(win, 0, buf);
2884 /* maybe print out bones details */
2885 if (mptr->final_resting_place || final) {
2886 struct cemetery *bp;
2887 int kncnt = !died_here ? 0 : 1;
2889 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2890 if (bp->bonesknown || wizard || final)
2893 Sprintf(buf, "%s%s", PREFIX, "Final resting place for");
2894 putstr(win, 0, buf);
2896 /* disclosure occurs before bones creation, so listing dead
2897 hero here doesn't give away whether bones are produced */
2898 formatkiller(tmpbuf, sizeof tmpbuf, how);
2899 /* rephrase a few death reasons to work with "you" */
2900 (void) strsubst(tmpbuf, " himself", " yourself");
2901 (void) strsubst(tmpbuf, " herself", " yourself");
2902 (void) strsubst(tmpbuf, " his ", " your ");
2903 (void) strsubst(tmpbuf, " her ", " your ");
2904 Sprintf(buf, "%s%syou, %s%c", PREFIX, TAB, tmpbuf,
2905 --kncnt ? ',' : '.');
2906 putstr(win, 0, buf);
2908 for (bp = mptr->final_resting_place; bp; bp = bp->next) {
2909 if (bp->bonesknown || wizard || final) {
2910 Sprintf(buf, "%s%s%s, %s%c", PREFIX, TAB, bp->who,
2911 bp->how, --kncnt ? ',' : '.');
2912 putstr(win, 0, buf);