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 /* allow strings like "the oracle level" to find "oracle" */
1669 if (!strncmpi(nam, "the ", 4))
1671 if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
1672 nam = strcpy(buf, nam);
1673 *(eos(buf) - 6) = '\0';
1675 /* hell is the old name, and wouldn't match; gehennom would match its
1676 branch, yielding the castle level instead of the valley of the dead */
1677 if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1678 if (In_V_tower(&u.uz))
1679 nam = " to Vlad's tower"; /* branch to... */
1684 if ((slev = find_level(nam)) != 0)
1685 dlev = slev->dlevel;
1688 if (mseen || slev) {
1689 idx = ledger_no(&dlev);
1690 if ((dlev.dnum == u.uz.dnum
1691 /* within same branch, or else main dungeon <-> gehennom */
1692 || (u.uz.dnum == valley_level.dnum
1693 && dlev.dnum == medusa_level.dnum)
1694 || (u.uz.dnum == medusa_level.dnum
1695 && dlev.dnum == valley_level.dnum))
1696 && (/* either wizard mode or else seen and not forgotten */
1698 || (level_info[idx].flags & (FORGOTTEN | VISITED))
1702 } else { /* not a specific level; try branch names */
1703 idx = find_branch(nam, (struct proto_dungeon *) 0);
1704 /* "<branch> to Xyzzy" */
1705 if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1706 idx = find_branch(p + 4, (struct proto_dungeon *) 0);
1709 idxtoo = (idx >> 8) & 0x00FF;
1711 if (/* either wizard mode, or else _both_ sides of branch seen */
1713 || ((level_info[idx].flags & (FORGOTTEN | VISITED)) == VISITED
1714 && (level_info[idxtoo].flags & (FORGOTTEN | VISITED))
1716 if (ledger_to_dnum(idxtoo) == u.uz.dnum)
1718 dlev.dnum = ledger_to_dnum(idx);
1719 dlev.dlevel = ledger_to_dlev(idx);
1728 unplaced_floater(dptr)
1729 struct dungeon *dptr;
1732 int idx = (int) (dptr - dungeons);
1734 /* if other floating branches are added, this will need to change */
1735 if (idx != knox_level.dnum)
1737 for (br = branches; br; br = br->next)
1738 if (br->end1.dnum == n_dgns && br->end2.dnum == idx)
1744 unreachable_level(lvl_p, unplaced)
1752 if (In_endgame(&u.uz) && !In_endgame(lvl_p))
1754 if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
1760 tport_menu(win, entry, lchoices, lvl_p, unreachable)
1763 struct lchoice *lchoices;
1765 boolean unreachable;
1770 lchoices->lev[lchoices->idx] = lvl_p->dlevel;
1771 lchoices->dgn[lchoices->idx] = lvl_p->dnum;
1772 lchoices->playerlev[lchoices->idx] = depth(lvl_p);
1775 /* not selectable, but still consumes next menuletter;
1776 prepend padding in place of missing menu selector */
1777 Sprintf(tmpbuf, " %s", entry);
1780 any.a_int = lchoices->idx + 1;
1782 add_menu(win, NO_GLYPH, &any, lchoices->menuletter, 0, ATR_NONE, entry,
1784 /* this assumes there are at most 52 interesting levels */
1785 if (lchoices->menuletter == 'z')
1786 lchoices->menuletter = 'A';
1788 lchoices->menuletter++;
1793 /* Convert a branch type to a string usable by print_dungeon(). */
1794 STATIC_OVL const char *
1803 return "Connection";
1805 return "
\90Ú
\91±
\95\94";
1807 return "One way stair";
1811 return " (unknown)";
1818 return u.uz.dnum == dlev->dnum && u.uz.dlevel == dlev->dlevel ? '*' : ' ';
1821 /* Print all child branches between the lower and upper bounds. */
1823 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
1829 struct lchoice *lchoices_p;
1834 /* This assumes that end1 is the "parent". */
1835 for (br = branches; br; br = br->next) {
1836 if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
1837 && br->end1.dlevel <= upper_bound) {
1838 Sprintf(buf, "%c %s to %s: %d",
1839 bymenu ? chr_u_on_lvl(&br->end1) : ' ',
1840 br_string(br->type),
1841 dungeons[br->end2.dnum].dname, depth(&br->end1));
1843 tport_menu(win, buf, lchoices_p, &br->end1,
1844 unreachable_level(&br->end1, FALSE));
1846 putstr(win, 0, buf);
1851 /* Print available dungeon information. */
1853 print_dungeon(bymenu, rlev, rdgn)
1858 int i, last_level, nlev;
1861 boolean first, unplaced;
1866 struct lchoice lchoices;
1867 winid win = create_nhwindow(NHW_MENU);
1872 lchoices.menuletter = 'a';
1875 for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1876 if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum)
1878 unplaced = unplaced_floater(dptr);
1879 descr = unplaced ? "depth" : "level";
1880 nlev = dptr->num_dunlevs;
1882 Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
1883 dptr->depth_start, dptr->depth_start + nlev - 1);
1885 Sprintf(buf, "%s: %s %d", dptr->dname, descr, dptr->depth_start);
1887 /* Most entrances are uninteresting. */
1888 if (dptr->entry_lev != 1) {
1889 if (dptr->entry_lev == nlev)
1890 Strcat(buf, ", entrance from below");
1892 Sprintf(eos(buf), ", entrance on %d",
1893 dptr->depth_start + dptr->entry_lev - 1);
1897 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
1900 putstr(win, 0, buf);
1903 * Circle through the special levels to find levels that are in
1906 for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1907 if (slev->dlevel.dnum != i)
1910 /* print any branches before this level */
1911 print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
1914 Sprintf(buf, "%c %s: %d",
1915 chr_u_on_lvl(&slev->dlevel),
1916 slev->proto, depth(&slev->dlevel));
1917 if (Is_stronghold(&slev->dlevel))
1918 Sprintf(eos(buf), " (tune %s)", tune);
1920 tport_menu(win, buf, &lchoices, &slev->dlevel,
1921 unreachable_level(&slev->dlevel, unplaced));
1923 putstr(win, 0, buf);
1925 last_level = slev->dlevel.dlevel;
1927 /* print branches after the last special level */
1928 print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1933 menu_item *selected;
1936 end_menu(win, "Level teleport to where:");
1937 n = select_menu(win, PICK_ONE, &selected);
1938 destroy_nhwindow(win);
1940 idx = selected[0].item.a_int - 1;
1941 free((genericptr_t) selected);
1943 *rlev = lchoices.lev[idx];
1944 *rdgn = lchoices.dgn[idx];
1945 return lchoices.playerlev[idx];
1951 /* Print out floating branches (if any). */
1952 for (first = TRUE, br = branches; br; br = br->next) {
1953 if (br->end1.dnum == n_dgns) {
1956 putstr(win, 0, "Floating branches");
1959 Sprintf(buf, " %s to %s", br_string(br->type),
1960 dungeons[br->end2.dnum].dname);
1961 putstr(win, 0, buf);
1965 /* I hate searching for the invocation pos while debugging. -dean */
1966 if (Invocation_lev(&u.uz)) {
1968 Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1969 inv_pos.x, inv_pos.y, u.ux, u.uy);
1970 putstr(win, 0, buf);
1974 /* if current level has a magic portal, report its location;
1975 this assumes that there is at most one magic portal on any
1976 given level; quest and ft.ludios have pairs (one in main
1977 dungeon matched with one in the corresponding branch), the
1978 elemental planes have singletons (connection to next plane) */
1980 for (trap = ftrap; trap; trap = trap->ntrap)
1981 if (trap->ttyp == MAGIC_PORTAL)
1985 Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)",
1986 trap->tx, trap->ty, u.ux, u.uy);
1988 /* only report "no portal found" when actually expecting a portal */
1989 else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
1990 || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)
1991 || Is_qstart(&u.uz) || at_dgn_entrance("The Quest")
1993 Strcpy(buf, "No portal found.");
1995 /* only give output if we found a portal or expected one and didn't */
1998 putstr(win, 0, buf);
2002 display_nhwindow(win, TRUE);
2003 destroy_nhwindow(win);
2007 /* Record that the player knows about a branch from a level. This function
2008 * will determine whether or not it was a "real" branch that was taken.
2009 * This function should not be called for a transition done via level
2010 * teleport or via the Eye.
2013 recbranch_mapseen(source, dest)
2021 if (source->dnum == dest->dnum)
2024 /* we only care about forward branches */
2025 for (br = branches; br; br = br->next) {
2026 if (on_level(source, &br->end1) && on_level(dest, &br->end2))
2028 if (on_level(source, &br->end2) && on_level(dest, &br->end1))
2032 /* branch not found, so not a real branch. */
2036 if ((mptr = find_mapseen(source)) != 0) {
2037 if (mptr->br && br != mptr->br)
2038 impossible("Two branches on the same level?");
2041 impossible("Can't note branch for unseen level (%d, %d)",
2042 source->dnum, source->dlevel);
2052 if ((mptr = find_mapseen(lev)))
2053 return mptr->custom;
2057 /* #annotate command - add a custom name to the current level */
2062 char nbuf[BUFSZ]; /* Buffer for response */
2064 if (!(mptr = find_mapseen(&u.uz)))
2070 (void) strncpy(nbuf, mptr->custom, BUFSZ);
2071 nbuf[BUFSZ - 1] = '\0';
2078 Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
2079 (strlen(mptr->custom) > 30) ? "..." : "");
2081 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,
2082 strlen(mptr->custom) > 30 ? "..." : "");
2084 getlin(tmpbuf, nbuf);
2088 getlin("What do you want to call this dungeon level?", nbuf);
2090 getlin("
\82±
\82Ì
\8aK
\82ð
\89½
\82Æ
\8cÄ
\82Ô
\81H", nbuf);
2092 /* empty input or ESC means don't add or change annotation;
2093 space-only means discard current annotation without adding new one */
2094 if (!*nbuf || *nbuf == '\033')
2096 /* strip leading and trailing spaces, compress out consecutive spaces */
2097 (void) mungspaces(nbuf);
2099 /* discard old annotation, if any */
2101 free((genericptr_t) mptr->custom);
2102 mptr->custom = (char *) 0;
2103 mptr->custom_lth = 0;
2105 /* add new annotation, unless it's all spaces (which will be an
2106 empty string after mungspaces() above) */
2107 if (*nbuf && strcmp(nbuf, " ")) {
2108 mptr->custom = dupstr(nbuf);
2109 mptr->custom_lth = strlen(mptr->custom);
2114 /* find the particular mapseen object in the chain; may return null */
2115 STATIC_OVL mapseen *
2121 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2122 if (on_level(&(mptr->lev), lev))
2128 STATIC_OVL mapseen *
2129 find_mapseen_by_str(s)
2134 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2135 if (mptr->custom && !strcmpi(s, mptr->custom))
2143 forget_mapseen(ledger_num)
2147 struct cemetery *bp;
2149 for (mptr = mapseenchn; mptr; mptr = mptr->next)
2150 if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
2154 /* if not found, then nothing to forget */
2156 mptr->flags.forgot = 1;
2157 mptr->br = (branch *) 0;
2159 /* custom names are erased, not just forgotten until revisited */
2161 mptr->custom_lth = 0;
2162 free((genericptr_t) mptr->custom);
2163 mptr->custom = (char *) 0;
2165 (void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
2166 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2167 bp->bonesknown = FALSE;
2172 rm_mapseen(ledger_num)
2175 mapseen *mptr, *mprev = (mapseen *)0;
2176 struct cemetery *bp, *bpnext;
2178 for (mptr = mapseenchn; mptr; mprev = mptr, mptr = mptr->next)
2179 if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel == ledger_num)
2186 free((genericptr_t) mptr->custom);
2188 bp = mptr->final_resting_place;
2196 mprev->next = mptr->next;
2199 mapseenchn = mptr->next;
2205 save_mapseen(fd, mptr)
2212 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2213 if (curr == mptr->br)
2215 bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
2217 bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
2218 bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
2219 bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
2220 bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
2221 if (mptr->custom_lth)
2222 bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
2223 bwrite(fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
2224 savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
2227 STATIC_OVL mapseen *
2231 int branchnum, brindx;
2235 load = (mapseen *) alloc(sizeof *load);
2237 mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
2238 for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2239 if (brindx == branchnum)
2243 mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
2244 mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
2245 mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
2246 mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
2247 if (load->custom_lth) {
2248 /* length doesn't include terminator (which isn't saved & restored) */
2249 load->custom = (char *) alloc(load->custom_lth + 1);
2250 mread(fd, (genericptr_t) load->custom, load->custom_lth);
2251 load->custom[load->custom_lth] = '\0';
2254 mread(fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
2255 restcemetery(fd, &load->final_resting_place);
2260 /* to support '#stats' wizard-mode command */
2262 overview_stats(win, statsfmt, total_count, total_size)
2264 const char *statsfmt;
2265 long *total_count, *total_size;
2267 char buf[BUFSZ], hdrbuf[QBUFSZ];
2268 long ocount, osize, bcount, bsize, acount, asize;
2269 struct cemetery *ce;
2270 mapseen *mptr = find_mapseen(&u.uz);
2272 ocount = bcount = acount = osize = bsize = asize = 0L;
2273 for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2275 osize += (long) sizeof *mptr;
2276 for (ce = mptr->final_resting_place; ce; ce = ce->next) {
2278 bsize += (long) sizeof *ce;
2280 if (mptr->custom_lth) {
2282 asize += (long) (mptr->custom_lth + 1);
2286 Sprintf(hdrbuf, "general, size %ld", (long) sizeof (mapseen));
2287 Sprintf(buf, statsfmt, hdrbuf, ocount, osize);
2288 putstr(win, 0, buf);
2290 Sprintf(hdrbuf, "cemetery, size %ld",
2291 (long) sizeof (struct cemetery));
2292 Sprintf(buf, statsfmt, hdrbuf, bcount, bsize);
2293 putstr(win, 0, buf);
2296 Sprintf(hdrbuf, "annotations, text");
2297 Sprintf(buf, statsfmt, hdrbuf, acount, asize);
2298 putstr(win, 0, buf);
2300 *total_count += ocount + bcount + acount;
2301 *total_size += osize + bsize + asize;
2304 /* Remove all mapseen objects for a particular dnum.
2305 * Useful during quest expulsion to remove quest levels.
2306 * [No longer deleted, just marked as unreachable. #overview will
2307 * ignore such levels, end of game disclosure will include them.]
2310 remdun_mapseen(dnum)
2313 mapseen *mptr, **mptraddr;
2315 mptraddr = &mapseenchn;
2316 while ((mptr = *mptraddr) != 0) {
2317 if (mptr->lev.dnum == dnum) {
2318 #if 1 /* use this... */
2319 mptr->flags.unreachable = 1;
2321 #else /* old deletion code */
2322 *mptraddr = mptr->next;
2324 free((genericptr_t) mptr->custom);
2325 if (mptr->final_resting_place)
2326 savecemetery(-1, FREE_SAVE, &mptr->final_resting_place);
2327 free((genericptr_t) mptr);
2330 mptraddr = &mptr->next;
2338 /* Create a level and insert in "sorted" order. This is an insertion
2339 * sort first by dungeon (in order of discovery) and then by level number.
2341 mapseen *mptr, *init, *prev;
2343 init = (mapseen *) alloc(sizeof *init);
2344 (void) memset((genericptr_t) init, 0, sizeof *init);
2345 /* memset is fine for feature bits, flags, and rooms array;
2346 explicitly initialize pointers to null */
2347 init->next = 0, init->br = 0, init->custom = 0;
2348 init->final_resting_place = 0;
2349 /* lastseentyp[][] is reused for each level, so get rid of
2350 previous level's data */
2351 (void) memset((genericptr_t) lastseentyp, 0, sizeof lastseentyp);
2353 init->lev.dnum = lev->dnum;
2354 init->lev.dlevel = lev->dlevel;
2356 /* walk until we get to the place where we should insert init */
2357 for (mptr = mapseenchn, prev = 0; mptr; prev = mptr, mptr = mptr->next)
2358 if (mptr->lev.dnum > init->lev.dnum
2359 || (mptr->lev.dnum == init->lev.dnum
2360 && mptr->lev.dlevel > init->lev.dlevel))
2363 init->next = mapseenchn;
2372 #define INTEREST(feat) \
2373 ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2374 || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2375 /* || (feat).water || (feat).ice || (feat).lava */
2377 /* returns true if this level has something interesting to print out */
2379 interest_mapseen(mptr)
2382 if (on_level(&u.uz, &mptr->lev))
2384 if (mptr->flags.unreachable || mptr->flags.forgot)
2386 /* level is of interest if it has an auto-generated annotation */
2387 if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
2388 || mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
2389 || mptr->flags.quest_summons || mptr->flags.questing)
2391 /* when in Sokoban, list all sokoban levels visited; when not in it,
2392 list any visited Sokoban level which remains unsolved (will usually
2393 only be furthest one reached, but it's possible to enter pits and
2394 climb out on the far side on the first Sokoban level; also, wizard
2395 mode overrides teleport restrictions) */
2396 if (In_sokoban(&mptr->lev)
2397 && (In_sokoban(&u.uz) || !mptr->flags.sokosolved))
2399 /* when in the endgame, list all endgame levels visited, whether they
2400 have annotations or not, so that #overview doesn't become extremely
2401 sparse once the rest of the dungeon has been flagged as unreachable */
2402 if (In_endgame(&u.uz))
2403 return (boolean) In_endgame(&mptr->lev);
2404 /* level is of interest if it has non-zero feature count or known bones
2405 or user annotation or known connection to another dungeon branch
2406 or is the furthest level reached in its branch */
2407 return (boolean) (INTEREST(mptr->feat)
2408 || (mptr->final_resting_place
2409 && (mptr->flags.knownbones || wizard))
2410 || mptr->custom || mptr->br
2411 || (mptr->lev.dlevel
2412 == dungeons[mptr->lev.dnum].dunlev_ureached));
2415 /* recalculate mapseen for the current level */
2421 struct cemetery *bp, **bonesaddr;
2423 int x, y, ltyp, count, atmp;
2425 /* Should not happen in general, but possible if in the process
2426 * of being booted from the quest. The mapseen object gets
2427 * removed during the expulsion but prior to leaving the level
2428 * [Since quest expulsion no longer deletes quest mapseen data,
2429 * null return from find_mapseen() should now be impossible.]
2431 if (!(mptr = find_mapseen(&u.uz)))
2434 /* reset all features; mptr->feat.* = 0; */
2435 (void) memset((genericptr_t) &mptr->feat, 0, sizeof mptr->feat);
2436 /* reset most flags; some level-specific ones are left as-is */
2437 if (mptr->flags.unreachable) {
2438 mptr->flags.unreachable = 0; /* reached it; Eye of the Aethiopica? */
2439 if (In_quest(&u.uz)) {
2440 mapseen *mptrtmp = mapseenchn;
2442 /* when quest was unreachable due to ejection and portal removal,
2443 getting back to it via arti-invoke should revive annotation
2444 data for all quest levels, not just the one we're on now */
2446 if (mptrtmp->lev.dnum == mptr->lev.dnum)
2447 mptrtmp->flags.unreachable = 0;
2448 mptrtmp = mptrtmp->next;
2452 mptr->flags.knownbones = 0;
2453 mptr->flags.sokosolved = In_sokoban(&u.uz) && !Sokoban;
2454 /* mptr->flags.bigroom retains previous value when hero can't see */
2456 mptr->flags.bigroom = Is_bigroom(&u.uz);
2457 else if (mptr->flags.forgot)
2458 mptr->flags.bigroom = 0;
2459 mptr->flags.roguelevel = Is_rogue_level(&u.uz);
2460 mptr->flags.oracle = 0; /* recalculated during room traversal below */
2461 mptr->flags.castletune = 0;
2462 /* flags.castle, flags.valley, flags.msanctum retain previous value */
2463 mptr->flags.forgot = 0;
2464 /* flags.quest_summons disabled once quest finished */
2466 mptr->flags.quest_summons = (at_dgn_entrance("The Quest")
2468 mptr->flags.quest_summons = (at_dgn_entrance("
\83N
\83G
\83X
\83g")
2470 && !(u.uevent.qcompleted
2471 || u.uevent.qexpelled
2472 || quest_status.leader_is_dead));
2473 mptr->flags.questing = (on_level(&u.uz, &qstart_level)
2474 && quest_status.got_quest);
2476 /* track rooms the hero is in */
2477 for (i = 0; i < SIZE(u.urooms); ++i) {
2481 ridx = u.urooms[i] - ROOMOFFSET;
2482 mptr->msrooms[ridx].seen = 1;
2483 mptr->msrooms[ridx].untended =
2484 (rooms[ridx].rtype >= SHOPBASE)
2485 ? (!(mtmp = shop_keeper(u.urooms[i])) || !inhishop(mtmp))
2486 : (rooms[ridx].rtype == TEMPLE)
2487 ? (!(mtmp = findpriest(u.urooms[i]))
2488 || !inhistemple(mtmp))
2492 /* recalculate room knowledge: for now, just shops and temples
2493 * this could be extended to an array of 0..SHOPBASE
2495 for (i = 0; i < SIZE(mptr->msrooms); ++i) {
2496 if (mptr->msrooms[i].seen) {
2497 if (rooms[i].rtype >= SHOPBASE) {
2498 if (mptr->msrooms[i].untended)
2499 mptr->feat.shoptype = SHOPBASE - 1;
2500 else if (!mptr->feat.nshop)
2501 mptr->feat.shoptype = rooms[i].rtype;
2502 else if (mptr->feat.shoptype != (unsigned) rooms[i].rtype)
2503 mptr->feat.shoptype = 0;
2504 count = mptr->feat.nshop + 1;
2506 mptr->feat.nshop = count;
2507 } else if (rooms[i].rtype == TEMPLE) {
2508 /* altar and temple alignment handled below */
2509 count = mptr->feat.ntemple + 1;
2511 mptr->feat.ntemple = count;
2512 } else if (rooms[i].orig_rtype == DELPHI) {
2513 mptr->flags.oracle = 1;
2518 /* Update lastseentyp with typ if and only if it is in sight or the
2519 * hero can feel it on their current location (i.e. not levitating).
2520 * This *should* give the "last known typ" for each dungeon location.
2521 * (At the very least, it's a better assumption than determining what
2522 * the player knows from the glyph and the typ (which is isn't quite
2523 * enough information in some cases)).
2525 * It was reluctantly added to struct rm to track. Alternatively
2526 * we could track "features" and then update them all here, and keep
2527 * track of when new features are created or destroyed, but this
2528 * seemed the most elegant, despite adding more data to struct rm.
2529 * [3.6.0: we're using lastseentyp[][] rather than level.locations
2530 * to track the features seen.]
2532 * Although no current windowing systems (can) do this, this would add
2533 * the ability to have non-dungeon glyphs float above the last known
2534 * dungeon glyph (i.e. items on fountains).
2536 for (x = 1; x < COLNO; x++) {
2537 for (y = 0; y < ROWNO; y++) {
2538 if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
2539 ltyp = levl[x][y].typ;
2540 if (ltyp == DRAWBRIDGE_UP)
2541 ltyp = db_under_typ(levl[x][y].drawbridgemask);
2542 if ((mtmp = m_at(x, y)) != 0
2543 && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
2544 ltyp = cmap_to_type(mtmp->mappearance);
2545 lastseentyp[x][y] = ltyp;
2548 switch (lastseentyp[x][y]) {
2551 count = mptr->feat.ice + 1;
2553 mptr->feat.ice = count;
2558 count = mptr->feat.water + 1;
2560 mptr->feat.water = count;
2563 count = mptr->feat.lava + 1;
2565 mptr->feat.lava = count;
2569 count = mptr->feat.ntree + 1;
2571 mptr->feat.ntree = count;
2574 count = mptr->feat.nfount + 1;
2576 mptr->feat.nfount = count;
2579 count = mptr->feat.nthrone + 1;
2581 mptr->feat.nthrone = count;
2584 count = mptr->feat.nsink + 1;
2586 mptr->feat.nsink = count;
2589 count = mptr->feat.ngrave + 1;
2591 mptr->feat.ngrave = count;
2594 atmp = (Is_astralevel(&u.uz)
2595 && (levl[x][y].seenv & SVALL) != SVALL)
2597 : Amask2msa(levl[x][y].altarmask);
2598 if (!mptr->feat.naltar)
2599 mptr->feat.msalign = atmp;
2600 else if (mptr->feat.msalign != atmp)
2601 mptr->feat.msalign = MSA_NONE;
2602 count = mptr->feat.naltar + 1;
2604 mptr->feat.naltar = count;
2606 /* An automatic annotation is added to the Castle and
2607 * to Fort Ludios once their structure's main entrance
2608 * has been seen (in person or via magic mapping).
2609 * For the Fort, that entrance is just a secret door
2610 * which will be converted into a regular one when
2611 * located (or destroyed).
2612 * DOOR: possibly a lowered drawbridge's open portcullis;
2613 * DBWALL: a raised drawbridge's "closed door";
2614 * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2615 * with moat or other terrain hidden underneath;
2616 * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2617 * not recognizable as a bridge location unless/until
2618 * the adjacent DBWALL has been seen.
2621 if (Is_knox(&u.uz)) {
2624 /* Throne is four columns left, either directly in
2625 * line or one row higher or lower, and doesn't have
2626 * to have been seen yet.
2631 * For 3.6.0 and earlier, it was always in direct line:
2632 * both throne and door on the lower of the two rows.
2634 for (ty = y - 1; ty <= y + 1; ++ty)
2635 if (isok(tx, ty) && IS_THRONE(levl[tx][ty].typ)) {
2636 mptr->flags.ludios = 1;
2641 if (is_drawbridge_wall(x, y) < 0)
2645 case DRAWBRIDGE_DOWN:
2646 if (Is_stronghold(&u.uz))
2647 mptr->flags.castle = 1, mptr->flags.castletune = 1;
2655 if (level.bonesinfo && !mptr->final_resting_place) {
2656 /* clone the bonesinfo so we aren't dependent upon this
2657 level being in memory */
2658 bonesaddr = &mptr->final_resting_place;
2659 bp = level.bonesinfo;
2661 *bonesaddr = (struct cemetery *) alloc(sizeof **bonesaddr);
2664 bonesaddr = &(*bonesaddr)->next;
2668 /* decide which past hero deaths have become known; there's no
2669 guarantee of either a grave or a ghost, so we go by whether the
2670 current hero has seen the map location where each old one died */
2671 for (bp = mptr->final_resting_place; bp; bp = bp->next)
2672 if (lastseentyp[bp->frpx][bp->frpy]) {
2673 bp->bonesknown = TRUE;
2674 mptr->flags.knownbones = 1;
2679 /* valley and sanctum levels get automatic annotation once temple is entered
2682 mapseen_temple(priest)
2683 struct monst *priest UNUSED; /* currently unused; might be useful someday */
2685 mapseen *mptr = find_mapseen(&u.uz);
2687 if (Is_valley(&u.uz))
2688 mptr->flags.valley = 1;
2689 else if (Is_sanctum(&u.uz))
2690 mptr->flags.msanctum = 1;
2693 /* room entry message has just been delivered so learn room even if blind */
2695 room_discovered(roomno)
2698 mapseen *mptr = find_mapseen(&u.uz);
2700 mptr->msrooms[roomno].seen = 1;
2703 /* #overview command */
2707 show_overview(0, 0);
2711 /* called for #overview or for end of game disclosure */
2713 show_overview(why, reason)
2714 int why; /* 0 => #overview command,
2715 1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2716 int reason; /* how hero died; used when disclosing end-of-game level */
2721 /* lazy initialization */
2722 (void) recalc_mapseen();
2724 win = create_nhwindow(NHW_MENU);
2725 /* show the endgame levels before the rest of the dungeon,
2726 so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2727 if (In_endgame(&u.uz))
2728 traverse_mapseenchn(TRUE, win, why, reason, &lastdun);
2729 /* if game is over or we're not in the endgame yet, show the dungeon */
2730 if (why > 0 || !In_endgame(&u.uz))
2731 traverse_mapseenchn(FALSE, win, why, reason, &lastdun);
2732 display_nhwindow(win, TRUE);
2733 destroy_nhwindow(win);
2736 /* display endgame levels or non-endgame levels, not both */
2738 traverse_mapseenchn(viewendgame, win, why, reason, lastdun_p)
2739 boolean viewendgame;
2741 int why, reason, *lastdun_p;
2746 for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2747 if (viewendgame ^ In_endgame(&mptr->lev))
2750 /* only print out info for a level or a dungeon if interest */
2751 if (why > 0 || interest_mapseen(mptr)) {
2752 showheader = (boolean) (mptr->lev.dnum != *lastdun_p);
2753 print_mapseen(win, mptr, why, reason, showheader);
2754 *lastdun_p = mptr->lev.dnum;
2759 STATIC_OVL const char *
2764 /* players are computer scientists: 0, 1, 2, n */
2767 /*JP:
\82±
\82±
\82É
\82Í
\97\88\82È
\82¢
\82Í
\82¸*/
2769 /* an() returns too much. index is ok in this case */
2772 return index(vowels, *obj) ? "an" : "a";
2779 return "
\93ñ
\82Â
\82Ì";
2784 return "
\91½
\82
\82Ì";
2790 /* better br_string */
2791 STATIC_OVL const char *
2795 /* Special case: quest portal says closed if kicked from quest */
2796 boolean closed_portal = (br->end2.dnum == quest_dnum
2797 && u.uevent.qexpelled);
2802 return closed_portal ? "Sealed portal" : "Portal";
2804 return closed_portal ? "
\95\95\88ó
\82³
\82ê
\82½
\96\82\96@
\82Ì
\93ü
\8cû" : "
\96\82\96@
\82Ì
\93ü
\8cû";
2806 return "Connection";
2809 return br->end1_up ? "One way stairs up" : "One way stairs down";
2811 return br->end1_up ? "
\8fã
\82è
\95Ð
\93¹
\8aK
\92i" : "
\89º
\82è
\95Ð
\93¹
\8aK
\92i";
2814 return br->end1_up ? "Stairs up" : "Stairs down";
2816 return br->end1_up ? "
\8fã
\82è
\8aK
\92i" : "
\89º
\82è
\8aK
\92i";
2822 /* get the name of an endgame level; topten.c does something similar */
2823 STATIC_OVL const char *
2824 endgamelevelname(outbuf, indx)
2828 const char *planename = 0;
2834 Strcpy(outbuf, "Astral Plane");
2836 Strcpy(outbuf, "
\93V
\8fã
\8aE");
2840 planename = "Water";
2842 planename = "
\90\85";
2854 planename = "
\95\97";
2858 planename = "Earth";
2865 Sprintf(outbuf, "Plane of %s", planename);
2867 Sprintf(outbuf, "%s
\82Ì
\90¸
\97ì
\8aE", planename);
2869 Sprintf(outbuf, "unknown plane #%d", indx);
2873 STATIC_OVL const char *
2878 const char *str = "shop"; /* catchall */
2880 const char *str = "
\93X"; /* catchall */
2883 /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2887 str = "untended shop";
2889 str = "
\95ú
\8aü
\82³
\82ê
\82½
\93X";
2890 break; /* see recalc_mapseen */
2893 str = "general store";
2895 str = "
\8eG
\89Ý
\93X";
2901 str = "
\96h
\8bï
\93X";
2905 str = "scroll shop";
2907 str = "
\8aª
\95¨
\93X";
2911 str = "potion shop";
2917 str = "weapon shop";
2919 str = "
\95\90\8aí
\93X";
2923 str = "delicatessen";
2925 str = "
\90H
\97¿
\95i
\93X";
2931 str = "
\95ó
\90Î
\93X";
2947 str = "health food store";
2949 str = "
\8c\92\8dN
\90H
\95i
\93X";
2953 str = "lighting shop";
2955 str = "
\8fÆ
\96¾
\93X";
2963 /* if player knows about the mastermind tune, append it to Castle annotation;
2964 if drawbridge has been destroyed, flags.castletune will be zero */
2966 tunesuffix(mptr, outbuf)
2971 if (mptr->flags.castletune && u.uevent.uheard_tune) {
2974 if (u.uevent.uheard_tune == 2)
2975 Sprintf(tmp, "notes \"%s\"", tune);
2977 Strcpy(tmp, "5-note tune");
2978 Sprintf(outbuf, " (play %s to open or close drawbridge)", tmp);
2983 /* some utility macros for print_mapseen */
2984 #define TAB " " /* three spaces */
2986 #define BULLET "" /* empty; otherwise output becomes cluttered */
2987 #define PREFIX TAB TAB BULLET
2989 /* K&R: don't require support for concatenation of adjacent string literals */
2990 #define PREFIX " " /* two TABs + empty BULLET: six spaces */
2992 #define COMMA (i++ > 0 ? ", " : PREFIX)
2993 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2995 #define ADDNTOBUF(nam, var) \
2998 Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2999 (nam), plur(var)); \
3002 #define ADDNTOBUF(nam, var) \
3005 Sprintf(eos(buf), "%s%s%s", COMMA, seen_string((var), (nam)), \
3009 #define ADDTOBUF(nam, var) \
3012 Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
3016 print_mapseen(win, mptr, final, how, printdun)
3019 int final; /* 0: not final; 1: game over, alive; 2: game over, dead */
3020 int how; /* cause of death; only used if final==2 and mptr->lev==u.uz */
3023 char buf[BUFSZ], tmpbuf[BUFSZ];
3024 int i, depthstart, dnum;
3025 boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
3027 /* Damnable special cases */
3028 /* The quest and knox should appear to be level 1 to match
3031 dnum = mptr->lev.dnum;
3032 if (dnum == quest_dnum || dnum == knox_level.dnum)
3035 depthstart = dungeons[dnum].depth_start;
3038 if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
3039 /* suppress the negative numbers in the endgame */
3040 || In_endgame(&mptr->lev))
3041 Sprintf(buf, "%s:", dungeons[dnum].dname);
3042 else if (builds_up(&mptr->lev))
3044 Sprintf(buf, "%s: levels %d up to %d",
3046 Sprintf(buf, "%s: %d
\8aK
\82©
\82ç%d
\8aK",
3047 dungeons[dnum].dname,
3048 depthstart + dungeons[dnum].entry_lev - 1,
3049 depthstart + dungeons[dnum].dunlev_ureached - 1);
3052 Sprintf(buf, "%s: levels %d to %d",
3054 Sprintf(buf, "%s: %d
\8aK
\82©
\82ç%d
\8aK",
3055 dungeons[dnum].dname, depthstart,
3056 depthstart + dungeons[dnum].dunlev_ureached - 1);
3057 putstr(win, !final ? ATR_INVERSE : 0, buf);
3060 /* calculate level number */
3061 i = depthstart + mptr->lev.dlevel - 1;
3062 if (In_endgame(&mptr->lev))
3063 Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
3066 Sprintf(buf, "%sLevel %d:", TAB, i);
3068 Sprintf(buf, "%s%d
\8aK:", TAB, i);
3070 /* wizmode prints out proto dungeon names for clarity */
3074 if ((slev = Is_special(&mptr->lev)) != 0)
3075 Sprintf(eos(buf), " [%s]", slev->proto);
3077 /* [perhaps print custom annotation on its own line when it's long] */
3079 Sprintf(eos(buf), " \"%s\"", mptr->custom);
3080 if (on_level(&u.uz, &mptr->lev))
3082 Sprintf(eos(buf), " <- You %s here.",
3083 (!final || (final == 1 && how == ASCENDED)) ? "are"
3084 : (final == 1 && how == ESCAPED) ? "left from"
3087 Sprintf(eos(buf), " <-
\82±
\82±%s
\81D",
3088 (!final || (final == 1 && how == ASCENDED)) ? "
\82É
\82¢
\82é"
3089 : (final == 1 && how == ESCAPED) ? "
\82©
\82ç
\94²
\82¯
\82½"
3092 putstr(win, !final ? ATR_BOLD : 0, buf);
3094 if (mptr->flags.forgot)
3097 if (INTEREST(mptr->feat)) {
3100 i = 0; /* interest counter */
3101 /* List interests in an order vaguely corresponding to
3102 * how important they are.
3104 if (mptr->feat.nshop > 0) {
3105 if (mptr->feat.nshop > 1)
3107 ADDNTOBUF("shop", mptr->feat.nshop);
3109 ADDNTOBUF("
\93X", mptr->feat.nshop);
3111 Sprintf(eos(buf), "%s%s", COMMA,
3112 an(shop_string(mptr->feat.shoptype)));
3114 if (mptr->feat.naltar > 0) {
3115 /* Temples + non-temple altars get munged into just "altars" */
3116 if (mptr->feat.ntemple != mptr->feat.naltar)
3118 ADDNTOBUF("altar", mptr->feat.naltar);
3120 ADDNTOBUF("
\8dÕ
\92d", mptr->feat.naltar);
3123 ADDNTOBUF("temple", mptr->feat.ntemple);
3125 ADDNTOBUF("
\8e\9b\89@", mptr->feat.ntemple);
3127 /* only print out altar's god if they are all to your god */
3128 if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
3130 Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
3132 Sprintf(eos(buf), "(%s)", align_gname(u.ualign.type));
3135 ADDNTOBUF("throne", mptr->feat.nthrone);
3137 ADDNTOBUF("
\8bÊ
\8dÀ", mptr->feat.nthrone);
3139 ADDNTOBUF("fountain", mptr->feat.nfount);
3141 ADDNTOBUF("
\90ò", mptr->feat.nfount);
3143 ADDNTOBUF("sink", mptr->feat.nsink);
3145 ADDNTOBUF("
\97¬
\82µ
\91ä", mptr->feat.nsink);
3147 ADDNTOBUF("grave", mptr->feat.ngrave);
3149 ADDNTOBUF("
\95æ", mptr->feat.ngrave);
3151 ADDNTOBUF("tree", mptr->feat.ntree);
3153 ADDNTOBUF("
\96Ø", mptr->feat.ntree);
3155 ADDTOBUF("water", mptr->feat.water);
3156 ADDTOBUF("lava", mptr->feat.lava);
3157 ADDTOBUF("ice", mptr->feat.ice);
3159 /* capitalize afterwards */
3161 buf[i] = highc(buf[i]);
3162 /* capitalizing it makes it a sentence; terminate with '.' */
3164 putstr(win, 0, buf);
3167 /* we assume that these are mutually exclusive */
3169 if (mptr->flags.oracle) {
3171 Sprintf(buf, "%sOracle of Delphi.", PREFIX);
3173 Sprintf(buf, "%s
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\93a
\81D", PREFIX);
3174 } else if (In_sokoban(&mptr->lev)) {
3176 Sprintf(buf, "%s%s.", PREFIX,
3177 mptr->flags.sokosolved ? "Solved" : "Unsolved");
3179 Sprintf(buf, "%s%s.", PREFIX,
3180 mptr->flags.sokosolved ? "
\83N
\83\8a\83A
\8dÏ" : "
\96¢
\83N
\83\8a\83A");
3182 } else if (mptr->flags.bigroom) {
3184 Sprintf(buf, "%sA very big room.", PREFIX);
3186 Sprintf(buf, "%s
\82Æ
\82Ä
\82à
\91å
\82«
\82¢
\95\94\89®
\81D", PREFIX);
3187 } else if (mptr->flags.roguelevel) {
3189 Sprintf(buf, "%sA primitive area.", PREFIX);
3191 Sprintf(buf, "%s
\92P
\8f\83\82È
\95\94\89®
\81D", PREFIX);
3192 } else if (on_level(&mptr->lev, &qstart_level)) {
3194 Sprintf(buf, "%sHome%s.", PREFIX,
3195 mptr->flags.unreachable ? " (no way back...)" : "");
3197 Sprintf(buf, "%s
\8cÌ
\8b½%s
\81D", PREFIX,
3198 mptr->flags.unreachable ? "(
\96ß
\82ê
\82È
\82¢
\81D
\81D
\81D)" : "");
3200 if (u.uevent.qcompleted)
3202 Sprintf(buf, "%sCompleted quest for %s.", PREFIX, ldrname());
3204 Sprintf(buf, "%s%s
\82Ì
\82½
\82ß
\82É
\83N
\83G
\83X
\83g
\82ð
\8a®
\90\8b\82µ
\82½
\81D", PREFIX, ldrname());
3205 else if (mptr->flags.questing)
3207 Sprintf(buf, "%sGiven quest by %s.", PREFIX, ldrname());
3209 Sprintf(buf, "%s%s
\82©
\82ç
\83N
\83G
\83X
\83g
\82ð
\97^
\82¦
\82ç
\82ê
\82½
\81D", PREFIX, ldrname());
3210 } else if (mptr->flags.ludios) {
3211 /* presence of the ludios branch in #overview output indicates that
3212 the player has made it onto the level; presence of this annotation
3213 indicates that the fort's entrance has been seen (or mapped) */
3215 Sprintf(buf, "%sFort Ludios.", PREFIX);
3217 Sprintf(buf, "%s
\83\8d\81[
\83f
\83B
\83I
\83X
\8dÔ
\81D", PREFIX);
3218 } else if (mptr->flags.castle) {
3220 Sprintf(buf, "%sThe castle%s.", PREFIX, tunesuffix(mptr, tmpbuf));
3222 Sprintf(buf, "%s
\8fé%s
\81D", PREFIX, tunesuffix(mptr, tmpbuf));
3223 } else if (mptr->flags.valley) {
3225 Sprintf(buf, "%sValley of the Dead.", PREFIX);
3227 Sprintf(buf, "%s
\8e\80\82Ì
\92J
\81D", PREFIX);
3228 } else if (mptr->flags.msanctum) {
3230 Sprintf(buf, "%sMoloch's Sanctum.", PREFIX);
3232 Sprintf(buf, "%s
\83\82\81[
\83\8d\83b
\83N
\82Ì
\90¹
\88æ
\81D", PREFIX);
3235 putstr(win, 0, buf);
3236 /* quest entrance is not mutually-exclusive with bigroom or rogue level */
3237 if (mptr->flags.quest_summons) {
3239 Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
3241 Sprintf(buf, "%s%s
\82©
\82ç
\8cÄ
\82Ñ
\8fo
\82³
\82ê
\82½
\81D", PREFIX, ldrname());
3242 putstr(win, 0, buf);
3245 /* print out branches */
3248 Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br),
3249 dungeons[mptr->br->end2.dnum].dname);
3251 Sprintf(buf, "%s%s
\82Ö
\82Ì%s", PREFIX, dungeons[mptr->br->end2.dnum].dname,
3252 br_string2(mptr->br));
3255 /* Since mapseen objects are printed out in increasing order
3256 * of dlevel, clarify which level this branch is going to
3257 * if the branch goes upwards. Unless it's the end game.
3259 if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
3261 Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
3263 Sprintf(eos(buf), ", %d
\8aK", depth(&(mptr->br->end2)));
3265 putstr(win, 0, buf);
3268 /* maybe print out bones details */
3269 if (mptr->final_resting_place || final) {
3270 struct cemetery *bp;
3271 int kncnt = !died_here ? 0 : 1;
3273 for (bp = mptr->final_resting_place; bp; bp = bp->next)
3274 if (bp->bonesknown || wizard || final)
3278 Sprintf(buf, "%s%s", PREFIX, "Final resting place for");
3280 Sprintf(buf, "%s%s", PREFIX, "
\8dÅ
\8aú
\82Ì
\92n:");
3281 putstr(win, 0, buf);
3283 /* disclosure occurs before bones creation, so listing dead
3284 hero here doesn't give away whether bones are produced */
3285 formatkiller(tmpbuf, sizeof tmpbuf, how, TRUE);
3287 /* rephrase a few death reasons to work with "you" */
3288 (void) strsubst(tmpbuf, " himself", " yourself");
3289 (void) strsubst(tmpbuf, " herself", " yourself");
3290 (void) strsubst(tmpbuf, " his ", " your ");
3291 (void) strsubst(tmpbuf, " her ", " your ");
3294 Sprintf(buf, "%s%syou, %s%c", PREFIX, TAB, tmpbuf,
3295 --kncnt ? ',' : '.');
3297 Sprintf(buf, "%s%s %s%c", PREFIX, TAB, tmpbuf,
3298 --kncnt ? ',' : '.');
3300 putstr(win, 0, buf);
3302 for (bp = mptr->final_resting_place; bp; bp = bp->next) {
3303 if (bp->bonesknown || wizard || final) {
3304 Sprintf(buf, "%s%s%s, %s%c", PREFIX, TAB, bp->who,
3305 bp->how, --kncnt ? ',' : '.');
3306 putstr(win, 0, buf);