1 /* NetHack 3.6 dungeon.c $NHDT-Date: 1523308357 2018/04/09 21:12:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.87 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2012. */
4 /* NetHack may be freely redistributed. See license for details. */
11 #define DUNGEON_FILE "dungeon"
13 #define X_START "x-strt"
14 #define X_LOCATE "x-loca"
15 #define X_GOAL "x-goal"
17 struct proto_dungeon {
18 struct tmpdungeon tmpdungeon[MAXDUNGEON];
19 struct tmplevel tmplevel[LEV_LIMIT];
20 s_level *final_lev[LEV_LIMIT]; /* corresponding level pointers */
21 struct tmpbranch tmpbranch[BRANCH_LIMIT];
23 int start; /* starting index of current dungeon sp levels */
24 int n_levs; /* number of tmplevel entries */
25 int n_brs; /* number of tmpbranch entries */
28 int n_dgns; /* number of dungeons (also used in mklev.c and do.c) */
29 static branch *branches = (branch *) 0; /* dungeon branch list */
31 mapseen *mapseenchn = (struct mapseen *) 0; /*DUNGEON_OVERVIEW*/
36 schar playerlev[MAXLINFO];
41 static void FDECL(Fread, (genericptr_t, int, int, dlb *));
42 STATIC_DCL xchar FDECL(dname_to_dnum, (const char *));
43 STATIC_DCL int FDECL(find_branch, (const char *, struct proto_dungeon *));
44 STATIC_DCL xchar FDECL(parent_dnum, (const char *, struct proto_dungeon *));
45 STATIC_DCL int FDECL(level_range, (XCHAR_P, int, int, int,
46 struct proto_dungeon *, int *));
47 STATIC_DCL xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *));
48 STATIC_DCL int FDECL(correct_branch_type, (struct tmpbranch *));
49 STATIC_DCL branch *FDECL(add_branch, (int, int, struct proto_dungeon *));
50 STATIC_DCL void FDECL(add_level, (s_level *));
51 STATIC_DCL void FDECL(init_level, (int, int, struct proto_dungeon *));
52 STATIC_DCL int FDECL(possible_places, (int, boolean *,
53 struct proto_dungeon *));
54 STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
55 STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
56 STATIC_DCL boolean FDECL(unplaced_floater, (struct dungeon *));
57 STATIC_DCL boolean FDECL(unreachable_level, (d_level *, BOOLEAN_P));
58 STATIC_DCL void FDECL(tport_menu, (winid, char *, struct lchoice *, d_level *,
60 STATIC_DCL const char *FDECL(br_string, (int));
61 STATIC_DCL char FDECL(chr_u_on_lvl, (d_level *));
62 STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
64 STATIC_DCL mapseen *FDECL(load_mapseen, (int));
65 STATIC_DCL void FDECL(save_mapseen, (int, mapseen *));
66 STATIC_DCL mapseen *FDECL(find_mapseen, (d_level *));
67 STATIC_DCL mapseen *FDECL(find_mapseen_by_str, (const char *));
68 STATIC_DCL void FDECL(print_mapseen, (winid, mapseen *, int, int, BOOLEAN_P));
69 STATIC_DCL boolean FDECL(interest_mapseen, (mapseen *));
70 STATIC_DCL void FDECL(traverse_mapseenchn, (BOOLEAN_P, winid,
72 STATIC_DCL const char *FDECL(seen_string, (XCHAR_P, const char *));
73 STATIC_DCL const char *FDECL(br_string2, (branch *));
74 STATIC_DCL const char *FDECL(endgamelevelname, (char *, int));
75 STATIC_DCL const char *FDECL(shop_string, (int));
76 STATIC_DCL char *FDECL(tunesuffix, (mapseen *, char *));
79 #define DD dungeons[i]
80 STATIC_DCL void NDECL(dumpit);
89 if (!explicitdebug(__FILE__))
92 for (i = 0; i < n_dgns; i++) {
93 fprintf(stderr, "\n#%d \"%s\" (%s):\n", i, DD.dname, DD.proto);
94 fprintf(stderr, " num_dunlevs %d, dunlev_ureached %d\n",
95 DD.num_dunlevs, DD.dunlev_ureached);
96 fprintf(stderr, " depth_start %d, ledger_start %d\n",
97 DD.depth_start, DD.ledger_start);
98 fprintf(stderr, " flags:%s%s%s\n",
99 DD.flags.rogue_like ? " rogue_like" : "",
100 DD.flags.maze_like ? " maze_like" : "",
101 DD.flags.hellish ? " hellish" : "");
104 fprintf(stderr, "\nSpecial levels:\n");
105 for (x = sp_levchn; x; x = x->next) {
106 fprintf(stderr, "%s (%d): ", x->proto, x->rndlevs);
107 fprintf(stderr, "on %d, %d; ", x->dlevel.dnum, x->dlevel.dlevel);
108 fprintf(stderr, "flags:%s%s%s%s\n",
109 x->flags.rogue_like ? " rogue_like" : "",
110 x->flags.maze_like ? " maze_like" : "",
111 x->flags.hellish ? " hellish" : "",
112 x->flags.town ? " town" : "");
115 fprintf(stderr, "\nBranches:\n");
116 for (br = branches; br; br = br->next) {
117 fprintf(stderr, "%d: %s, end1 %d %d, end2 %d %d, %s\n", br->id,
120 : br->type == BR_NO_END1
122 : br->type == BR_NO_END2
124 : br->type == BR_PORTAL
127 br->end1.dnum, br->end1.dlevel, br->end2.dnum,
128 br->end2.dlevel, br->end1_up ? "end1 up" : "end1 down");
131 fprintf(stderr, "\nDone\n");
136 /* Save the dungeon structures. */
138 save_dungeon(fd, perform_write, free_data)
140 boolean perform_write, free_data;
143 mapseen *curr_ms, *next_ms;
147 bwrite(fd, (genericptr_t) &n_dgns, sizeof n_dgns);
148 bwrite(fd, (genericptr_t) dungeons,
149 sizeof(dungeon) * (unsigned) n_dgns);
150 bwrite(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
151 bwrite(fd, (genericptr_t) tune, sizeof tune);
153 for (count = 0, curr = branches; curr; curr = curr->next)
155 bwrite(fd, (genericptr_t) &count, sizeof(count));
157 for (curr = branches; curr; curr = curr->next)
158 bwrite(fd, (genericptr_t) curr, sizeof(branch));
160 count = maxledgerno();
161 bwrite(fd, (genericptr_t) &count, sizeof count);
162 bwrite(fd, (genericptr_t) level_info,
163 (unsigned) count * sizeof(struct linfo));
164 bwrite(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
166 for (count = 0, curr_ms = mapseenchn; curr_ms;
167 curr_ms = curr_ms->next)
169 bwrite(fd, (genericptr_t) &count, sizeof(count));
171 for (curr_ms = mapseenchn; curr_ms; curr_ms = curr_ms->next)
172 save_mapseen(fd, curr_ms);
176 for (curr = branches; curr; curr = next) {
178 free((genericptr_t) curr);
181 for (curr_ms = mapseenchn; curr_ms; curr_ms = next_ms) {
182 next_ms = curr_ms->next;
184 free((genericptr_t) curr_ms->custom);
185 free((genericptr_t) curr_ms);
191 /* Restore the dungeon structures. */
198 mapseen *curr_ms, *last_ms;
200 mread(fd, (genericptr_t) &n_dgns, sizeof(n_dgns));
201 mread(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned) n_dgns);
202 mread(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
203 mread(fd, (genericptr_t) tune, sizeof tune);
205 last = branches = (branch *) 0;
207 mread(fd, (genericptr_t) &count, sizeof(count));
208 for (i = 0; i < count; i++) {
209 curr = (branch *) alloc(sizeof(branch));
210 mread(fd, (genericptr_t) curr, sizeof(branch));
211 curr->next = (branch *) 0;
219 mread(fd, (genericptr_t) &count, sizeof(count));
220 if (count >= MAXLINFO)
221 panic("level information count larger (%d) than allocated size",
223 mread(fd, (genericptr_t) level_info,
224 (unsigned) count * sizeof(struct linfo));
225 mread(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
227 mread(fd, (genericptr_t) &count, sizeof(count));
228 last_ms = (mapseen *) 0;
229 for (i = 0; i < count; i++) {
230 curr_ms = load_mapseen(fd);
231 curr_ms->next = (mapseen *) 0;
233 last_ms->next = curr_ms;
235 mapseenchn = curr_ms;
241 Fread(ptr, size, nitems, stream)
248 if ((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) {
250 "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
251 (size * nitems), (size * cnt));
252 nh_terminate(EXIT_FAILURE);
262 for (i = 0; i < n_dgns; i++)
263 if (!strcmp(dungeons[i].dname, s))
266 panic("Couldn't resolve dungeon number for name \"%s\".", s);
276 for (curr = sp_levchn; curr; curr = curr->next)
277 if (!strcmpi(s, curr->proto))
282 /* Find the branch that links the named dungeon. */
285 const char *s; /* dungeon name */
286 struct proto_dungeon *pd;
291 for (i = 0; i < pd->n_brs; i++)
292 if (!strcmp(pd->tmpbranch[i].name, s))
295 panic("find_branch: can't find %s", s);
297 /* support for level tport by name */
301 for (br = branches; br; br = br->next) {
302 dnam = dungeons[br->end2.dnum].dname;
303 if (!strcmpi(dnam, s)
304 || (!strncmpi(dnam, "The ", 4) && !strcmpi(dnam + 4, s)))
307 i = br ? ((ledger_no(&br->end1) << 8) | ledger_no(&br->end2)) : -1;
313 * Find the "parent" by searching the prototype branch list for the branch
314 * listing, then figuring out to which dungeon it belongs.
318 const char *s; /* dungeon name */
319 struct proto_dungeon *pd;
324 i = find_branch(s, pd);
326 * Got branch, now find parent dungeon. Stop if we have reached
327 * "this" dungeon (if we haven't found it by now it is an error).
329 for (pdnum = 0; strcmp(pd->tmpdungeon[pdnum].name, s); pdnum++)
330 if ((i -= pd->tmpdungeon[pdnum].branches) < 0)
333 panic("parent_dnum: couldn't resolve branch.");
339 * Return a starting point and number of successive positions a level
340 * or dungeon entrance can occupy.
342 * Note: This follows the acouple (instead of the rcouple) rules for a
343 * negative random component (randc < 0). These rules are found
344 * in dgn_comp.y. The acouple [absolute couple] section says that
345 * a negative random component means from the (adjusted) base to the
346 * end of the dungeon.
349 level_range(dgn, base, randc, chain, pd, adjusted_base)
351 int base, randc, chain;
352 struct proto_dungeon *pd;
355 int lmax = dungeons[dgn].num_dunlevs;
357 if (chain >= 0) { /* relative to a special level */
358 s_level *levtmp = pd->final_lev[chain];
360 panic("level_range: empty chain level!");
362 base += levtmp->dlevel.dlevel;
363 } else { /* absolute in the dungeon */
364 /* from end of dungeon */
366 base = (lmax + base + 1);
369 if (base < 1 || base > lmax)
370 panic("level_range: base value out of range");
372 *adjusted_base = base;
374 if (randc == -1) { /* from base to end of dungeon */
375 return (lmax - base + 1);
377 /* make sure we don't run off the end of the dungeon */
378 return (((base + randc - 1) > lmax) ? lmax - base + 1 : randc);
379 } /* else only one choice */
386 struct proto_dungeon *pd;
388 int i, j, num, base, dnum = parent_dnum(s, pd);
391 i = find_branch(s, pd);
392 num = level_range(dnum, pd->tmpbranch[i].lev.base,
393 pd->tmpbranch[i].lev.rand, pd->tmpbranch[i].chain, pd,
396 /* KMH -- Try our best to find a level without an existing branch */
401 for (curr = branches; curr; curr = curr->next)
402 if ((curr->end1.dnum == dnum && curr->end1.dlevel == base + i)
403 || (curr->end2.dnum == dnum && curr->end2.dlevel == base + i))
405 } while (curr && i != j);
409 /* Convert from the temporary branch type to the dungeon branch type. */
411 correct_branch_type(tbr)
412 struct tmpbranch *tbr;
418 return tbr->up ? BR_NO_END1 : BR_NO_END2;
420 return tbr->up ? BR_NO_END2 : BR_NO_END1;
424 impossible("correct_branch_type: unknown branch type");
429 * Add the given branch to the branch list. The branch list is ordered
430 * by end1 dungeon and level followed by end2 dungeon and level. If
431 * extract_first is true, then the branch is already part of the list
432 * but needs to be repositioned.
435 insert_branch(new_branch, extract_first)
437 boolean extract_first;
440 long new_val, curr_val, prev_val;
443 for (prev = 0, curr = branches; curr; prev = curr, curr = curr->next)
444 if (curr == new_branch)
448 panic("insert_branch: not found");
450 prev->next = curr->next;
452 branches = curr->next;
454 new_branch->next = (branch *) 0;
456 /* Convert the branch into a unique number so we can sort them. */
457 #define branch_val(bp) \
458 ((((long) (bp)->end1.dnum * (MAXLEVEL + 1) + (long) (bp)->end1.dlevel) \
459 * (MAXDUNGEON + 1) * (MAXLEVEL + 1)) \
460 + ((long) (bp)->end2.dnum * (MAXLEVEL + 1) + (long) (bp)->end2.dlevel))
463 * Insert the new branch into the correct place in the branch list.
467 new_val = branch_val(new_branch);
468 for (curr = branches; curr;
469 prev_val = curr_val, prev = curr, curr = curr->next) {
470 curr_val = branch_val(curr);
471 if (prev_val < new_val && new_val <= curr_val)
475 new_branch->next = curr;
476 prev->next = new_branch;
478 new_branch->next = branches;
479 branches = new_branch;
483 /* Add a dungeon branch to the branch list. */
485 add_branch(dgn, child_entry_level, pd)
487 int child_entry_level;
488 struct proto_dungeon *pd;
490 static int branch_id = 0;
494 branch_num = find_branch(dungeons[dgn].dname, pd);
495 new_branch = (branch *) alloc(sizeof(branch));
496 (void) memset((genericptr_t)new_branch, 0, sizeof(branch));
497 new_branch->next = (branch *) 0;
498 new_branch->id = branch_id++;
499 new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
500 new_branch->end1.dnum = parent_dnum(dungeons[dgn].dname, pd);
501 new_branch->end1.dlevel = parent_dlevel(dungeons[dgn].dname, pd);
502 new_branch->end2.dnum = dgn;
503 new_branch->end2.dlevel = child_entry_level;
504 new_branch->end1_up = pd->tmpbranch[branch_num].up ? TRUE : FALSE;
506 insert_branch(new_branch, FALSE);
511 * Add new level to special level chain. Insert it in level order with the
512 * other levels in this dungeon. This assumes that we are never given a
513 * level that has a dungeon number less than the dungeon number of the
520 s_level *prev, *curr;
522 prev = (s_level *) 0;
523 for (curr = sp_levchn; curr; curr = curr->next) {
524 if (curr->dlevel.dnum == new_lev->dlevel.dnum
525 && curr->dlevel.dlevel > new_lev->dlevel.dlevel)
530 new_lev->next = sp_levchn;
533 new_lev->next = curr;
534 prev->next = new_lev;
539 init_level(dgn, proto_index, pd)
540 int dgn, proto_index;
541 struct proto_dungeon *pd;
544 struct tmplevel *tlevel = &pd->tmplevel[proto_index];
546 pd->final_lev[proto_index] = (s_level *) 0; /* no "real" level */
547 if (!wizard && tlevel->chance <= rn2(100))
550 pd->final_lev[proto_index] = new_level =
551 (s_level *) alloc(sizeof(s_level));
552 (void) memset((genericptr_t)new_level, 0, sizeof(s_level));
553 /* load new level with data */
554 Strcpy(new_level->proto, tlevel->name);
555 new_level->boneid = tlevel->boneschar;
556 new_level->dlevel.dnum = dgn;
557 new_level->dlevel.dlevel = 0; /* for now */
559 new_level->flags.town = !!(tlevel->flags & TOWN);
560 new_level->flags.hellish = !!(tlevel->flags & HELLISH);
561 new_level->flags.maze_like = !!(tlevel->flags & MAZELIKE);
562 new_level->flags.rogue_like = !!(tlevel->flags & ROGUELIKE);
563 new_level->flags.align = ((tlevel->flags & D_ALIGN_MASK) >> 4);
564 if (!new_level->flags.align)
565 new_level->flags.align =
566 ((pd->tmpdungeon[dgn].flags & D_ALIGN_MASK) >> 4);
568 new_level->rndlevs = tlevel->rndlevs;
569 new_level->next = (s_level *) 0;
573 possible_places(idx, map, pd)
574 int idx; /* prototype index */
575 boolean *map; /* array MAXLEVEL+1 in length */
576 struct proto_dungeon *pd;
579 s_level *lev = pd->final_lev[idx];
581 /* init level possibilities */
582 for (i = 0; i <= MAXLEVEL; i++)
585 /* get base and range and set those entries to true */
586 count = level_range(lev->dlevel.dnum, pd->tmplevel[idx].lev.base,
587 pd->tmplevel[idx].lev.rand, pd->tmplevel[idx].chain,
589 for (i = start; i < start + count; i++)
592 /* mark off already placed levels */
593 for (i = pd->start; i < idx; i++) {
594 if (pd->final_lev[i] && map[pd->final_lev[i]->dlevel.dlevel]) {
595 map[pd->final_lev[i]->dlevel.dlevel] = FALSE;
603 /* Pick the nth TRUE entry in the given boolean array. */
606 boolean *map; /* an array MAXLEVEL+1 in size */
610 for (i = 1; i <= MAXLEVEL; i++)
611 if (map[i] && !nth--)
613 panic("pick_level: ran out of valid levels");
618 static void FDECL(indent, (int));
630 * Place a level. First, find the possible places on a dungeon map
631 * template. Next pick one. Then try to place the next level. If
632 * successful, we're done. Otherwise, try another (and another) until
633 * all possible places have been tried. If all possible places have
634 * been exhausted, return false.
637 place_level(proto_index, pd)
639 struct proto_dungeon *pd;
641 boolean map[MAXLEVEL + 1]; /* valid levels are 1..MAXLEVEL inclusive */
648 if (proto_index == pd->n_levs)
649 return TRUE; /* at end of proto levels */
651 lev = pd->final_lev[proto_index];
653 /* No level created for this prototype, goto next. */
655 return place_level(proto_index + 1, pd);
657 npossible = possible_places(proto_index, map, pd);
659 for (; npossible; --npossible) {
660 lev->dlevel.dlevel = pick_level(map, rn2(npossible));
662 indent(proto_index - pd->start);
663 fprintf(stderr, "%s: trying %d [ ", lev->proto, lev->dlevel.dlevel);
664 for (i = 1; i <= MAXLEVEL; i++)
666 fprintf(stderr, "%d ", i);
667 fprintf(stderr, "]\n");
669 if (place_level(proto_index + 1, pd))
671 map[lev->dlevel.dlevel] = FALSE; /* this choice didn't work */
674 indent(proto_index - pd->start);
675 fprintf(stderr, "%s: failed\n", lev->proto);
681 const char *lev_name;
683 } level_map[] = { { "air", &air_level },
684 { "asmodeus", &asmodeus_level },
685 { "astral", &astral_level },
686 { "baalz", &baalzebub_level },
687 { "bigrm", &bigroom_level },
688 { "castle", &stronghold_level },
689 { "earth", &earth_level },
690 { "fakewiz1", &portal_level },
691 { "fire", &fire_level },
692 { "juiblex", &juiblex_level },
693 { "knox", &knox_level },
694 { "medusa", &medusa_level },
695 { "oracle", &oracle_level },
696 { "orcus", &orcus_level },
697 { "rogue", &rogue_level },
698 { "sanctum", &sanctum_level },
699 { "valley", &valley_level },
700 { "water", &water_level },
701 { "wizard1", &wiz1_level },
702 { "wizard2", &wiz2_level },
703 { "wizard3", &wiz3_level },
704 { "minend", &mineend_level },
705 { "soko1", &sokoend_level },
706 { X_START, &qstart_level },
707 { X_LOCATE, &qlocate_level },
708 { X_GOAL, &nemesis_level },
709 { "", (d_level *) 0 } };
711 /* initialize the "dungeon" structs */
716 register int i, cl = 0, cb = 0;
718 struct proto_dungeon pd;
719 struct level_map *lev_map;
720 struct version_info vers_info;
722 pd.n_levs = pd.n_brs = 0;
724 dgn_file = dlb_fopen(DUNGEON_FILE, RDBMODE);
727 Sprintf(tbuf, "Cannot open dungeon description - \"%s", DUNGEON_FILE);
728 #ifdef DLBRSRC /* using a resource from the executable */
729 Strcat(tbuf, "\" resource!");
730 #else /* using a file or DLB file */
732 Strcat(tbuf, "\" from ");
733 #ifdef PREFIXES_IN_USE
734 Strcat(tbuf, "\n\"");
735 if (fqn_prefix[DATAPREFIX])
736 Strcat(tbuf, fqn_prefix[DATAPREFIX]);
740 Strcat(tbuf, DLBFILE);
742 Strcat(tbuf, "\" file!");
745 interject_assistance(1, INTERJECT_PANIC, (genericptr_t) tbuf,
746 (genericptr_t) fqn_prefix[DATAPREFIX]);
751 /* validate the data's version against the program's version */
752 Fread((genericptr_t) &vers_info, sizeof vers_info, 1, dgn_file);
753 /* we'd better clear the screen now, since when error messages come from
754 * check_version() they will be printed using pline(), which doesn't
755 * mix with the raw messages that might be already on the screen
757 if (iflags.window_inited)
758 clear_nhwindow(WIN_MAP);
759 if (!check_version(&vers_info, DUNGEON_FILE, TRUE))
760 panic("Dungeon description not valid.");
763 * Read in each dungeon and transfer the results to the internal
766 sp_levchn = (s_level *) 0;
767 Fread((genericptr_t) &n_dgns, sizeof(int), 1, dgn_file);
768 if (n_dgns >= MAXDUNGEON)
769 panic("init_dungeons: too many dungeons");
771 for (i = 0; i < n_dgns; i++) {
772 Fread((genericptr_t) &pd.tmpdungeon[i], sizeof(struct tmpdungeon), 1,
774 if (!wizard && pd.tmpdungeon[i].chance
775 && (pd.tmpdungeon[i].chance <= rn2(100))) {
778 /* skip over any levels or branches */
779 for (j = 0; j < pd.tmpdungeon[i].levels; j++)
780 Fread((genericptr_t) &pd.tmplevel[cl],
781 sizeof(struct tmplevel), 1, dgn_file);
783 for (j = 0; j < pd.tmpdungeon[i].branches; j++)
784 Fread((genericptr_t) &pd.tmpbranch[cb],
785 sizeof(struct tmpbranch), 1, dgn_file);
791 Strcpy(dungeons[i].dname, pd.tmpdungeon[i].name);
792 Strcpy(dungeons[i].proto, pd.tmpdungeon[i].protoname);
793 dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
795 if (pd.tmpdungeon[i].lev.rand)
796 dungeons[i].num_dunlevs = (xchar) rn1(pd.tmpdungeon[i].lev.rand,
797 pd.tmpdungeon[i].lev.base);
799 dungeons[i].num_dunlevs = (xchar) pd.tmpdungeon[i].lev.base;
802 dungeons[i].ledger_start = 0;
803 dungeons[i].depth_start = 1;
804 dungeons[i].dunlev_ureached = 1;
806 dungeons[i].ledger_start =
807 dungeons[i - 1].ledger_start + dungeons[i - 1].num_dunlevs;
808 dungeons[i].dunlev_ureached = 0;
811 dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH);
812 dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE);
813 dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE);
814 dungeons[i].flags.align =
815 ((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4);
817 * Set the entry level for this dungeon. The pd.tmpdungeon entry
819 * < 0 from bottom (-1 == bottom level)
821 * > 0 actual level (1 = top)
823 * Note that the entry_lev field in the dungeon structure is
824 * redundant. It is used only here and in print_dungeon().
826 if (pd.tmpdungeon[i].entry_lev < 0) {
827 dungeons[i].entry_lev =
828 dungeons[i].num_dunlevs + pd.tmpdungeon[i].entry_lev + 1;
829 if (dungeons[i].entry_lev <= 0)
830 dungeons[i].entry_lev = 1;
831 } else if (pd.tmpdungeon[i].entry_lev > 0) {
832 dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
833 if (dungeons[i].entry_lev > dungeons[i].num_dunlevs)
834 dungeons[i].entry_lev = dungeons[i].num_dunlevs;
835 } else { /* default */
836 dungeons[i].entry_lev = 1; /* defaults to top level */
839 if (i) { /* set depth */
844 br = add_branch(i, dungeons[i].entry_lev, &pd);
846 /* Get the depth of the connecting end. */
847 if (br->end1.dnum == i) {
848 from_depth = depth(&br->end2);
849 from_up = !br->end1_up;
851 from_depth = depth(&br->end1);
852 from_up = br->end1_up;
856 * Calculate the depth of the top of the dungeon via
857 * its branch. First, the depth of the entry point:
859 * depth of branch from "parent" dungeon
860 * + -1 or 1 depending on an up or down stair or
863 * Followed by the depth of the top of the dungeon:
865 * - (entry depth - 1)
867 * We'll say that portals stay on the same depth.
869 dungeons[i].depth_start =
870 from_depth + (br->type == BR_PORTAL ? 0 : (from_up ? -1 : 1))
871 - (dungeons[i].entry_lev - 1);
874 /* this is redundant - it should have been flagged by dgn_comp */
875 if (dungeons[i].num_dunlevs > MAXLEVEL)
876 dungeons[i].num_dunlevs = MAXLEVEL;
878 pd.start = pd.n_levs; /* save starting point */
879 pd.n_levs += pd.tmpdungeon[i].levels;
880 if (pd.n_levs > LEV_LIMIT)
881 panic("init_dungeon: too many special levels");
883 * Read in the prototype special levels. Don't add generated
884 * special levels until they are all placed.
886 for (; cl < pd.n_levs; cl++) {
887 Fread((genericptr_t) &pd.tmplevel[cl], sizeof(struct tmplevel), 1,
889 init_level(i, cl, &pd);
892 * Recursively place the generated levels for this dungeon. This
893 * routine will attempt all possible combinations before giving
896 if (!place_level(pd.start, &pd))
897 panic("init_dungeon: couldn't place levels");
899 fprintf(stderr, "--- end of dungeon %d ---\n", i);
903 for (; pd.start < pd.n_levs; pd.start++)
904 if (pd.final_lev[pd.start])
905 add_level(pd.final_lev[pd.start]);
907 pd.n_brs += pd.tmpdungeon[i].branches;
908 if (pd.n_brs > BRANCH_LIMIT)
909 panic("init_dungeon: too many branches");
910 for (; cb < pd.n_brs; cb++)
911 Fread((genericptr_t) &pd.tmpbranch[cb], sizeof(struct tmpbranch),
914 (void) dlb_fclose(dgn_file);
916 for (i = 0; i < 5; i++)
917 tune[i] = 'A' + rn2(7);
921 * Find most of the special levels and dungeons so we can access their
924 for (lev_map = level_map; lev_map->lev_name[0]; lev_map++) {
925 x = find_level(lev_map->lev_name);
927 assign_level(lev_map->lev_spec, &x->dlevel);
928 if (!strncmp(lev_map->lev_name, "x-", 2)) {
929 /* This is where the name substitution on the
930 * levels of the quest dungeon occur.
932 Sprintf(x->proto, "%s%s", urole.filecode,
933 &lev_map->lev_name[1]);
934 } else if (lev_map->lev_spec == &knox_level) {
937 * Kludge to allow floating Knox entrance. We
938 * specify a floating entrance by the fact that
939 * its entrance (end1) has a bogus dnum, namely
942 for (br = branches; br; br = br->next)
943 if (on_level(&br->end2, &knox_level))
947 br->end1.dnum = n_dgns;
948 /* adjust the branch's position on the list */
949 insert_branch(br, TRUE);
954 * I hate hardwiring these names. :-(
957 quest_dnum = dname_to_dnum("The Quest");
959 quest_dnum = dname_to_dnum("
\83N
\83G
\83X
\83g");
961 sokoban_dnum = dname_to_dnum("Sokoban");
963 sokoban_dnum = dname_to_dnum("
\91q
\8cÉ
\94Ô");
965 mines_dnum = dname_to_dnum("The Gnomish Mines");
967 mines_dnum = dname_to_dnum("
\83m
\81[
\83\80\82Ì
\8dz
\8eR");
969 tower_dnum = dname_to_dnum("Vlad's Tower");
971 tower_dnum = dname_to_dnum("
\83\94\83\89\83h
\8cò
\82Ì
\93\83");
973 /* one special fixup for dummy surface level */
974 if ((x = find_level("dummy")) != 0) {
976 /* the code above puts earth one level above dungeon level #1,
977 making the dummy level overlay level 1; but the whole reason
978 for having the dummy level is to make earth have depth -1
979 instead of 0, so adjust the start point to shift endgame up */
980 if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
981 dungeons[i].depth_start -= 1;
982 /* TODO: strip "dummy" out all the way here,
983 so that it's hidden from <ctrl/O> feedback. */
991 /* return the level number for lev in *this* dungeon */
999 /* return the lowest level number for *this* dungeon */
1001 dunlevs_in_dungeon(lev)
1004 return dungeons[lev->dnum].num_dunlevs;
1007 /* return the lowest level explored in the game*/
1009 deepest_lev_reached(noquest)
1012 /* this function is used for three purposes: to provide a factor
1013 * of difficulty in monster generation; to provide a factor of
1014 * difficulty in experience calculations (botl.c and end.c); and
1015 * to insert the deepest level reached in the game in the topten
1016 * display. the 'noquest' arg switch is required for the latter.
1018 * from the player's point of view, going into the Quest is _not_
1019 * going deeper into the dungeon -- it is going back "home", where
1020 * the dungeon starts at level 1. given the setup in dungeon.def,
1021 * the depth of the Quest (thought of as starting at level 1) is
1022 * never lower than the level of entry into the Quest, so we exclude
1023 * the Quest from the topten "deepest level reached" display
1024 * calculation. _However_ the Quest is a difficult dungeon, so we
1025 * include it in the factor of difficulty calculations.
1029 register schar ret = 0;
1031 for (i = 0; i < n_dgns; i++) {
1032 if (noquest && i == quest_dnum)
1034 tmp.dlevel = dungeons[i].dunlev_ureached;
1035 if (tmp.dlevel == 0)
1038 if (depth(&tmp) > ret)
1044 /* return a bookkeeping level number for purpose of comparisons and
1050 return (xchar) (lev->dlevel + dungeons[lev->dnum].ledger_start);
1054 * The last level in the bookkeeping list of level is the bottom of the last
1055 * dungeon in the dungeons[] array.
1057 * Maxledgerno() -- which is the max number of levels in the bookkeeping
1058 * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1059 * returns the max number of levels in lev's dungeon, and both should
1060 * not be confused with deepest_lev_reached() -- which returns the lowest
1061 * depth visited by the player.
1066 return (xchar) (dungeons[n_dgns - 1].ledger_start
1067 + dungeons[n_dgns - 1].num_dunlevs);
1070 /* return the dungeon that this ledgerno exists in */
1072 ledger_to_dnum(ledgerno)
1077 /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1078 for (i = 0; i < n_dgns; i++)
1079 if (dungeons[i].ledger_start < ledgerno
1080 && ledgerno <= dungeons[i].ledger_start + dungeons[i].num_dunlevs)
1083 panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno);
1088 /* return the level of the dungeon this ledgerno exists in */
1090 ledger_to_dlev(ledgerno)
1093 return (xchar) (ledgerno
1094 - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
1097 /* returns the depth of a level, in floors below the surface
1098 (note levels in different dungeons can have the same depth) */
1103 return (schar) (dungeons[lev->dnum].depth_start + lev->dlevel - 1);
1106 /* are "lev1" and "lev2" actually the same? */
1108 on_level(lev1, lev2)
1109 d_level *lev1, *lev2;
1111 return (boolean) (lev1->dnum == lev2->dnum
1112 && lev1->dlevel == lev2->dlevel);
1115 /* is this level referenced in the special level chain? */
1122 for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
1123 if (on_level(lev, &levtmp->dlevel))
1126 return (s_level *) 0;
1130 * Is this a multi-dungeon branch level? If so, return a pointer to the
1131 * branch. Otherwise, return null.
1139 for (curr = branches; curr; curr = curr->next) {
1140 if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
1143 return (branch *) 0;
1146 /* returns True iff the branch 'lev' is in a branch which builds up */
1151 dungeon *dptr = &dungeons[lev->dnum];
1153 * FIXME: this misclassifies a single level branch reached via stairs
1154 * from below. Saving grace is that no such branches currently exist.
1156 return (boolean) (dptr->num_dunlevs > 1
1157 && dptr->entry_lev == dptr->num_dunlevs);
1160 /* goto the next level (or appropriate dungeon) */
1162 next_level(at_stairs)
1165 if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1166 /* Taking a down dungeon branch. */
1167 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1169 /* Going down a stairs or jump in a trap door. */
1172 newlevel.dnum = u.uz.dnum;
1173 newlevel.dlevel = u.uz.dlevel + 1;
1174 goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
1178 /* goto the previous level (or appropriate dungeon) */
1180 prev_level(at_stairs)
1183 if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1184 /* Taking an up dungeon branch. */
1185 /* KMH -- Upwards branches are okay if not level 1 */
1186 /* (Just make sure it doesn't go above depth 1) */
1187 if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
1190 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1192 /* Going up a stairs or rising through the ceiling. */
1194 newlevel.dnum = u.uz.dnum;
1195 newlevel.dlevel = u.uz.dlevel - 1;
1196 goto_level(&newlevel, at_stairs, FALSE, FALSE);
1207 cliparound(u.ux, u.uy);
1209 /* ridden steed always shares hero's location */
1211 u.usteed->mx = u.ux, u.usteed->my = u.uy;
1212 /* when changing levels, don't leave old position set with
1213 stale values from previous level */
1214 if (!on_level(&u.uz, &u.uz0))
1215 u.ux0 = u.ux, u.uy0 = u.uy;
1218 /* place you on a random location */
1220 u_on_rndspot(upflag)
1223 int up = (upflag & 1), was_in_W_tower = (upflag & 2);
1226 * Place the hero at a random location within the relevant region.
1227 * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1228 * Unspecified region (.lx == 0) defaults to entire level.
1230 if (was_in_W_tower && On_W_tower_level(&u.uz))
1231 /* Stay inside the Wizard's tower when feasible.
1232 We use the W Tower's exclusion region for the
1233 destination instead of its enclosing region.
1234 Note: up vs down doesn't matter in this case
1235 because both specify the same exclusion area. */
1236 place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy,
1237 0, 0, 0, 0, LR_DOWNTELE, (d_level *) 0);
1239 place_lregion(updest.lx, updest.ly, updest.hx, updest.hy,
1240 updest.nlx, updest.nly, updest.nhx, updest.nhy,
1241 LR_UPTELE, (d_level *) 0);
1243 place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy,
1244 dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy,
1245 LR_DOWNTELE, (d_level *) 0);
1248 /* place you on the special staircase */
1250 u_on_sstairs(upflag)
1254 u_on_newpos(sstairs.sx, sstairs.sy);
1256 u_on_rndspot(upflag);
1259 /* place you on upstairs (or special equivalent) */
1264 u_on_newpos(xupstair, yupstair);
1266 u_on_sstairs(0); /* destination upstairs implies moving down */
1269 /* place you on dnstairs (or special equivalent) */
1274 u_on_newpos(xdnstair, ydnstair);
1276 u_on_sstairs(1); /* destination dnstairs implies moving up */
1283 return (boolean) ((x == xupstair && y == yupstair)
1284 || (x == xdnstair && y == ydnstair)
1285 || (x == xdnladder && y == ydnladder)
1286 || (x == xupladder && y == yupladder)
1287 || (x == sstairs.sx && y == sstairs.sy));
1294 return (boolean) (lev->dlevel == dungeons[lev->dnum].num_dunlevs);
1301 return (boolean) (!level.flags.hardfloor
1302 && !Is_botlevel(lev)
1303 && !Invocation_lev(lev));
1307 * Like Can_dig_down (above), but also allows falling through on the
1308 * stronghold level. Normally, the bottom level of a dungeon resists
1309 * both digging and falling.
1315 return (boolean) (Can_dig_down(lev) || Is_stronghold(lev));
1319 * True if one can rise up a level (e.g. cursed gain level).
1320 * This happens on intermediate dungeon levels or on any top dungeon
1321 * level that has a stairwell style branch to the next higher dungeon.
1322 * Checks for amulets and such must be done elsewhere.
1325 Can_rise_up(x, y, lev)
1329 /* can't rise up from inside the top of the Wizard's tower */
1330 /* KMH -- or in sokoban */
1331 if (In_endgame(lev) || In_sokoban(lev)
1332 || (Is_wiz1_level(lev) && In_W_tower(x, y, lev)))
1334 return (boolean) (lev->dlevel > 1
1335 || (dungeons[lev->dnum].entry_lev == 1
1336 && ledger_no(lev) != 1
1337 && sstairs.sx && sstairs.up));
1344 /* [what about level 1 of the quest?] */
1345 return (boolean) (!Is_airlevel(lev) && !Is_waterlevel(lev));
1349 * It is expected that the second argument of get_level is a depth value,
1350 * either supplied by the user (teleport control) or randomly generated.
1351 * But more than one level can be at the same depth. If the target level
1352 * is "above" the present depth location, get_level must trace "up" from
1353 * the player's location (through the ancestors dungeons) the dungeon
1354 * within which the target level is located. With only one exception
1355 * which does not pass through this routine (see level_tele), teleporting
1356 * "down" is confined to the current dungeon. At present, level teleport
1357 * in dungeons that build up is confined within them.
1360 get_level(newlevel, levnum)
1365 xchar dgn = u.uz.dnum;
1368 /* can only currently happen in endgame */
1369 levnum = u.uz.dlevel;
1371 > dungeons[dgn].depth_start + dungeons[dgn].num_dunlevs - 1) {
1372 /* beyond end of dungeon, jump to last level */
1373 levnum = dungeons[dgn].num_dunlevs;
1375 /* The desired level is in this dungeon or a "higher" one. */
1378 * Branch up the tree until we reach a dungeon that contains the
1381 if (levnum < dungeons[dgn].depth_start) {
1384 * Find the parent dungeon of this dungeon.
1386 * This assumes that end2 is always the "child" and it is
1389 for (br = branches; br; br = br->next)
1390 if (br->end2.dnum == dgn)
1393 panic("get_level: can't find parent dungeon");
1395 dgn = br->end1.dnum;
1396 } while (levnum < dungeons[dgn].depth_start);
1399 /* We're within the same dungeon; calculate the level. */
1400 levnum = levnum - dungeons[dgn].depth_start + 1;
1403 newlevel->dnum = dgn;
1404 newlevel->dlevel = levnum;
1407 /* are you in the quest dungeon? */
1412 return (boolean) (lev->dnum == quest_dnum);
1415 /* are you in the mines dungeon? */
1420 return (boolean) (lev->dnum == mines_dnum);
1424 * Return the branch for the given dungeon.
1426 * This function assumes:
1427 * + This is not called with "Dungeons of Doom".
1428 * + There is only _one_ branch to a given dungeon.
1429 * + Field end2 is the "child" dungeon.
1438 dnum = dname_to_dnum(s);
1440 /* Find the branch that connects to dungeon i's branch. */
1441 for (br = branches; br; br = br->next)
1442 if (br->end2.dnum == dnum)
1446 panic("dgn_entrance: can't find entrance to %s", s);
1452 * This returns true if the hero is on the same level as the entrance to
1453 * the named dungeon.
1455 * Called from do.c and mklev.c.
1457 * Assumes that end1 is always the "parent".
1465 br = dungeon_branch(s);
1466 return on_level(&u.uz, &br->end1) ? TRUE : FALSE;
1469 /* is `lev' part of Vlad's tower? */
1474 return (boolean) (lev->dnum == tower_dnum);
1477 /* is `lev' a level containing the Wizard's tower? */
1479 On_W_tower_level(lev)
1482 return (boolean) (Is_wiz1_level(lev)
1483 || Is_wiz2_level(lev)
1484 || Is_wiz3_level(lev));
1487 /* is <x,y> of `lev' inside the Wizard's tower? */
1489 In_W_tower(x, y, lev)
1493 if (!On_W_tower_level(lev))
1496 * Both of the exclusion regions for arriving via level teleport
1497 * (from above or below) define the tower's boundary.
1498 * assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1501 return (boolean) within_bounded_area(x, y, dndest.nlx, dndest.nly,
1502 dndest.nhx, dndest.nhy);
1504 impossible("No boundary for Wizard's Tower?");
1508 /* are you in one of the Hell levels? */
1513 return (boolean) (dungeons[lev->dnum].flags.hellish);
1516 /* sets *lev to be the gateway to Gehennom... */
1521 lev->dnum = valley_level.dnum;
1525 /* go directly to hell... */
1527 goto_hell(at_stairs, falling)
1528 boolean at_stairs, falling;
1533 goto_level(&lev, at_stairs, falling, FALSE);
1536 /* equivalent to dest = source */
1538 assign_level(dest, src)
1539 d_level *dest, *src;
1541 dest->dnum = src->dnum;
1542 dest->dlevel = src->dlevel;
1545 /* dest = src + rn1(range) */
1547 assign_rnd_level(dest, src, range)
1548 d_level *dest, *src;
1551 dest->dnum = src->dnum;
1552 dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range));
1554 if (dest->dlevel > dunlevs_in_dungeon(dest))
1555 dest->dlevel = dunlevs_in_dungeon(dest);
1556 else if (dest->dlevel < 1)
1564 s_level *lev = Is_special(&u.uz);
1567 if (lev && lev->flags.align)
1569 return lev->flags.align;
1571 if (dungeons[u.uz.dnum].flags.align)
1573 return dungeons[u.uz.dnum].flags.align;
1576 return Align2amask(al);
1583 return (boolean) (In_hell(lev)
1584 && lev->dlevel == dungeons[lev->dnum].num_dunlevs - 1);
1587 /* use instead of depth() wherever a degree of difficulty is made
1588 * dependent on the location in the dungeon (eg. monster creation).
1595 if (In_endgame(&u.uz)) {
1596 res = depth(&sanctum_level) + u.ulevel / 2;
1597 } else if (u.uhave.amulet) {
1598 res = deepest_lev_reached(FALSE);
1601 /* depth() is the number of elevation units (levels) below
1602 the theoretical surface; in a builds-up branch, that value
1603 ends up making the harder to reach levels be treated as if
1604 they were easier; adjust for the extra effort involved in
1605 going down to the entrance and then up to the location */
1606 if (builds_up(&u.uz))
1607 res += 2 * (dungeons[u.uz.dnum].entry_lev - u.uz.dlevel + 1);
1609 * 'Proof' by example: suppose the entrance to sokoban is
1610 * on dungeon level 9, leading up to bottom sokoban level
1611 * of 8 [entry_lev]. When the hero is on sokoban level 8
1612 * [uz.dlevel], depth() yields eight but he has ventured
1613 * one level beyond 9, so difficulty depth should be 10:
1614 * 8 + 2 * (8 - 8 + 1) => 10.
1615 * Going up to 7, depth is 7 but hero will be two beyond 9:
1616 * 7 + 2 * (8 - 7 + 1) => 11.
1617 * When he goes up to level 6, three levels beyond 9:
1618 * 6 + 2 * (8 - 6 + 1) => 12.
1619 * And the top level of sokoban at 5, four levels beyond 9:
1620 * 5 + 2 * (8 - 5 + 1) => 13.
1621 * The same applies to Vlad's Tower, although the increment
1622 * there is inconsequential compared to overall depth.
1626 * The inside of the Wizard's Tower is also effectively a
1627 * builds-up area, reached from a portal an arbitrary distance
1628 * below rather than stairs 1 level beneath the entry level.
1630 else if (On_W_tower_level(&u.uz) && In_W_tower(some_X, some_Y, &u.uz))
1631 res += (fakewiz1.dlev - u.uz.dlev);
1633 * Handling this properly would need more information here:
1634 * an inside/outside flag, or coordinates to calculate it.
1635 * Unfortunately level difficulty may be wanted before
1636 * coordinates have been chosen so simply extending this
1637 * routine to take extra arguments is not sufficient to cope.
1638 * The difference beyond naive depth-from-surface is small
1639 * relative to the overall depth, so just ignore complications
1647 /* Take one word and try to match it to a level.
1648 * Recognized levels are as shown by print_dungeon().
1655 s_level *slev = (s_level *)0;
1662 /* look at the player's custom level annotations first */
1663 if ((mseen = find_mapseen_by_str(nam)) != 0) {
1666 /* no matching annotation, check whether they used a name we know */
1668 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
1669 /* allow strings like "the oracle level" to find "oracle" */
1670 if (!strncmpi(nam, "the ", 4))
1672 if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
1673 nam = strcpy(buf, nam);
1674 *(eos(buf) - 6) = '\0';
1676 /* hell is the old name, and wouldn't match; gehennom would match its
1677 branch, yielding the castle level instead of the valley of the dead */
1678 if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1679 if (In_V_tower(&u.uz))
1680 nam = " to Vlad's tower"; /* branch to... */
1686 if ((slev = find_level(nam)) != 0)
1687 dlev = slev->dlevel;
1690 if (mseen || slev) {
1691 idx = ledger_no(&dlev);
1692 if ((dlev.dnum == u.uz.dnum
1693 /* within same branch, or else main dungeon <-> gehennom */
1694 || (u.uz.dnum == valley_level.dnum
1695 && dlev.dnum == medusa_level.dnum)
1696 || (u.uz.dnum == medusa_level.dnum
1697 && dlev.dnum == valley_level.dnum))
1698 && (/* either wizard mode or else seen and not forgotten */
1700 || (level_info[idx].flags & (FORGOTTEN | VISITED))
1704 } else { /* not a specific level; try branch names */
1705 idx = find_branch(nam, (struct proto_dungeon *) 0);
1706 /* "<branch> to Xyzzy" */
1707 if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1708 idx = find_branch(p + 4, (struct proto_dungeon *) 0);
1711 idxtoo = (idx >> 8) & 0x00FF;
1713 if (/* either wizard mode, or else _both_ sides of branch seen */
1715 || ((level_info[idx].flags & (FORGOTTEN | VISITED)) == VISITED
1716 && (level_info[idxtoo].flags & (FORGOTTEN | VISITED))
1718 if (ledger_to_dnum(idxtoo) == u.uz.dnum)
1720 dlev.dnum = ledger_to_dnum(idx);
1721 dlev.dlevel = ledger_to_dlev(idx);
1730 unplaced_floater(dptr)
1731 struct dungeon *dptr;
1734 int idx = (int) (dptr - dungeons);
1736 /* if other floating branches are added, this will need to change */
1737 if (idx != knox_level.dnum)
1739 for (br = branches; br; br = br->next)
1740 if (br->end1.dnum == n_dgns && br->end2.dnum == idx)
1746 unreachable_level(lvl_p, unplaced)
1754 if (In_endgame(&u.uz) && !In_endgame(lvl_p))
1756 if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
1762 tport_menu(win, entry, lchoices, lvl_p, unreachable)
1765 struct lchoice *lchoices;
1767 boolean unreachable;
1772 lchoices->lev[lchoices->idx] = lvl_p->dlevel;
1773 lchoices->dgn[lchoices->idx] = lvl_p->dnum;
1774 lchoices->playerlev[lchoices->idx] = depth(lvl_p);
1777 /* not selectable, but still consumes next menuletter;
1778 prepend padding in place of missing menu selector */
1779 Sprintf(tmpbuf, " %s", entry);
1782 any.a_int = lchoices->idx + 1;
1784 add_menu(win, NO_GLYPH, &any, lchoices->menuletter, 0, ATR_NONE, entry,
1786 /* this assumes there are at most 52 interesting levels */
1787 if (lchoices->menuletter == 'z')
1788 lchoices->menuletter = 'A';
1790 lchoices->menuletter++;
1795 /* Convert a branch type to a string usable by print_dungeon(). */
1796 STATIC_OVL const char *
1805 return "
\96\82\96@
\82Ì
\93ü
\82è
\8cû";
1808 return "Connection";
1810 return "
\90Ú
\91±
\95\94";
1813 return "One way stair";
1815 return "
\88ê
\95û
\92Ê
\8ds
\82Ì
\8aK
\92i";
1823 return " (unknown)";
1825 return " (
\95s
\96¾)";
1832 return u.uz.dnum == dlev->dnum && u.uz.dlevel == dlev->dlevel ? '*' : ' ';
1835 /* Print all child branches between the lower and upper bounds. */
1837 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
1843 struct lchoice *lchoices_p;
1848 /* This assumes that end1 is the "parent". */
1849 for (br = branches; br; br = br->next) {
1850 if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
1851 && br->end1.dlevel <= upper_bound) {
1853 Sprintf(buf, "%c %s to %s: %d",
1854 bymenu ? chr_u_on_lvl(&br->end1) : ' ',
1855 br_string(br->type),
1856 dungeons[br->end2.dnum].dname, depth(&br->end1));
1858 Sprintf(buf, "%c %s
\82©
\82ç%s: %d",
1859 bymenu ? chr_u_on_lvl(&br->end1) : ' ',
1860 br_string(br->type),
1861 dungeons[br->end2.dnum].dname, depth(&br->end1));
1864 tport_menu(win, buf, lchoices_p, &br->end1,
1865 unreachable_level(&br->end1, FALSE));
1867 putstr(win, 0, buf);
1872 /* Print available dungeon information. */
1874 print_dungeon(bymenu, rlev, rdgn)
1879 int i, last_level, nlev;
1882 boolean first, unplaced;
1887 struct lchoice lchoices;
1888 winid win = create_nhwindow(NHW_MENU);
1893 lchoices.menuletter = 'a';
1896 for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1897 if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum)
1899 unplaced = unplaced_floater(dptr);
1901 descr = unplaced ? "depth" : "level";
1903 descr = unplaced ? "
\92n
\89º" : "
\83\8c\83x
\83\8b";
1904 nlev = dptr->num_dunlevs;
1907 Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
1908 dptr->depth_start, dptr->depth_start + nlev - 1);
1910 Sprintf(buf, "%s: %s%d
\82©
\82ç%d", dptr->dname, descr,
1911 dptr->depth_start, dptr->depth_start + nlev - 1);
1914 Sprintf(buf, "%s: %s %d", dptr->dname, descr, dptr->depth_start);
1916 /* Most entrances are uninteresting. */
1917 if (dptr->entry_lev != 1) {
1918 if (dptr->entry_lev == nlev)
1920 Strcat(buf, ", entrance from below");
1922 Strcat(buf, ",
\89º
\82©
\82ç
\82Ì
\93ü
\82è
\8cû");
1925 Sprintf(eos(buf), ", entrance on %d",
1926 dptr->depth_start + dptr->entry_lev - 1);
1928 Sprintf(eos(buf), ", %d
\82Ì
\93ü
\82è
\8cû",
1929 dptr->depth_start + dptr->entry_lev - 1);
1934 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
1937 putstr(win, 0, buf);
1940 * Circle through the special levels to find levels that are in
1943 for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1944 if (slev->dlevel.dnum != i)
1947 /* print any branches before this level */
1948 print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
1951 Sprintf(buf, "%c %s: %d",
1952 chr_u_on_lvl(&slev->dlevel),
1953 slev->proto, depth(&slev->dlevel));
1954 if (Is_stronghold(&slev->dlevel))
1955 Sprintf(eos(buf), " (tune %s)", tune);
1957 tport_menu(win, buf, &lchoices, &slev->dlevel,
1958 unreachable_level(&slev->dlevel, unplaced));
1960 putstr(win, 0, buf);
1962 last_level = slev->dlevel.dlevel;
1964 /* print branches after the last special level */
1965 print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1970 menu_item *selected;
1974 end_menu(win, "Level teleport to where:");
1976 end_menu(win, "
\82Ç
\82±
\82É
\8fu
\8aÔ
\88Ú
\93®
\82·
\82é
\81F");
1977 n = select_menu(win, PICK_ONE, &selected);
1978 destroy_nhwindow(win);
1980 idx = selected[0].item.a_int - 1;
1981 free((genericptr_t) selected);
1983 *rlev = lchoices.lev[idx];
1984 *rdgn = lchoices.dgn[idx];
1985 return lchoices.playerlev[idx];
1991 /* Print out floating branches (if any). */
1992 for (first = TRUE, br = branches; br; br = br->next) {
1993 if (br->end1.dnum == n_dgns) {
1997 putstr(win, 0, "Floating branches");
1999 putstr(win, 0, "
\95\82\93®
\95ª
\8aò");
2003 Sprintf(buf, " %s to %s", br_string(br->type),
2004 dungeons[br->end2.dnum].dname);
2006 Sprintf(buf, " %s
\82©
\82ç%s", br_string(br->type),
2007 dungeons[br->end2.dnum].dname);
2009 putstr(win, 0, buf);
2013 /* I hate searching for the invocation pos while debugging. -dean */
2014 if (Invocation_lev(&u.uz)) {
2017 Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
2018 inv_pos.x, inv_pos.y, u.ux, u.uy);
2020 Sprintf(buf, "
\94
\93®
\88Ê
\92u @ (%d,%d),
\83v
\83\8c\83C
\83\84\81[ @ (%d,%d)",
2021 inv_pos.x, inv_pos.y, u.ux, u.uy);
2023 putstr(win, 0, buf);
2027 /* if current level has a magic portal, report its location;
2028 this assumes that there is at most one magic portal on any
2029 given level; quest and ft.ludios have pairs (one in main
2030 dungeon matched with one in the corresponding branch), the
2031 elemental planes have singletons (connection to next plane) */
2033 for (trap = ftrap; trap; trap = trap->ntrap)
2034 if (trap->ttyp == MAGIC_PORTAL)
2038 Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)",
2039 trap->tx, trap->ty, u.ux, u.uy);
2041 /* only report "no portal found" when actually expecting a portal */
2042 else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
2043 || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)
2044 || Is_qstart(&u.uz) || at_dgn_entrance("The Quest")
2046 Strcpy(buf, "No portal found.");
2048 /* only give output if we found a portal or expected one and didn't */
2051 putstr(win, 0, buf);
2055 display_nhwindow(win, TRUE);
2056 destroy_nhwindow(win);
2060 /* Record that the player knows about a branch from a level. This function
2061 * will determine whether or not it was a "real" branch that was taken.
2062 * This function should not be called for a transition done via level
2063 * teleport or via the Eye.
2066 recbranch_mapseen(source, dest)
2074 if (source->dnum == dest->dnum)
2077 /* we only care about forward branches */
2078 for (br = branches; br; br = br->next) {
2079 if (on_level(source, &br->end1) && on_level(dest, &br->end2))
2081 if (on_level(source, &br->end2) && on_level(dest, &br->end1))
2085 /* branch not found, so not a real branch. */
2089 if ((mptr = find_mapseen(source)) != 0) {
2090 if (mptr->br && br != mptr->br)
2091 impossible("Two branches on the same level?");
2094 impossible("Can't note branch for unseen level (%d, %d)",
2095 source->dnum, source->dlevel);
2105 if ((mptr = find_mapseen(lev)))
2106 return mptr->custom;
2110 /* #annotate command - add a custom name to the current level */
2115 char nbuf[BUFSZ]; /* Buffer for response */
2117 if (!(mptr = find_mapseen(&u.uz)))
2123 (void) strncpy(nbuf, mptr->custom, BUFSZ);
2124 nbuf[BUFSZ - 1] = '\0';
2131 Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
2132 (strlen(mptr->custom) > 30) ? "..." : "");
2134 Sprintf(tmpbuf, "
\8c»
\8dÝ
\82Ì
\83\81\83\82\81u%.30s%s
\81v
\82ð
\89½
\82É
\8f\91\82«
\8a·
\82¦
\82é
\81H", mptr->custom,
2135 strlen(mptr->custom) > 30 ? "..." : "");
2137 getlin(tmpbuf, nbuf);
2141 getlin("What do you want to call this dungeon level?", nbuf);
2143 getlin("
\82±
\82Ì
\8aK
\82ð
\89½
\82Æ
\8cÄ
\82Ô
\81H", nbuf);
2145 /* empty input or ESC means don't add or change annotation;
2146 space-only means discard current annotation without adding new one */
2147 if (!*nbuf || *nbuf == '\033')
2149 /* strip leading and trailing spaces, compress out consecutive spaces */
2150 (void) mungspaces(nbuf);
2152 /* discard old annotation, if any */
2154 free((genericptr_t) mptr->custom);
2155 mptr->custom = (char *) 0;
2156 mptr->custom_lth = 0;
2158 /* add new annotation, unless it's all spaces (which will be an
2159 empty string after mungspaces() above) */
2160 if (*nbuf && strcmp(nbuf, " ")) {
2161 mptr->custom = dupstr(nbuf);
2162 mptr->custom_lth = strlen(mptr->custom);
2167 /* find the particular mapseen object in the chain; may return null */
2168 STATIC_OVL mapseen *
2174 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2175 if (on_level(&(mptr->lev), lev))
2181 STATIC_OVL mapseen *
2182 find_mapseen_by_str(s)
2187 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2188 if (mptr->custom && !strcmpi(s, mptr->custom))
2196 forget_mapseen(ledger_num)
2200 struct cemetery *bp;
2202 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2203 if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
2207 /* if not found, then nothing to forget */
2209 mptr->flags.forgot = 1;
2210 mptr->br = (branch *) 0;
2212 /* custom names are erased, not just forgotten until revisited */
2214 mptr->custom_lth = 0;
2215 free((genericptr_t) mptr->custom);
2216 mptr->custom = (char *) 0;
2218 (void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
2219 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2220 bp->bonesknown = FALSE;
2225 rm_mapseen(ledger_num)
2228 mapseen *mptr, *mprev = (mapseen *)0;
2229 struct cemetery *bp, *bpnext;
2231 for (mptr = mapseenchn; mptr; mprev = mptr, mptr = mptr->next)
2232 if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel == ledger_num)
2239 free((genericptr_t) mptr->custom);
2241 bp = mptr->final_resting_place;
2249 mprev->next = mptr->next;
2252 mapseenchn = mptr->next;
2258 save_mapseen(fd, mptr)
2265 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2266 if (curr == mptr->br)
2268 bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
2270 bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
2271 bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
2272 bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
2273 bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
2274 if (mptr->custom_lth)
2275 bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
2276 bwrite(fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
2277 savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
2280 STATIC_OVL mapseen *
2284 int branchnum, brindx;
2288 load = (mapseen *) alloc(sizeof *load);
2290 mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
2291 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2292 if (brindx == branchnum)
2296 mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
2297 mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
2298 mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
2299 mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
2300 if (load->custom_lth) {
2301 /* length doesn't include terminator (which isn't saved & restored) */
2302 load->custom = (char *) alloc(load->custom_lth + 1);
2303 mread(fd, (genericptr_t) load->custom, load->custom_lth);
2304 load->custom[load->custom_lth] = '\0';
2307 mread(fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
2308 restcemetery(fd, &load->final_resting_place);
2313 /* to support '#stats' wizard-mode command */
2315 overview_stats(win, statsfmt, total_count, total_size)
2317 const char *statsfmt;
2318 long *total_count, *total_size;
2320 char buf[BUFSZ], hdrbuf[QBUFSZ];
2321 long ocount, osize, bcount, bsize, acount, asize;
2322 struct cemetery *ce;
2323 mapseen *mptr = find_mapseen(&u.uz);
2325 ocount = bcount = acount = osize = bsize = asize = 0L;
2326 for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2328 osize += (long) sizeof *mptr;
2329 for (ce = mptr->final_resting_place; ce; ce = ce->next) {
2331 bsize += (long) sizeof *ce;
2333 if (mptr->custom_lth) {
2335 asize += (long) (mptr->custom_lth + 1);
2339 Sprintf(hdrbuf, "general, size %ld", (long) sizeof (mapseen));
2340 Sprintf(buf, statsfmt, hdrbuf, ocount, osize);
2341 putstr(win, 0, buf);
2343 Sprintf(hdrbuf, "cemetery, size %ld",
2344 (long) sizeof (struct cemetery));
2345 Sprintf(buf, statsfmt, hdrbuf, bcount, bsize);
2346 putstr(win, 0, buf);
2349 Sprintf(hdrbuf, "annotations, text");
2350 Sprintf(buf, statsfmt, hdrbuf, acount, asize);
2351 putstr(win, 0, buf);
2353 *total_count += ocount + bcount + acount;
2354 *total_size += osize + bsize + asize;
2357 /* Remove all mapseen objects for a particular dnum.
2358 * Useful during quest expulsion to remove quest levels.
2359 * [No longer deleted, just marked as unreachable. #overview will
2360 * ignore such levels, end of game disclosure will include them.]
2363 remdun_mapseen(dnum)
2366 mapseen *mptr, **mptraddr;
2368 mptraddr = &mapseenchn;
2369 while ((mptr = *mptraddr) != 0) {
2370 if (mptr->lev.dnum == dnum) {
2371 #if 1 /* use this... */
2372 mptr->flags.unreachable = 1;
2374 #else /* old deletion code */
2375 *mptraddr = mptr->next;
2377 free((genericptr_t) mptr->custom);
2378 if (mptr->final_resting_place)
2379 savecemetery(-1, FREE_SAVE, &mptr->final_resting_place);
2380 free((genericptr_t) mptr);
2383 mptraddr = &mptr->next;
2391 /* Create a level and insert in "sorted" order. This is an insertion
2392 * sort first by dungeon (in order of discovery) and then by level number.
2394 mapseen *mptr, *init, *prev;
2396 init = (mapseen *) alloc(sizeof *init);
2397 (void) memset((genericptr_t) init, 0, sizeof *init);
2398 /* memset is fine for feature bits, flags, and rooms array;
2399 explicitly initialize pointers to null */
2400 init->next = 0, init->br = 0, init->custom = 0;
2401 init->final_resting_place = 0;
2402 /* lastseentyp[][] is reused for each level, so get rid of
2403 previous level's data */
2404 (void) memset((genericptr_t) lastseentyp, 0, sizeof lastseentyp);
2406 init->lev.dnum = lev->dnum;
2407 init->lev.dlevel = lev->dlevel;
2409 /* walk until we get to the place where we should insert init */
2410 for (mptr = mapseenchn, prev = 0; mptr; prev = mptr, mptr = mptr->next)
2411 if (mptr->lev.dnum > init->lev.dnum
2412 || (mptr->lev.dnum == init->lev.dnum
2413 && mptr->lev.dlevel > init->lev.dlevel))
2416 init->next = mapseenchn;
2425 #define INTEREST(feat) \
2426 ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2427 || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2428 /* || (feat).water || (feat).ice || (feat).lava */
2430 /* returns true if this level has something interesting to print out */
2432 interest_mapseen(mptr)
2435 if (on_level(&u.uz, &mptr->lev))
2437 if (mptr->flags.unreachable || mptr->flags.forgot)
2439 /* level is of interest if it has an auto-generated annotation */
2440 if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
2441 || mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
2442 || mptr->flags.quest_summons || mptr->flags.questing)
2444 /* when in Sokoban, list all sokoban levels visited; when not in it,
2445 list any visited Sokoban level which remains unsolved (will usually
2446 only be furthest one reached, but it's possible to enter pits and
2447 climb out on the far side on the first Sokoban level; also, wizard
2448 mode overrides teleport restrictions) */
2449 if (In_sokoban(&mptr->lev)
2450 && (In_sokoban(&u.uz) || !mptr->flags.sokosolved))
2452 /* when in the endgame, list all endgame levels visited, whether they
2453 have annotations or not, so that #overview doesn't become extremely
2454 sparse once the rest of the dungeon has been flagged as unreachable */
2455 if (In_endgame(&u.uz))
2456 return (boolean) In_endgame(&mptr->lev);
2457 /* level is of interest if it has non-zero feature count or known bones
2458 or user annotation or known connection to another dungeon branch
2459 or is the furthest level reached in its branch */
2460 return (boolean) (INTEREST(mptr->feat)
2461 || (mptr->final_resting_place
2462 && (mptr->flags.knownbones || wizard))
2463 || mptr->custom || mptr->br
2464 || (mptr->lev.dlevel
2465 == dungeons[mptr->lev.dnum].dunlev_ureached));
2468 /* recalculate mapseen for the current level */
2474 struct cemetery *bp, **bonesaddr;
2476 int x, y, ltyp, count, atmp;
2478 /* Should not happen in general, but possible if in the process
2479 * of being booted from the quest. The mapseen object gets
2480 * removed during the expulsion but prior to leaving the level
2481 * [Since quest expulsion no longer deletes quest mapseen data,
2482 * null return from find_mapseen() should now be impossible.]
2484 if (!(mptr = find_mapseen(&u.uz)))
2487 /* reset all features; mptr->feat.* = 0; */
2488 (void) memset((genericptr_t) &mptr->feat, 0, sizeof mptr->feat);
2489 /* reset most flags; some level-specific ones are left as-is */
2490 if (mptr->flags.unreachable) {
2491 mptr->flags.unreachable = 0; /* reached it; Eye of the Aethiopica? */
2492 if (In_quest(&u.uz)) {
2493 mapseen *mptrtmp = mapseenchn;
2495 /* when quest was unreachable due to ejection and portal removal,
2496 getting back to it via arti-invoke should revive annotation
2497 data for all quest levels, not just the one we're on now */
2499 if (mptrtmp->lev.dnum == mptr->lev.dnum)
2500 mptrtmp->flags.unreachable = 0;
2501 mptrtmp = mptrtmp->next;
2505 mptr->flags.knownbones = 0;
2506 mptr->flags.sokosolved = In_sokoban(&u.uz) && !Sokoban;
2507 /* mptr->flags.bigroom retains previous value when hero can't see */
2509 mptr->flags.bigroom = Is_bigroom(&u.uz);
2510 else if (mptr->flags.forgot)
2511 mptr->flags.bigroom = 0;
2512 mptr->flags.roguelevel = Is_rogue_level(&u.uz);
2513 mptr->flags.oracle = 0; /* recalculated during room traversal below */
2514 mptr->flags.castletune = 0;
2515 /* flags.castle, flags.valley, flags.msanctum retain previous value */
2516 mptr->flags.forgot = 0;
2517 /* flags.quest_summons disabled once quest finished */
2519 mptr->flags.quest_summons = (at_dgn_entrance("The Quest")
2521 mptr->flags.quest_summons = (at_dgn_entrance("
\83N
\83G
\83X
\83g")
2523 && !(u.uevent.qcompleted
2524 || u.uevent.qexpelled
2525 || quest_status.leader_is_dead));
2526 mptr->flags.questing = (on_level(&u.uz, &qstart_level)
2527 && quest_status.got_quest);
2529 /* track rooms the hero is in */
2530 for (i = 0; i < SIZE(u.urooms); ++i) {
2534 ridx = u.urooms[i] - ROOMOFFSET;
2535 mptr->msrooms[ridx].seen = 1;
2536 mptr->msrooms[ridx].untended =
2537 (rooms[ridx].rtype >= SHOPBASE)
2538 ? (!(mtmp = shop_keeper(u.urooms[i])) || !inhishop(mtmp))
2539 : (rooms[ridx].rtype == TEMPLE)
2540 ? (!(mtmp = findpriest(u.urooms[i]))
2541 || !inhistemple(mtmp))
2545 /* recalculate room knowledge: for now, just shops and temples
2546 * this could be extended to an array of 0..SHOPBASE
2548 for (i = 0; i < SIZE(mptr->msrooms); ++i) {
2549 if (mptr->msrooms[i].seen) {
2550 if (rooms[i].rtype >= SHOPBASE) {
2551 if (mptr->msrooms[i].untended)
2552 mptr->feat.shoptype = SHOPBASE - 1;
2553 else if (!mptr->feat.nshop)
2554 mptr->feat.shoptype = rooms[i].rtype;
2555 else if (mptr->feat.shoptype != (unsigned) rooms[i].rtype)
2556 mptr->feat.shoptype = 0;
2557 count = mptr->feat.nshop + 1;
2559 mptr->feat.nshop = count;
2560 } else if (rooms[i].rtype == TEMPLE) {
2561 /* altar and temple alignment handled below */
2562 count = mptr->feat.ntemple + 1;
2564 mptr->feat.ntemple = count;
2565 } else if (rooms[i].orig_rtype == DELPHI) {
2566 mptr->flags.oracle = 1;
2571 /* Update lastseentyp with typ if and only if it is in sight or the
2572 * hero can feel it on their current location (i.e. not levitating).
2573 * This *should* give the "last known typ" for each dungeon location.
2574 * (At the very least, it's a better assumption than determining what
2575 * the player knows from the glyph and the typ (which is isn't quite
2576 * enough information in some cases)).
2578 * It was reluctantly added to struct rm to track. Alternatively
2579 * we could track "features" and then update them all here, and keep
2580 * track of when new features are created or destroyed, but this
2581 * seemed the most elegant, despite adding more data to struct rm.
2582 * [3.6.0: we're using lastseentyp[][] rather than level.locations
2583 * to track the features seen.]
2585 * Although no current windowing systems (can) do this, this would add
2586 * the ability to have non-dungeon glyphs float above the last known
2587 * dungeon glyph (i.e. items on fountains).
2589 for (x = 1; x < COLNO; x++) {
2590 for (y = 0; y < ROWNO; y++) {
2591 if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
2592 ltyp = levl[x][y].typ;
2593 if (ltyp == DRAWBRIDGE_UP)
2594 ltyp = db_under_typ(levl[x][y].drawbridgemask);
2595 if ((mtmp = m_at(x, y)) != 0
2596 && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
2597 ltyp = cmap_to_type(mtmp->mappearance);
2598 lastseentyp[x][y] = ltyp;
2601 switch (lastseentyp[x][y]) {
2604 count = mptr->feat.ice + 1;
2606 mptr->feat.ice = count;
2611 count = mptr->feat.water + 1;
2613 mptr->feat.water = count;
2616 count = mptr->feat.lava + 1;
2618 mptr->feat.lava = count;
2622 count = mptr->feat.ntree + 1;
2624 mptr->feat.ntree = count;
2627 count = mptr->feat.nfount + 1;
2629 mptr->feat.nfount = count;
2632 count = mptr->feat.nthrone + 1;
2634 mptr->feat.nthrone = count;
2637 count = mptr->feat.nsink + 1;
2639 mptr->feat.nsink = count;
2642 count = mptr->feat.ngrave + 1;
2644 mptr->feat.ngrave = count;
2647 atmp = (Is_astralevel(&u.uz)
2648 && (levl[x][y].seenv & SVALL) != SVALL)
2650 : Amask2msa(levl[x][y].altarmask);
2651 if (!mptr->feat.naltar)
2652 mptr->feat.msalign = atmp;
2653 else if (mptr->feat.msalign != atmp)
2654 mptr->feat.msalign = MSA_NONE;
2655 count = mptr->feat.naltar + 1;
2657 mptr->feat.naltar = count;
2659 /* An automatic annotation is added to the Castle and
2660 * to Fort Ludios once their structure's main entrance
2661 * has been seen (in person or via magic mapping).
2662 * For the Fort, that entrance is just a secret door
2663 * which will be converted into a regular one when
2664 * located (or destroyed).
2665 * DOOR: possibly a lowered drawbridge's open portcullis;
2666 * DBWALL: a raised drawbridge's "closed door";
2667 * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2668 * with moat or other terrain hidden underneath;
2669 * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2670 * not recognizable as a bridge location unless/until
2671 * the adjacent DBWALL has been seen.
2674 if (Is_knox(&u.uz)) {
2677 /* Throne is four columns left, either directly in
2678 * line or one row higher or lower, and doesn't have
2679 * to have been seen yet.
2684 * For 3.6.0 and earlier, it was always in direct line:
2685 * both throne and door on the lower of the two rows.
2687 for (ty = y - 1; ty <= y + 1; ++ty)
2688 if (isok(tx, ty) && IS_THRONE(levl[tx][ty].typ)) {
2689 mptr->flags.ludios = 1;
2694 if (is_drawbridge_wall(x, y) < 0)
2698 case DRAWBRIDGE_DOWN:
2699 if (Is_stronghold(&u.uz))
2700 mptr->flags.castle = 1, mptr->flags.castletune = 1;
2708 if (level.bonesinfo && !mptr->final_resting_place) {
2709 /* clone the bonesinfo so we aren't dependent upon this
2710 level being in memory */
2711 bonesaddr = &mptr->final_resting_place;
2712 bp = level.bonesinfo;
2714 *bonesaddr = (struct cemetery *) alloc(sizeof **bonesaddr);
2717 bonesaddr = &(*bonesaddr)->next;
2721 /* decide which past hero deaths have become known; there's no
2722 guarantee of either a grave or a ghost, so we go by whether the
2723 current hero has seen the map location where each old one died */
2724 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2725 if (lastseentyp[bp->frpx][bp->frpy]) {
2726 bp->bonesknown = TRUE;
2727 mptr->flags.knownbones = 1;
2732 /* valley and sanctum levels get automatic annotation once temple is entered
2735 mapseen_temple(priest)
2736 struct monst *priest UNUSED; /* currently unused; might be useful someday */
2738 mapseen *mptr = find_mapseen(&u.uz);
2740 if (Is_valley(&u.uz))
2741 mptr->flags.valley = 1;
2742 else if (Is_sanctum(&u.uz))
2743 mptr->flags.msanctum = 1;
2746 /* room entry message has just been delivered so learn room even if blind */
2748 room_discovered(roomno)
2751 mapseen *mptr = find_mapseen(&u.uz);
2753 mptr->msrooms[roomno].seen = 1;
2756 /* #overview command */
2760 show_overview(0, 0);
2764 /* called for #overview or for end of game disclosure */
2766 show_overview(why, reason)
2767 int why; /* 0 => #overview command,
2768 1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2769 int reason; /* how hero died; used when disclosing end-of-game level */
2774 /* lazy initialization */
2775 (void) recalc_mapseen();
2777 win = create_nhwindow(NHW_MENU);
2778 /* show the endgame levels before the rest of the dungeon,
2779 so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2780 if (In_endgame(&u.uz))
2781 traverse_mapseenchn(TRUE, win, why, reason, &lastdun);
2782 /* if game is over or we're not in the endgame yet, show the dungeon */
2783 if (why > 0 || !In_endgame(&u.uz))
2784 traverse_mapseenchn(FALSE, win, why, reason, &lastdun);
2785 display_nhwindow(win, TRUE);
2786 destroy_nhwindow(win);
2789 /* display endgame levels or non-endgame levels, not both */
2791 traverse_mapseenchn(viewendgame, win, why, reason, lastdun_p)
2792 boolean viewendgame;
2794 int why, reason, *lastdun_p;
2799 for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2800 if (viewendgame ^ In_endgame(&mptr->lev))
2803 /* only print out info for a level or a dungeon if interest */
2804 if (why > 0 || interest_mapseen(mptr)) {
2805 showheader = (boolean) (mptr->lev.dnum != *lastdun_p);
2806 print_mapseen(win, mptr, why, reason, showheader);
2807 *lastdun_p = mptr->lev.dnum;
2812 STATIC_OVL const char *
2817 /* players are computer scientists: 0, 1, 2, n */
2820 /*JP:
\82±
\82±
\82É
\82Í
\97\88\82È
\82¢
\82Í
\82¸*/
2822 /* an() returns too much. index is ok in this case */
2825 return index(vowels, *obj) ? "an" : "a";
2832 return "
\93ñ
\82Â
\82Ì";
2837 return "
\91½
\82
\82Ì";
2843 /* better br_string */
2844 STATIC_OVL const char *
2848 /* Special case: quest portal says closed if kicked from quest */
2849 boolean closed_portal = (br->end2.dnum == quest_dnum
2850 && u.uevent.qexpelled);
2855 return closed_portal ? "Sealed portal" : "Portal";
2857 return closed_portal ? "
\95\95\88ó
\82³
\82ê
\82½
\96\82\96@
\82Ì
\93ü
\8cû" : "
\96\82\96@
\82Ì
\93ü
\8cû";
2859 return "Connection";
2862 return br->end1_up ? "One way stairs up" : "One way stairs down";
2864 return br->end1_up ? "
\8fã
\82è
\95Ð
\93¹
\8aK
\92i" : "
\89º
\82è
\95Ð
\93¹
\8aK
\92i";
2867 return br->end1_up ? "Stairs up" : "Stairs down";
2869 return br->end1_up ? "
\8fã
\82è
\8aK
\92i" : "
\89º
\82è
\8aK
\92i";
2875 /* get the name of an endgame level; topten.c does something similar */
2876 STATIC_OVL const char *
2877 endgamelevelname(outbuf, indx)
2881 const char *planename = 0;
2887 Strcpy(outbuf, "Astral Plane");
2889 Strcpy(outbuf, "
\93V
\8fã
\8aE");
2893 planename = "Water";
2895 planename = "
\90\85";
2907 planename = "
\95\97";
2911 planename = "Earth";
2918 Sprintf(outbuf, "Plane of %s", planename);
2920 Sprintf(outbuf, "%s
\82Ì
\90¸
\97ì
\8aE", planename);
2922 Sprintf(outbuf, "unknown plane #%d", indx);
2926 STATIC_OVL const char *
2931 const char *str = "shop"; /* catchall */
2933 const char *str = "
\93X"; /* catchall */
2936 /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2940 str = "untended shop";
2942 str = "
\95ú
\8aü
\82³
\82ê
\82½
\93X";
2943 break; /* see recalc_mapseen */
2946 str = "general store";
2948 str = "
\8eG
\89Ý
\93X";
2954 str = "
\96h
\8bï
\93X";
2958 str = "scroll shop";
2960 str = "
\8aª
\95¨
\93X";
2964 str = "potion shop";
2970 str = "weapon shop";
2972 str = "
\95\90\8aí
\93X";
2976 str = "delicatessen";
2978 str = "
\90H
\97¿
\95i
\93X";
2984 str = "
\95ó
\90Î
\93X";
3000 str = "health food store";
3002 str = "
\8c\92\8dN
\90H
\95i
\93X";
3006 str = "lighting shop";
3008 str = "
\8fÆ
\96¾
\93X";
3016 /* if player knows about the mastermind tune, append it to Castle annotation;
3017 if drawbridge has been destroyed, flags.castletune will be zero */
3019 tunesuffix(mptr, outbuf)
3024 if (mptr->flags.castletune && u.uevent.uheard_tune) {
3027 if (u.uevent.uheard_tune == 2)
3028 Sprintf(tmp, "notes \"%s\"", tune);
3030 Strcpy(tmp, "5-note tune");
3031 Sprintf(outbuf, " (play %s to open or close drawbridge)", tmp);
3036 /* some utility macros for print_mapseen */
3037 #define TAB " " /* three spaces */
3039 #define BULLET "" /* empty; otherwise output becomes cluttered */
3040 #define PREFIX TAB TAB BULLET
3042 /* K&R: don't require support for concatenation of adjacent string literals */
3043 #define PREFIX " " /* two TABs + empty BULLET: six spaces */
3045 #define COMMA (i++ > 0 ? ", " : PREFIX)
3046 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
3048 #define ADDNTOBUF(nam, var) \
3051 Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
3052 (nam), plur(var)); \
3055 #define ADDNTOBUF(nam, var) \
3058 Sprintf(eos(buf), "%s%s%s", COMMA, seen_string((var), (nam)), \
3062 #define ADDTOBUF(nam, var) \
3065 Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
3069 print_mapseen(win, mptr, final, how, printdun)
3072 int final; /* 0: not final; 1: game over, alive; 2: game over, dead */
3073 int how; /* cause of death; only used if final==2 and mptr->lev==u.uz */
3076 char buf[BUFSZ], tmpbuf[BUFSZ];
3077 int i, depthstart, dnum;
3078 boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
3080 /* Damnable special cases */
3081 /* The quest and knox should appear to be level 1 to match
3084 dnum = mptr->lev.dnum;
3085 if (dnum == quest_dnum || dnum == knox_level.dnum)
3088 depthstart = dungeons[dnum].depth_start;
3091 if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
3092 /* suppress the negative numbers in the endgame */
3093 || In_endgame(&mptr->lev))
3094 Sprintf(buf, "%s:", dungeons[dnum].dname);
3095 else if (builds_up(&mptr->lev))
3097 Sprintf(buf, "%s: levels %d up to %d",
3099 Sprintf(buf, "%s: %d
\8aK
\82©
\82ç%d
\8aK",
3100 dungeons[dnum].dname,
3101 depthstart + dungeons[dnum].entry_lev - 1,
3102 depthstart + dungeons[dnum].dunlev_ureached - 1);
3105 Sprintf(buf, "%s: levels %d to %d",
3107 Sprintf(buf, "%s: %d
\8aK
\82©
\82ç%d
\8aK",
3108 dungeons[dnum].dname, depthstart,
3109 depthstart + dungeons[dnum].dunlev_ureached - 1);
3110 putstr(win, !final ? ATR_INVERSE : 0, buf);
3113 /* calculate level number */
3114 i = depthstart + mptr->lev.dlevel - 1;
3115 if (In_endgame(&mptr->lev))
3116 Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
3119 Sprintf(buf, "%sLevel %d:", TAB, i);
3121 Sprintf(buf, "%s%d
\8aK:", TAB, i);
3123 /* wizmode prints out proto dungeon names for clarity */
3127 if ((slev = Is_special(&mptr->lev)) != 0)
3128 Sprintf(eos(buf), " [%s]", slev->proto);
3130 /* [perhaps print custom annotation on its own line when it's long] */
3132 Sprintf(eos(buf), " \"%s\"", mptr->custom);
3133 if (on_level(&u.uz, &mptr->lev))
3135 Sprintf(eos(buf), " <- You %s here.",
3136 (!final || (final == 1 && how == ASCENDED)) ? "are"
3137 : (final == 1 && how == ESCAPED) ? "left from"
3140 Sprintf(eos(buf), " <-
\82±
\82±%s
\81D",
3141 (!final || (final == 1 && how == ASCENDED)) ? "
\82É
\82¢
\82é"
3142 : (final == 1 && how == ESCAPED) ? "
\82©
\82ç
\94²
\82¯
\82½"
3145 putstr(win, !final ? ATR_BOLD : 0, buf);
3147 if (mptr->flags.forgot)
3150 if (INTEREST(mptr->feat)) {
3153 i = 0; /* interest counter */
3154 /* List interests in an order vaguely corresponding to
3155 * how important they are.
3157 if (mptr->feat.nshop > 0) {
3158 if (mptr->feat.nshop > 1)
3160 ADDNTOBUF("shop", mptr->feat.nshop);
3162 ADDNTOBUF("
\93X", mptr->feat.nshop);
3164 Sprintf(eos(buf), "%s%s", COMMA,
3165 an(shop_string(mptr->feat.shoptype)));
3167 if (mptr->feat.naltar > 0) {
3168 /* Temples + non-temple altars get munged into just "altars" */
3169 if (mptr->feat.ntemple != mptr->feat.naltar)
3171 ADDNTOBUF("altar", mptr->feat.naltar);
3173 ADDNTOBUF("
\8dÕ
\92d", mptr->feat.naltar);
3176 ADDNTOBUF("temple", mptr->feat.ntemple);
3178 ADDNTOBUF("
\8e\9b\89@", mptr->feat.ntemple);
3180 /* only print out altar's god if they are all to your god */
3181 if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
3183 Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
3185 Sprintf(eos(buf), "(%s)", align_gname(u.ualign.type));
3188 ADDNTOBUF("throne", mptr->feat.nthrone);
3190 ADDNTOBUF("
\8bÊ
\8dÀ", mptr->feat.nthrone);
3192 ADDNTOBUF("fountain", mptr->feat.nfount);
3194 ADDNTOBUF("
\90ò", mptr->feat.nfount);
3196 ADDNTOBUF("sink", mptr->feat.nsink);
3198 ADDNTOBUF("
\97¬
\82µ
\91ä", mptr->feat.nsink);
3200 ADDNTOBUF("grave", mptr->feat.ngrave);
3202 ADDNTOBUF("
\95æ", mptr->feat.ngrave);
3204 ADDNTOBUF("tree", mptr->feat.ntree);
3206 ADDNTOBUF("
\96Ø", mptr->feat.ntree);
3208 ADDTOBUF("water", mptr->feat.water);
3209 ADDTOBUF("lava", mptr->feat.lava);
3210 ADDTOBUF("ice", mptr->feat.ice);
3212 /* capitalize afterwards */
3214 buf[i] = highc(buf[i]);
3215 /* capitalizing it makes it a sentence; terminate with '.' */
3217 putstr(win, 0, buf);
3220 /* we assume that these are mutually exclusive */
3222 if (mptr->flags.oracle) {
3224 Sprintf(buf, "%sOracle of Delphi.", PREFIX);
3226 Sprintf(buf, "%s
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\93a
\81D", PREFIX);
3227 } else if (In_sokoban(&mptr->lev)) {
3229 Sprintf(buf, "%s%s.", PREFIX,
3230 mptr->flags.sokosolved ? "Solved" : "Unsolved");
3232 Sprintf(buf, "%s%s.", PREFIX,
3233 mptr->flags.sokosolved ? "
\83N
\83\8a\83A
\8dÏ" : "
\96¢
\83N
\83\8a\83A");
3235 } else if (mptr->flags.bigroom) {
3237 Sprintf(buf, "%sA very big room.", PREFIX);
3239 Sprintf(buf, "%s
\82Æ
\82Ä
\82à
\91å
\82«
\82¢
\95\94\89®
\81D", PREFIX);
3240 } else if (mptr->flags.roguelevel) {
3242 Sprintf(buf, "%sA primitive area.", PREFIX);
3244 Sprintf(buf, "%s
\92P
\8f\83\82È
\95\94\89®
\81D", PREFIX);
3245 } else if (on_level(&mptr->lev, &qstart_level)) {
3247 Sprintf(buf, "%sHome%s.", PREFIX,
3248 mptr->flags.unreachable ? " (no way back...)" : "");
3250 Sprintf(buf, "%s
\8cÌ
\8b½%s
\81D", PREFIX,
3251 mptr->flags.unreachable ? "(
\96ß
\82ê
\82È
\82¢
\81D
\81D
\81D)" : "");
3253 if (u.uevent.qcompleted)
3255 Sprintf(buf, "%sCompleted quest for %s.", PREFIX, ldrname());
3257 Sprintf(buf, "%s%s
\82Ì
\82½
\82ß
\82É
\83N
\83G
\83X
\83g
\82ð
\8a®
\90\8b\82µ
\82½
\81D", PREFIX, ldrname());
3258 else if (mptr->flags.questing)
3260 Sprintf(buf, "%sGiven quest by %s.", PREFIX, ldrname());
3262 Sprintf(buf, "%s%s
\82©
\82ç
\83N
\83G
\83X
\83g
\82ð
\97^
\82¦
\82ç
\82ê
\82½
\81D", PREFIX, ldrname());
3263 } else if (mptr->flags.ludios) {
3264 /* presence of the ludios branch in #overview output indicates that
3265 the player has made it onto the level; presence of this annotation
3266 indicates that the fort's entrance has been seen (or mapped) */
3268 Sprintf(buf, "%sFort Ludios.", PREFIX);
3270 Sprintf(buf, "%s
\83\8d\81[
\83f
\83B
\83I
\83X
\8dÔ
\81D", PREFIX);
3271 } else if (mptr->flags.castle) {
3273 Sprintf(buf, "%sThe castle%s.", PREFIX, tunesuffix(mptr, tmpbuf));
3275 Sprintf(buf, "%s
\8fé%s
\81D", PREFIX, tunesuffix(mptr, tmpbuf));
3276 } else if (mptr->flags.valley) {
3278 Sprintf(buf, "%sValley of the Dead.", PREFIX);
3280 Sprintf(buf, "%s
\8e\80\82Ì
\92J
\81D", PREFIX);
3281 } else if (mptr->flags.msanctum) {
3283 Sprintf(buf, "%sMoloch's Sanctum.", PREFIX);
3285 Sprintf(buf, "%s
\83\82\81[
\83\8d\83b
\83N
\82Ì
\90¹
\88æ
\81D", PREFIX);
3288 putstr(win, 0, buf);
3289 /* quest entrance is not mutually-exclusive with bigroom or rogue level */
3290 if (mptr->flags.quest_summons) {
3292 Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
3294 Sprintf(buf, "%s%s
\82©
\82ç
\8cÄ
\82Ñ
\8fo
\82³
\82ê
\82½
\81D", PREFIX, ldrname());
3295 putstr(win, 0, buf);
3298 /* print out branches */
3301 Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br),
3302 dungeons[mptr->br->end2.dnum].dname);
3304 Sprintf(buf, "%s%s
\82Ö
\82Ì%s", PREFIX, dungeons[mptr->br->end2.dnum].dname,
3305 br_string2(mptr->br));
3308 /* Since mapseen objects are printed out in increasing order
3309 * of dlevel, clarify which level this branch is going to
3310 * if the branch goes upwards. Unless it's the end game.
3312 if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
3314 Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
3316 Sprintf(eos(buf), ", %d
\8aK", depth(&(mptr->br->end2)));
3318 putstr(win, 0, buf);
3321 /* maybe print out bones details */
3322 if (mptr->final_resting_place || final) {
3323 struct cemetery *bp;
3324 int kncnt = !died_here ? 0 : 1;
3326 for (bp = mptr->final_resting_place; bp; bp = bp->next)
3327 if (bp->bonesknown || wizard || final)
3331 Sprintf(buf, "%s%s", PREFIX, "Final resting place for");
3333 Sprintf(buf, "%s%s", PREFIX, "
\8dÅ
\8aú
\82Ì
\92n:");
3334 putstr(win, 0, buf);
3336 /* disclosure occurs before bones creation, so listing dead
3337 hero here doesn't give away whether bones are produced */
3338 formatkiller(tmpbuf, sizeof tmpbuf, how, TRUE);
3340 /* rephrase a few death reasons to work with "you" */
3341 (void) strsubst(tmpbuf, " himself", " yourself");
3342 (void) strsubst(tmpbuf, " herself", " yourself");
3343 (void) strsubst(tmpbuf, " his ", " your ");
3344 (void) strsubst(tmpbuf, " her ", " your ");
3347 Sprintf(buf, "%s%syou, %s%c", PREFIX, TAB, tmpbuf,
3348 --kncnt ? ',' : '.');
3350 Sprintf(buf, "%s%s %s%c", PREFIX, TAB, tmpbuf,
3351 --kncnt ? ',' : '.');
3353 putstr(win, 0, buf);
3355 for (bp = mptr->final_resting_place; bp; bp = bp->next) {
3356 if (bp->bonesknown || wizard || final) {
3357 Sprintf(buf, "%s%s%s, %s%c", PREFIX, TAB, bp->who,
3358 bp->how, --kncnt ? ',' : '.');
3359 putstr(win, 0, buf);