OSDN Git Service

patch src/
[jnethack/source.git] / src / dungeon.c
1 /* NetHack 3.6  dungeon.c       $NHDT-Date: 1448862377 2015/11/30 05:46:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.69 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6 #include "dgn_file.h"
7 #include "dlb.h"
8 #include "lev.h"
9
10 #define DUNGEON_FILE "dungeon"
11
12 #define X_START "x-strt"
13 #define X_LOCATE "x-loca"
14 #define X_GOAL "x-goal"
15
16 struct proto_dungeon {
17     struct tmpdungeon tmpdungeon[MAXDUNGEON];
18     struct tmplevel tmplevel[LEV_LIMIT];
19     s_level *final_lev[LEV_LIMIT]; /* corresponding level pointers */
20     struct tmpbranch tmpbranch[BRANCH_LIMIT];
21
22     int start;  /* starting index of current dungeon sp levels */
23     int n_levs; /* number of tmplevel entries */
24     int n_brs;  /* number of tmpbranch entries */
25 };
26
27 int n_dgns;     /* number of dungeons (also used in mklev.c and do.c) */
28 static branch *branches = (branch *) 0;        /* dungeon branch list */
29
30 mapseen *mapseenchn = (struct mapseen *) 0; /*DUNGEON_OVERVIEW*/
31
32 struct lchoice {
33     int idx;
34     schar lev[MAXLINFO];
35     schar playerlev[MAXLINFO];
36     xchar dgn[MAXLINFO];
37     char menuletter;
38 };
39
40 static void FDECL(Fread, (genericptr_t, int, int, dlb *));
41 STATIC_DCL xchar FDECL(dname_to_dnum, (const char *));
42 STATIC_DCL int FDECL(find_branch, (const char *, struct proto_dungeon *));
43 STATIC_DCL xchar FDECL(parent_dnum, (const char *, struct proto_dungeon *));
44 STATIC_DCL int FDECL(level_range, (XCHAR_P, int, int, int,
45                                    struct proto_dungeon *, int *));
46 STATIC_DCL xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *));
47 STATIC_DCL int FDECL(correct_branch_type, (struct tmpbranch *));
48 STATIC_DCL branch *FDECL(add_branch, (int, int, struct proto_dungeon *));
49 STATIC_DCL void FDECL(add_level, (s_level *));
50 STATIC_DCL void FDECL(init_level, (int, int, struct proto_dungeon *));
51 STATIC_DCL int FDECL(possible_places, (int, boolean *,
52                                        struct proto_dungeon *));
53 STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
54 STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
55 STATIC_DCL boolean FDECL(unplaced_floater, (struct dungeon *));
56 STATIC_DCL boolean FDECL(unreachable_level, (d_level *, BOOLEAN_P));
57 STATIC_DCL void FDECL(tport_menu, (winid, char *, struct lchoice *, d_level *,
58                                    BOOLEAN_P));
59 STATIC_DCL const char *FDECL(br_string, (int));
60 STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
61                                      struct lchoice *));
62 STATIC_DCL mapseen *FDECL(load_mapseen, (int));
63 STATIC_DCL void FDECL(save_mapseen, (int, mapseen *));
64 STATIC_DCL mapseen *FDECL(find_mapseen, (d_level *));
65 STATIC_DCL void FDECL(print_mapseen, (winid, mapseen *, int, int, BOOLEAN_P));
66 STATIC_DCL boolean FDECL(interest_mapseen, (mapseen *));
67 STATIC_DCL void FDECL(traverse_mapseenchn, (BOOLEAN_P, winid,
68                                             int, int, int *));
69 STATIC_DCL const char *FDECL(seen_string, (XCHAR_P, const char *));
70 STATIC_DCL const char *FDECL(br_string2, (branch *));
71 STATIC_DCL const char *FDECL(endgamelevelname, (char *, int));
72 STATIC_DCL const char *FDECL(shop_string, (int));
73 STATIC_DCL char *FDECL(tunesuffix, (mapseen *, char *));
74
75 #ifdef DEBUG
76 #define DD dungeons[i]
77 STATIC_DCL void NDECL(dumpit);
78
79 STATIC_OVL void
80 dumpit()
81 {
82     int i;
83     s_level *x;
84     branch *br;
85
86     if (!explicitdebug(__FILE__))
87         return;
88
89     for (i = 0; i < n_dgns; i++) {
90         fprintf(stderr, "\n#%d \"%s\" (%s):\n", i, DD.dname, DD.proto);
91         fprintf(stderr, "    num_dunlevs %d, dunlev_ureached %d\n",
92                 DD.num_dunlevs, DD.dunlev_ureached);
93         fprintf(stderr, "    depth_start %d, ledger_start %d\n",
94                 DD.depth_start, DD.ledger_start);
95         fprintf(stderr, "    flags:%s%s%s\n",
96                 DD.flags.rogue_like ? " rogue_like" : "",
97                 DD.flags.maze_like ? " maze_like" : "",
98                 DD.flags.hellish ? " hellish" : "");
99         getchar();
100     }
101     fprintf(stderr, "\nSpecial levels:\n");
102     for (x = sp_levchn; x; x = x->next) {
103         fprintf(stderr, "%s (%d): ", x->proto, x->rndlevs);
104         fprintf(stderr, "on %d, %d; ", x->dlevel.dnum, x->dlevel.dlevel);
105         fprintf(stderr, "flags:%s%s%s%s\n",
106                 x->flags.rogue_like ? " rogue_like" : "",
107                 x->flags.maze_like ? " maze_like" : "",
108                 x->flags.hellish ? " hellish" : "",
109                 x->flags.town ? " town" : "");
110         getchar();
111     }
112     fprintf(stderr, "\nBranches:\n");
113     for (br = branches; br; br = br->next) {
114         fprintf(stderr, "%d: %s, end1 %d %d, end2 %d %d, %s\n", br->id,
115                 br->type == BR_STAIR
116                     ? "stair"
117                     : br->type == BR_NO_END1
118                         ? "no end1"
119                         : br->type == BR_NO_END2
120                             ? "no end2"
121                             : br->type == BR_PORTAL
122                                 ? "portal"
123                                 : "unknown",
124                 br->end1.dnum, br->end1.dlevel, br->end2.dnum,
125                 br->end2.dlevel, br->end1_up ? "end1 up" : "end1 down");
126     }
127     getchar();
128     fprintf(stderr, "\nDone\n");
129     getchar();
130 }
131 #endif
132
133 /* Save the dungeon structures. */
134 void
135 save_dungeon(fd, perform_write, free_data)
136 int fd;
137 boolean perform_write, free_data;
138 {
139     branch *curr, *next;
140     mapseen *curr_ms, *next_ms;
141     int count;
142
143     if (perform_write) {
144         bwrite(fd, (genericptr_t) &n_dgns, sizeof n_dgns);
145         bwrite(fd, (genericptr_t) dungeons,
146                sizeof(dungeon) * (unsigned) n_dgns);
147         bwrite(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
148         bwrite(fd, (genericptr_t) tune, sizeof tune);
149
150         for (count = 0, curr = branches; curr; curr = curr->next)
151             count++;
152         bwrite(fd, (genericptr_t) &count, sizeof(count));
153
154         for (curr = branches; curr; curr = curr->next)
155             bwrite(fd, (genericptr_t) curr, sizeof(branch));
156
157         count = maxledgerno();
158         bwrite(fd, (genericptr_t) &count, sizeof count);
159         bwrite(fd, (genericptr_t) level_info,
160                (unsigned) count * sizeof(struct linfo));
161         bwrite(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
162
163         for (count = 0, curr_ms = mapseenchn; curr_ms;
164              curr_ms = curr_ms->next)
165             count++;
166         bwrite(fd, (genericptr_t) &count, sizeof(count));
167
168         for (curr_ms = mapseenchn; curr_ms; curr_ms = curr_ms->next)
169             save_mapseen(fd, curr_ms);
170     }
171
172     if (free_data) {
173         for (curr = branches; curr; curr = next) {
174             next = curr->next;
175             free((genericptr_t) curr);
176         }
177         branches = 0;
178         for (curr_ms = mapseenchn; curr_ms; curr_ms = next_ms) {
179             next_ms = curr_ms->next;
180             if (curr_ms->custom)
181                 free((genericptr_t) curr_ms->custom);
182             free((genericptr_t) curr_ms);
183         }
184         mapseenchn = 0;
185     }
186 }
187
188 /* Restore the dungeon structures. */
189 void
190 restore_dungeon(fd)
191 int fd;
192 {
193     branch *curr, *last;
194     int count, i;
195     mapseen *curr_ms, *last_ms;
196
197     mread(fd, (genericptr_t) &n_dgns, sizeof(n_dgns));
198     mread(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned) n_dgns);
199     mread(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
200     mread(fd, (genericptr_t) tune, sizeof tune);
201
202     last = branches = (branch *) 0;
203
204     mread(fd, (genericptr_t) &count, sizeof(count));
205     for (i = 0; i < count; i++) {
206         curr = (branch *) alloc(sizeof(branch));
207         mread(fd, (genericptr_t) curr, sizeof(branch));
208         curr->next = (branch *) 0;
209         if (last)
210             last->next = curr;
211         else
212             branches = curr;
213         last = curr;
214     }
215
216     mread(fd, (genericptr_t) &count, sizeof(count));
217     if (count >= MAXLINFO)
218         panic("level information count larger (%d) than allocated size",
219               count);
220     mread(fd, (genericptr_t) level_info,
221           (unsigned) count * sizeof(struct linfo));
222     mread(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
223
224     mread(fd, (genericptr_t) &count, sizeof(count));
225     last_ms = (mapseen *) 0;
226     for (i = 0; i < count; i++) {
227         curr_ms = load_mapseen(fd);
228         curr_ms->next = (mapseen *) 0;
229         if (last_ms)
230             last_ms->next = curr_ms;
231         else
232             mapseenchn = curr_ms;
233         last_ms = curr_ms;
234     }
235 }
236
237 static void
238 Fread(ptr, size, nitems, stream)
239 genericptr_t ptr;
240 int size, nitems;
241 dlb *stream;
242 {
243     int cnt;
244
245     if ((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) {
246         panic(
247   "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
248               (size * nitems), (size * cnt));
249         terminate(EXIT_FAILURE);
250     }
251 }
252
253 STATIC_OVL xchar
254 dname_to_dnum(s)
255 const char *s;
256 {
257     xchar i;
258
259     for (i = 0; i < n_dgns; i++)
260         if (!strcmp(dungeons[i].dname, s))
261             return i;
262
263     panic("Couldn't resolve dungeon number for name \"%s\".", s);
264     /*NOT REACHED*/
265     return (xchar) 0;
266 }
267
268 s_level *
269 find_level(s)
270 const char *s;
271 {
272     s_level *curr;
273     for (curr = sp_levchn; curr; curr = curr->next)
274         if (!strcmpi(s, curr->proto))
275             break;
276     return curr;
277 }
278
279 /* Find the branch that links the named dungeon. */
280 STATIC_OVL int
281 find_branch(s, pd)
282 const char *s; /* dungeon name */
283 struct proto_dungeon *pd;
284 {
285     int i;
286
287     if (pd) {
288         for (i = 0; i < pd->n_brs; i++)
289             if (!strcmp(pd->tmpbranch[i].name, s))
290                 break;
291         if (i == pd->n_brs)
292             panic("find_branch: can't find %s", s);
293     } else {
294         /* support for level tport by name */
295         branch *br;
296         const char *dnam;
297
298         for (br = branches; br; br = br->next) {
299             dnam = dungeons[br->end2.dnum].dname;
300             if (!strcmpi(dnam, s)
301                 || (!strncmpi(dnam, "The ", 4) && !strcmpi(dnam + 4, s)))
302                 break;
303         }
304         i = br ? ((ledger_no(&br->end1) << 8) | ledger_no(&br->end2)) : -1;
305     }
306     return i;
307 }
308
309 /*
310  * Find the "parent" by searching the prototype branch list for the branch
311  * listing, then figuring out to which dungeon it belongs.
312  */
313 STATIC_OVL xchar
314 parent_dnum(s, pd)
315 const char *s; /* dungeon name */
316 struct proto_dungeon *pd;
317 {
318     int i;
319     xchar pdnum;
320
321     i = find_branch(s, pd);
322     /*
323      * Got branch, now find parent dungeon.  Stop if we have reached
324      * "this" dungeon (if we haven't found it by now it is an error).
325      */
326     for (pdnum = 0; strcmp(pd->tmpdungeon[pdnum].name, s); pdnum++)
327         if ((i -= pd->tmpdungeon[pdnum].branches) < 0)
328             return pdnum;
329
330     panic("parent_dnum: couldn't resolve branch.");
331     /*NOT REACHED*/
332     return (xchar) 0;
333 }
334
335 /*
336  * Return a starting point and number of successive positions a level
337  * or dungeon entrance can occupy.
338  *
339  * Note: This follows the acouple (instead of the rcouple) rules for a
340  *       negative random component (randc < 0).  These rules are found
341  *       in dgn_comp.y.  The acouple [absolute couple] section says that
342  *       a negative random component means from the (adjusted) base to the
343  *       end of the dungeon.
344  */
345 STATIC_OVL int
346 level_range(dgn, base, randc, chain, pd, adjusted_base)
347 xchar dgn;
348 int base, randc, chain;
349 struct proto_dungeon *pd;
350 int *adjusted_base;
351 {
352     int lmax = dungeons[dgn].num_dunlevs;
353
354     if (chain >= 0) { /* relative to a special level */
355         s_level *levtmp = pd->final_lev[chain];
356         if (!levtmp)
357             panic("level_range: empty chain level!");
358
359         base += levtmp->dlevel.dlevel;
360     } else { /* absolute in the dungeon */
361         /* from end of dungeon */
362         if (base < 0)
363             base = (lmax + base + 1);
364     }
365
366     if (base < 1 || base > lmax)
367         panic("level_range: base value out of range");
368
369     *adjusted_base = base;
370
371     if (randc == -1) { /* from base to end of dungeon */
372         return (lmax - base + 1);
373     } else if (randc) {
374         /* make sure we don't run off the end of the dungeon */
375         return (((base + randc - 1) > lmax) ? lmax - base + 1 : randc);
376     } /* else only one choice */
377     return 1;
378 }
379
380 STATIC_OVL xchar
381 parent_dlevel(s, pd)
382 const char *s;
383 struct proto_dungeon *pd;
384 {
385     int i, j, num, base, dnum = parent_dnum(s, pd);
386     branch *curr;
387
388     i = find_branch(s, pd);
389     num = level_range(dnum, pd->tmpbranch[i].lev.base,
390                       pd->tmpbranch[i].lev.rand, pd->tmpbranch[i].chain, pd,
391                       &base);
392
393     /* KMH -- Try our best to find a level without an existing branch */
394     i = j = rn2(num);
395     do {
396         if (++i >= num)
397             i = 0;
398         for (curr = branches; curr; curr = curr->next)
399             if ((curr->end1.dnum == dnum && curr->end1.dlevel == base + i)
400                 || (curr->end2.dnum == dnum && curr->end2.dlevel == base + i))
401                 break;
402     } while (curr && i != j);
403     return (base + i);
404 }
405
406 /* Convert from the temporary branch type to the dungeon branch type. */
407 STATIC_OVL int
408 correct_branch_type(tbr)
409 struct tmpbranch *tbr;
410 {
411     switch (tbr->type) {
412     case TBR_STAIR:
413         return BR_STAIR;
414     case TBR_NO_UP:
415         return tbr->up ? BR_NO_END1 : BR_NO_END2;
416     case TBR_NO_DOWN:
417         return tbr->up ? BR_NO_END2 : BR_NO_END1;
418     case TBR_PORTAL:
419         return BR_PORTAL;
420     }
421     impossible("correct_branch_type: unknown branch type");
422     return BR_STAIR;
423 }
424
425 /*
426  * Add the given branch to the branch list.  The branch list is ordered
427  * by end1 dungeon and level followed by end2 dungeon and level.  If
428  * extract_first is true, then the branch is already part of the list
429  * but needs to be repositioned.
430  */
431 void
432 insert_branch(new_branch, extract_first)
433 branch *new_branch;
434 boolean extract_first;
435 {
436     branch *curr, *prev;
437     long new_val, curr_val, prev_val;
438
439     if (extract_first) {
440         for (prev = 0, curr = branches; curr; prev = curr, curr = curr->next)
441             if (curr == new_branch)
442                 break;
443
444         if (!curr)
445             panic("insert_branch: not found");
446         if (prev)
447             prev->next = curr->next;
448         else
449             branches = curr->next;
450     }
451     new_branch->next = (branch *) 0;
452
453 /* Convert the branch into a unique number so we can sort them. */
454 #define branch_val(bp)                                                     \
455     ((((long) (bp)->end1.dnum * (MAXLEVEL + 1) + (long) (bp)->end1.dlevel) \
456       * (MAXDUNGEON + 1) * (MAXLEVEL + 1))                                 \
457      + ((long) (bp)->end2.dnum * (MAXLEVEL + 1) + (long) (bp)->end2.dlevel))
458
459     /*
460      * Insert the new branch into the correct place in the branch list.
461      */
462     prev = (branch *) 0;
463     prev_val = -1;
464     new_val = branch_val(new_branch);
465     for (curr = branches; curr;
466          prev_val = curr_val, prev = curr, curr = curr->next) {
467         curr_val = branch_val(curr);
468         if (prev_val < new_val && new_val <= curr_val)
469             break;
470     }
471     if (prev) {
472         new_branch->next = curr;
473         prev->next = new_branch;
474     } else {
475         new_branch->next = branches;
476         branches = new_branch;
477     }
478 }
479
480 /* Add a dungeon branch to the branch list. */
481 STATIC_OVL branch *
482 add_branch(dgn, child_entry_level, pd)
483 int dgn;
484 int child_entry_level;
485 struct proto_dungeon *pd;
486 {
487     static int branch_id = 0;
488     int branch_num;
489     branch *new_branch;
490
491     branch_num = find_branch(dungeons[dgn].dname, pd);
492     new_branch = (branch *) alloc(sizeof(branch));
493     new_branch->next = (branch *) 0;
494     new_branch->id = branch_id++;
495     new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
496     new_branch->end1.dnum = parent_dnum(dungeons[dgn].dname, pd);
497     new_branch->end1.dlevel = parent_dlevel(dungeons[dgn].dname, pd);
498     new_branch->end2.dnum = dgn;
499     new_branch->end2.dlevel = child_entry_level;
500     new_branch->end1_up = pd->tmpbranch[branch_num].up ? TRUE : FALSE;
501
502     insert_branch(new_branch, FALSE);
503     return new_branch;
504 }
505
506 /*
507  * Add new level to special level chain.  Insert it in level order with the
508  * other levels in this dungeon.  This assumes that we are never given a
509  * level that has a dungeon number less than the dungeon number of the
510  * last entry.
511  */
512 STATIC_OVL void
513 add_level(new_lev)
514 s_level *new_lev;
515 {
516     s_level *prev, *curr;
517
518     prev = (s_level *) 0;
519     for (curr = sp_levchn; curr; curr = curr->next) {
520         if (curr->dlevel.dnum == new_lev->dlevel.dnum
521             && curr->dlevel.dlevel > new_lev->dlevel.dlevel)
522             break;
523         prev = curr;
524     }
525     if (!prev) {
526         new_lev->next = sp_levchn;
527         sp_levchn = new_lev;
528     } else {
529         new_lev->next = curr;
530         prev->next = new_lev;
531     }
532 }
533
534 STATIC_OVL void
535 init_level(dgn, proto_index, pd)
536 int dgn, proto_index;
537 struct proto_dungeon *pd;
538 {
539     s_level *new_level;
540     struct tmplevel *tlevel = &pd->tmplevel[proto_index];
541
542     pd->final_lev[proto_index] = (s_level *) 0; /* no "real" level */
543     if (!wizard && tlevel->chance <= rn2(100))
544         return;
545
546     pd->final_lev[proto_index] = new_level =
547         (s_level *) alloc(sizeof(s_level));
548     /* load new level with data */
549     Strcpy(new_level->proto, tlevel->name);
550     new_level->boneid = tlevel->boneschar;
551     new_level->dlevel.dnum = dgn;
552     new_level->dlevel.dlevel = 0; /* for now */
553
554     new_level->flags.town = !!(tlevel->flags & TOWN);
555     new_level->flags.hellish = !!(tlevel->flags & HELLISH);
556     new_level->flags.maze_like = !!(tlevel->flags & MAZELIKE);
557     new_level->flags.rogue_like = !!(tlevel->flags & ROGUELIKE);
558     new_level->flags.align = ((tlevel->flags & D_ALIGN_MASK) >> 4);
559     if (!new_level->flags.align)
560         new_level->flags.align =
561             ((pd->tmpdungeon[dgn].flags & D_ALIGN_MASK) >> 4);
562
563     new_level->rndlevs = tlevel->rndlevs;
564     new_level->next = (s_level *) 0;
565 }
566
567 STATIC_OVL int
568 possible_places(idx, map, pd)
569 int idx;      /* prototype index */
570 boolean *map; /* array MAXLEVEL+1 in length */
571 struct proto_dungeon *pd;
572 {
573     int i, start, count;
574     s_level *lev = pd->final_lev[idx];
575
576     /* init level possibilities */
577     for (i = 0; i <= MAXLEVEL; i++)
578         map[i] = FALSE;
579
580     /* get base and range and set those entries to true */
581     count = level_range(lev->dlevel.dnum, pd->tmplevel[idx].lev.base,
582                         pd->tmplevel[idx].lev.rand, pd->tmplevel[idx].chain,
583                         pd, &start);
584     for (i = start; i < start + count; i++)
585         map[i] = TRUE;
586
587     /* mark off already placed levels */
588     for (i = pd->start; i < idx; i++) {
589         if (pd->final_lev[i] && map[pd->final_lev[i]->dlevel.dlevel]) {
590             map[pd->final_lev[i]->dlevel.dlevel] = FALSE;
591             --count;
592         }
593     }
594
595     return count;
596 }
597
598 /* Pick the nth TRUE entry in the given boolean array. */
599 STATIC_OVL xchar
600 pick_level(map, nth)
601 boolean *map; /* an array MAXLEVEL+1 in size */
602 int nth;
603 {
604     int i;
605     for (i = 1; i <= MAXLEVEL; i++)
606         if (map[i] && !nth--)
607             return (xchar) i;
608     panic("pick_level:  ran out of valid levels");
609     return 0;
610 }
611
612 #ifdef DDEBUG
613 static void FDECL(indent, (int));
614
615 static void
616 indent(d)
617 int d;
618 {
619     while (d-- > 0)
620         fputs("    ", stderr);
621 }
622 #endif
623
624 /*
625  * Place a level.  First, find the possible places on a dungeon map
626  * template.  Next pick one.  Then try to place the next level.  If
627  * successful, we're done.  Otherwise, try another (and another) until
628  * all possible places have been tried.  If all possible places have
629  * been exhausted, return false.
630  */
631 STATIC_OVL boolean
632 place_level(proto_index, pd)
633 int proto_index;
634 struct proto_dungeon *pd;
635 {
636     boolean map[MAXLEVEL + 1]; /* valid levels are 1..MAXLEVEL inclusive */
637     s_level *lev;
638     int npossible;
639 #ifdef DDEBUG
640     int i;
641 #endif
642
643     if (proto_index == pd->n_levs)
644         return TRUE; /* at end of proto levels */
645
646     lev = pd->final_lev[proto_index];
647
648     /* No level created for this prototype, goto next. */
649     if (!lev)
650         return place_level(proto_index + 1, pd);
651
652     npossible = possible_places(proto_index, map, pd);
653
654     for (; npossible; --npossible) {
655         lev->dlevel.dlevel = pick_level(map, rn2(npossible));
656 #ifdef DDEBUG
657         indent(proto_index - pd->start);
658         fprintf(stderr, "%s: trying %d [ ", lev->proto, lev->dlevel.dlevel);
659         for (i = 1; i <= MAXLEVEL; i++)
660             if (map[i])
661                 fprintf(stderr, "%d ", i);
662         fprintf(stderr, "]\n");
663 #endif
664         if (place_level(proto_index + 1, pd))
665             return TRUE;
666         map[lev->dlevel.dlevel] = FALSE; /* this choice didn't work */
667     }
668 #ifdef DDEBUG
669     indent(proto_index - pd->start);
670     fprintf(stderr, "%s: failed\n", lev->proto);
671 #endif
672     return FALSE;
673 }
674
675 struct level_map {
676     const char *lev_name;
677     d_level *lev_spec;
678 } level_map[] = { { "air", &air_level },
679                   { "asmodeus", &asmodeus_level },
680                   { "astral", &astral_level },
681                   { "baalz", &baalzebub_level },
682                   { "bigrm", &bigroom_level },
683                   { "castle", &stronghold_level },
684                   { "earth", &earth_level },
685                   { "fakewiz1", &portal_level },
686                   { "fire", &fire_level },
687                   { "juiblex", &juiblex_level },
688                   { "knox", &knox_level },
689                   { "medusa", &medusa_level },
690                   { "oracle", &oracle_level },
691                   { "orcus", &orcus_level },
692                   { "rogue", &rogue_level },
693                   { "sanctum", &sanctum_level },
694                   { "valley", &valley_level },
695                   { "water", &water_level },
696                   { "wizard1", &wiz1_level },
697                   { "wizard2", &wiz2_level },
698                   { "wizard3", &wiz3_level },
699                   { "minend", &mineend_level },
700                   { "soko1", &sokoend_level },
701                   { X_START, &qstart_level },
702                   { X_LOCATE, &qlocate_level },
703                   { X_GOAL, &nemesis_level },
704                   { "", (d_level *) 0 } };
705
706 /* initialize the "dungeon" structs */
707 void
708 init_dungeons()
709 {
710     dlb *dgn_file;
711     register int i, cl = 0, cb = 0;
712     register s_level *x;
713     struct proto_dungeon pd;
714     struct level_map *lev_map;
715     struct version_info vers_info;
716
717     pd.n_levs = pd.n_brs = 0;
718
719     dgn_file = dlb_fopen(DUNGEON_FILE, RDBMODE);
720     if (!dgn_file) {
721         char tbuf[BUFSZ];
722         Sprintf(tbuf, "Cannot open dungeon description - \"%s", DUNGEON_FILE);
723 #ifdef DLBRSRC /* using a resource from the executable */
724         Strcat(tbuf, "\" resource!");
725 #else /* using a file or DLB file */
726 #if defined(DLB)
727         Strcat(tbuf, "\" from ");
728 #ifdef PREFIXES_IN_USE
729         Strcat(tbuf, "\n\"");
730         if (fqn_prefix[DATAPREFIX])
731             Strcat(tbuf, fqn_prefix[DATAPREFIX]);
732 #else
733         Strcat(tbuf, "\"");
734 #endif
735         Strcat(tbuf, DLBFILE);
736 #endif
737         Strcat(tbuf, "\" file!");
738 #endif
739 #ifdef WIN32
740         interject_assistance(1, INTERJECT_PANIC, (genericptr_t) tbuf,
741                              (genericptr_t) fqn_prefix[DATAPREFIX]);
742 #endif
743         panic1(tbuf);
744     }
745
746     /* validate the data's version against the program's version */
747     Fread((genericptr_t) &vers_info, sizeof vers_info, 1, dgn_file);
748     /* we'd better clear the screen now, since when error messages come from
749      * check_version() they will be printed using pline(), which doesn't
750      * mix with the raw messages that might be already on the screen
751      */
752     if (iflags.window_inited)
753         clear_nhwindow(WIN_MAP);
754     if (!check_version(&vers_info, DUNGEON_FILE, TRUE))
755         panic("Dungeon description not valid.");
756
757     /*
758      * Read in each dungeon and transfer the results to the internal
759      * dungeon arrays.
760      */
761     sp_levchn = (s_level *) 0;
762     Fread((genericptr_t) &n_dgns, sizeof(int), 1, dgn_file);
763     if (n_dgns >= MAXDUNGEON)
764         panic("init_dungeons: too many dungeons");
765
766     for (i = 0; i < n_dgns; i++) {
767         Fread((genericptr_t) &pd.tmpdungeon[i], sizeof(struct tmpdungeon), 1,
768               dgn_file);
769         if (!wizard && pd.tmpdungeon[i].chance
770             && (pd.tmpdungeon[i].chance <= rn2(100))) {
771             int j;
772
773             /* skip over any levels or branches */
774             for (j = 0; j < pd.tmpdungeon[i].levels; j++)
775                 Fread((genericptr_t) &pd.tmplevel[cl],
776                       sizeof(struct tmplevel), 1, dgn_file);
777
778             for (j = 0; j < pd.tmpdungeon[i].branches; j++)
779                 Fread((genericptr_t) &pd.tmpbranch[cb],
780                       sizeof(struct tmpbranch), 1, dgn_file);
781             n_dgns--;
782             i--;
783             continue;
784         }
785
786         Strcpy(dungeons[i].dname, pd.tmpdungeon[i].name);
787         Strcpy(dungeons[i].proto, pd.tmpdungeon[i].protoname);
788         dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
789
790         if (pd.tmpdungeon[i].lev.rand)
791             dungeons[i].num_dunlevs = (xchar) rn1(pd.tmpdungeon[i].lev.rand,
792                                                   pd.tmpdungeon[i].lev.base);
793         else
794             dungeons[i].num_dunlevs = (xchar) pd.tmpdungeon[i].lev.base;
795
796         if (!i) {
797             dungeons[i].ledger_start = 0;
798             dungeons[i].depth_start = 1;
799             dungeons[i].dunlev_ureached = 1;
800         } else {
801             dungeons[i].ledger_start =
802                 dungeons[i - 1].ledger_start + dungeons[i - 1].num_dunlevs;
803             dungeons[i].dunlev_ureached = 0;
804         }
805
806         dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH);
807         dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE);
808         dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE);
809         dungeons[i].flags.align =
810             ((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4);
811         /*
812          * Set the entry level for this dungeon.  The pd.tmpdungeon entry
813          * value means:
814          *              < 0     from bottom (-1 == bottom level)
815          *                0     default (top)
816          *              > 0     actual level (1 = top)
817          *
818          * Note that the entry_lev field in the dungeon structure is
819          * redundant.  It is used only here and in print_dungeon().
820          */
821         if (pd.tmpdungeon[i].entry_lev < 0) {
822             dungeons[i].entry_lev =
823                 dungeons[i].num_dunlevs + pd.tmpdungeon[i].entry_lev + 1;
824             if (dungeons[i].entry_lev <= 0)
825                 dungeons[i].entry_lev = 1;
826         } else if (pd.tmpdungeon[i].entry_lev > 0) {
827             dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
828             if (dungeons[i].entry_lev > dungeons[i].num_dunlevs)
829                 dungeons[i].entry_lev = dungeons[i].num_dunlevs;
830         } else {                       /* default */
831             dungeons[i].entry_lev = 1; /* defaults to top level */
832         }
833
834         if (i) { /* set depth */
835             branch *br;
836             schar from_depth;
837             boolean from_up;
838
839             br = add_branch(i, dungeons[i].entry_lev, &pd);
840
841             /* Get the depth of the connecting end. */
842             if (br->end1.dnum == i) {
843                 from_depth = depth(&br->end2);
844                 from_up = !br->end1_up;
845             } else {
846                 from_depth = depth(&br->end1);
847                 from_up = br->end1_up;
848             }
849
850             /*
851              * Calculate the depth of the top of the dungeon via
852              * its branch.  First, the depth of the entry point:
853              *
854              *  depth of branch from "parent" dungeon
855              *  + -1 or 1 depending on a up or down stair or
856              *    0 if portal
857              *
858              * Followed by the depth of the top of the dungeon:
859              *
860              *  - (entry depth - 1)
861              *
862              * We'll say that portals stay on the same depth.
863              */
864             dungeons[i].depth_start =
865                 from_depth + (br->type == BR_PORTAL ? 0 : (from_up ? -1 : 1))
866                 - (dungeons[i].entry_lev - 1);
867         }
868
869         /* this is redundant - it should have been flagged by dgn_comp */
870         if (dungeons[i].num_dunlevs > MAXLEVEL)
871             dungeons[i].num_dunlevs = MAXLEVEL;
872
873         pd.start = pd.n_levs; /* save starting point */
874         pd.n_levs += pd.tmpdungeon[i].levels;
875         if (pd.n_levs > LEV_LIMIT)
876             panic("init_dungeon: too many special levels");
877         /*
878          * Read in the prototype special levels.  Don't add generated
879          * special levels until they are all placed.
880          */
881         for (; cl < pd.n_levs; cl++) {
882             Fread((genericptr_t) &pd.tmplevel[cl], sizeof(struct tmplevel), 1,
883                   dgn_file);
884             init_level(i, cl, &pd);
885         }
886         /*
887          * Recursively place the generated levels for this dungeon.  This
888          * routine will attempt all possible combinations before giving
889          * up.
890          */
891         if (!place_level(pd.start, &pd))
892             panic("init_dungeon:  couldn't place levels");
893 #ifdef DDEBUG
894         fprintf(stderr, "--- end of dungeon %d ---\n", i);
895         fflush(stderr);
896         getchar();
897 #endif
898         for (; pd.start < pd.n_levs; pd.start++)
899             if (pd.final_lev[pd.start])
900                 add_level(pd.final_lev[pd.start]);
901
902         pd.n_brs += pd.tmpdungeon[i].branches;
903         if (pd.n_brs > BRANCH_LIMIT)
904             panic("init_dungeon: too many branches");
905         for (; cb < pd.n_brs; cb++)
906             Fread((genericptr_t) &pd.tmpbranch[cb], sizeof(struct tmpbranch),
907                   1, dgn_file);
908     }
909     (void) dlb_fclose(dgn_file);
910
911     for (i = 0; i < 5; i++)
912         tune[i] = 'A' + rn2(7);
913     tune[5] = 0;
914
915     /*
916      * Find most of the special levels and dungeons so we can access their
917      * locations quickly.
918      */
919     for (lev_map = level_map; lev_map->lev_name[0]; lev_map++) {
920         x = find_level(lev_map->lev_name);
921         if (x) {
922             assign_level(lev_map->lev_spec, &x->dlevel);
923             if (!strncmp(lev_map->lev_name, "x-", 2)) {
924                 /* This is where the name substitution on the
925                  * levels of the quest dungeon occur.
926                  */
927                 Sprintf(x->proto, "%s%s", urole.filecode,
928                         &lev_map->lev_name[1]);
929             } else if (lev_map->lev_spec == &knox_level) {
930                 branch *br;
931                 /*
932                  * Kludge to allow floating Knox entrance.  We
933                  * specify a floating entrance by the fact that
934                  * its entrance (end1) has a bogus dnum, namely
935                  * n_dgns.
936                  */
937                 for (br = branches; br; br = br->next)
938                     if (on_level(&br->end2, &knox_level))
939                         break;
940
941                 if (br)
942                     br->end1.dnum = n_dgns;
943                 /* adjust the branch's position on the list */
944                 insert_branch(br, TRUE);
945             }
946         }
947     }
948     /*
949      *  I hate hardwiring these names. :-(
950      */
951 /*JP
952     quest_dnum = dname_to_dnum("The Quest");
953 */
954     quest_dnum = dname_to_dnum("\83N\83G\83X\83g");
955 /*JP
956     sokoban_dnum = dname_to_dnum("Sokoban");
957 */
958     sokoban_dnum = dname_to_dnum("\91q\8cÉ\94Ô");
959 /*JP
960     mines_dnum = dname_to_dnum("The Gnomish Mines");
961 */
962     mines_dnum = dname_to_dnum("\83m\81[\83\80\82ÃŒ\8dz\8eR");
963 /*JP
964     tower_dnum = dname_to_dnum("Vlad's Tower");
965 */
966     tower_dnum = dname_to_dnum("\83\94\83\89\83h\8cò\82ÃŒ\93\83");
967
968     /* one special fixup for dummy surface level */
969     if ((x = find_level("dummy")) != 0) {
970         i = x->dlevel.dnum;
971         /* the code above puts earth one level above dungeon level #1,
972            making the dummy level overlay level 1; but the whole reason
973            for having the dummy level is to make earth have depth -1
974            instead of 0, so adjust the start point to shift endgame up */
975         if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
976             dungeons[i].depth_start -= 1;
977         /* TO DO: strip "dummy" out all the way here,
978            so that it's hidden from <ctrl/O> feedback. */
979     }
980
981 #ifdef DEBUG
982     dumpit();
983 #endif
984 }
985
986 /* return the level number for lev in *this* dungeon */
987 xchar
988 dunlev(lev)
989 d_level *lev;
990 {
991     return lev->dlevel;
992 }
993
994 /* return the lowest level number for *this* dungeon */
995 xchar
996 dunlevs_in_dungeon(lev)
997 d_level *lev;
998 {
999     return dungeons[lev->dnum].num_dunlevs;
1000 }
1001
1002 /* return the lowest level explored in the game*/
1003 xchar
1004 deepest_lev_reached(noquest)
1005 boolean noquest;
1006 {
1007     /* this function is used for three purposes: to provide a factor
1008      * of difficulty in monster generation; to provide a factor of
1009      * difficulty in experience calculations (botl.c and end.c); and
1010      * to insert the deepest level reached in the game in the topten
1011      * display.  the 'noquest' arg switch is required for the latter.
1012      *
1013      * from the player's point of view, going into the Quest is _not_
1014      * going deeper into the dungeon -- it is going back "home", where
1015      * the dungeon starts at level 1.  given the setup in dungeon.def,
1016      * the depth of the Quest (thought of as starting at level 1) is
1017      * never lower than the level of entry into the Quest, so we exclude
1018      * the Quest from the topten "deepest level reached" display
1019      * calculation.  _However_ the Quest is a difficult dungeon, so we
1020      * include it in the factor of difficulty calculations.
1021      */
1022     register int i;
1023     d_level tmp;
1024     register schar ret = 0;
1025
1026     for (i = 0; i < n_dgns; i++) {
1027         if (noquest && i == quest_dnum)
1028             continue;
1029         tmp.dlevel = dungeons[i].dunlev_ureached;
1030         if (tmp.dlevel == 0)
1031             continue;
1032         tmp.dnum = i;
1033         if (depth(&tmp) > ret)
1034             ret = depth(&tmp);
1035     }
1036     return (xchar) ret;
1037 }
1038
1039 /* return a bookkeeping level number for purpose of comparisons and
1040    save/restore */
1041 xchar
1042 ledger_no(lev)
1043 d_level *lev;
1044 {
1045     return (xchar) (lev->dlevel + dungeons[lev->dnum].ledger_start);
1046 }
1047
1048 /*
1049  * The last level in the bookkeeping list of level is the bottom of the last
1050  * dungeon in the dungeons[] array.
1051  *
1052  * Maxledgerno() -- which is the max number of levels in the bookkeeping
1053  * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1054  * returns the max number of levels in lev's dungeon, and both should
1055  * not be confused with deepest_lev_reached() -- which returns the lowest
1056  * depth visited by the player.
1057  */
1058 xchar
1059 maxledgerno()
1060 {
1061     return (xchar) (dungeons[n_dgns - 1].ledger_start
1062                     + dungeons[n_dgns - 1].num_dunlevs);
1063 }
1064
1065 /* return the dungeon that this ledgerno exists in */
1066 xchar
1067 ledger_to_dnum(ledgerno)
1068 xchar ledgerno;
1069 {
1070     register int i;
1071
1072     /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1073     for (i = 0; i < n_dgns; i++)
1074         if (dungeons[i].ledger_start < ledgerno
1075             && ledgerno <= dungeons[i].ledger_start + dungeons[i].num_dunlevs)
1076             return (xchar) i;
1077
1078     panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno);
1079     /*NOT REACHED*/
1080     return (xchar) 0;
1081 }
1082
1083 /* return the level of the dungeon this ledgerno exists in */
1084 xchar
1085 ledger_to_dlev(ledgerno)
1086 xchar ledgerno;
1087 {
1088     return (xchar) (ledgerno
1089                     - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
1090 }
1091
1092 /* returns the depth of a level, in floors below the surface
1093    (note levels in different dungeons can have the same depth) */
1094 schar
1095 depth(lev)
1096 d_level *lev;
1097 {
1098     return (schar) (dungeons[lev->dnum].depth_start + lev->dlevel - 1);
1099 }
1100
1101 /* are "lev1" and "lev2" actually the same? */
1102 boolean
1103 on_level(lev1, lev2)
1104 d_level *lev1, *lev2;
1105 {
1106     return (boolean) (lev1->dnum == lev2->dnum
1107                       && lev1->dlevel == lev2->dlevel);
1108 }
1109
1110 /* is this level referenced in the special level chain? */
1111 s_level *
1112 Is_special(lev)
1113 d_level *lev;
1114 {
1115     s_level *levtmp;
1116
1117     for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
1118         if (on_level(lev, &levtmp->dlevel))
1119             return levtmp;
1120
1121     return (s_level *) 0;
1122 }
1123
1124 /*
1125  * Is this a multi-dungeon branch level?  If so, return a pointer to the
1126  * branch.  Otherwise, return null.
1127  */
1128 branch *
1129 Is_branchlev(lev)
1130 d_level *lev;
1131 {
1132     branch *curr;
1133
1134     for (curr = branches; curr; curr = curr->next) {
1135         if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
1136             return curr;
1137     }
1138     return (branch *) 0;
1139 }
1140
1141 /* returns True iff the branch 'lev' is in a branch which builds up */
1142 boolean
1143 builds_up(lev)
1144 d_level *lev;
1145 {
1146     dungeon *dptr = &dungeons[lev->dnum];
1147     /*
1148      * FIXME:  this misclassifies a single level branch reached via stairs
1149      * from below.  Saving grace is that no such branches currently exist.
1150      */
1151     return (boolean) (dptr->num_dunlevs > 1
1152                       && dptr->entry_lev == dptr->num_dunlevs);
1153 }
1154
1155 /* goto the next level (or appropriate dungeon) */
1156 void
1157 next_level(at_stairs)
1158 boolean at_stairs;
1159 {
1160     if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1161         /* Taking a down dungeon branch. */
1162         goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1163     } else {
1164         /* Going down a stairs or jump in a trap door. */
1165         d_level newlevel;
1166
1167         newlevel.dnum = u.uz.dnum;
1168         newlevel.dlevel = u.uz.dlevel + 1;
1169         goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
1170     }
1171 }
1172
1173 /* goto the previous level (or appropriate dungeon) */
1174 void
1175 prev_level(at_stairs)
1176 boolean at_stairs;
1177 {
1178     if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1179         /* Taking an up dungeon branch. */
1180         /* KMH -- Upwards branches are okay if not level 1 */
1181         /* (Just make sure it doesn't go above depth 1) */
1182         if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
1183             done(ESCAPED);
1184         else
1185             goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1186     } else {
1187         /* Going up a stairs or rising through the ceiling. */
1188         d_level newlevel;
1189         newlevel.dnum = u.uz.dnum;
1190         newlevel.dlevel = u.uz.dlevel - 1;
1191         goto_level(&newlevel, at_stairs, FALSE, FALSE);
1192     }
1193 }
1194
1195 void
1196 u_on_newpos(x, y)
1197 int x, y;
1198 {
1199     u.ux = x;
1200     u.uy = y;
1201 #ifdef CLIPPING
1202     cliparound(u.ux, u.uy);
1203 #endif
1204     /* ridden steed always shares hero's location */
1205     if (u.usteed)
1206         u.usteed->mx = u.ux, u.usteed->my = u.uy;
1207     /* when changing levels, don't leave old position set with
1208        stale values from previous level */
1209     if (!on_level(&u.uz, &u.uz0))
1210         u.ux0 = u.ux, u.uy0 = u.uy;
1211 }
1212
1213 /* place you on a random location */
1214 void
1215 u_on_rndspot(upflag)
1216 int upflag;
1217 {
1218     int up = (upflag & 1), was_in_W_tower = (upflag & 2);
1219
1220     /*
1221      * Place the hero at a random location within the relevant region.
1222      * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1223      * Unspecified region (.lx == 0) defaults to entire level.
1224      */
1225     if (was_in_W_tower && On_W_tower_level(&u.uz))
1226         /* Stay inside the Wizard's tower when feasible.
1227            We use the W Tower's exclusion region for the
1228            destination instead of its enclosing region.
1229            Note: up vs down doesn't matter in this case
1230            because both specify the same exclusion area. */
1231         place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy, 0, 0, 0,
1232                       0, LR_DOWNTELE, (d_level *) 0);
1233     else if (up)
1234         place_lregion(updest.lx, updest.ly, updest.hx, updest.hy, updest.nlx,
1235                       updest.nly, updest.nhx, updest.nhy, LR_UPTELE,
1236                       (d_level *) 0);
1237     else
1238         place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy, dndest.nlx,
1239                       dndest.nly, dndest.nhx, dndest.nhy, LR_DOWNTELE,
1240                       (d_level *) 0);
1241 }
1242
1243 /* place you on the special staircase */
1244 void
1245 u_on_sstairs(upflag)
1246 int upflag;
1247 {
1248     if (sstairs.sx)
1249         u_on_newpos(sstairs.sx, sstairs.sy);
1250     else
1251         u_on_rndspot(upflag);
1252 }
1253
1254 /* place you on upstairs (or special equivalent) */
1255 void
1256 u_on_upstairs()
1257 {
1258     if (xupstair)
1259         u_on_newpos(xupstair, yupstair);
1260     else
1261         u_on_sstairs(0); /* destination upstairs implies moving down */
1262 }
1263
1264 /* place you on dnstairs (or special equivalent) */
1265 void
1266 u_on_dnstairs()
1267 {
1268     if (xdnstair)
1269         u_on_newpos(xdnstair, ydnstair);
1270     else
1271         u_on_sstairs(1); /* destination dnstairs implies moving up */
1272 }
1273
1274 boolean
1275 On_stairs(x, y)
1276 xchar x, y;
1277 {
1278     return (boolean) ((x == xupstair && y == yupstair)
1279                       || (x == xdnstair && y == ydnstair)
1280                       || (x == xdnladder && y == ydnladder)
1281                       || (x == xupladder && y == yupladder)
1282                       || (x == sstairs.sx && y == sstairs.sy));
1283 }
1284
1285 boolean
1286 Is_botlevel(lev)
1287 d_level *lev;
1288 {
1289     return (boolean) (lev->dlevel == dungeons[lev->dnum].num_dunlevs);
1290 }
1291
1292 boolean
1293 Can_dig_down(lev)
1294 d_level *lev;
1295 {
1296     return (boolean) (!level.flags.hardfloor
1297                       && !Is_botlevel(lev)
1298                       && !Invocation_lev(lev));
1299 }
1300
1301 /*
1302  * Like Can_dig_down (above), but also allows falling through on the
1303  * stronghold level.  Normally, the bottom level of a dungeon resists
1304  * both digging and falling.
1305  */
1306 boolean
1307 Can_fall_thru(lev)
1308 d_level *lev;
1309 {
1310     return (boolean) (Can_dig_down(lev) || Is_stronghold(lev));
1311 }
1312
1313 /*
1314  * True if one can rise up a level (e.g. cursed gain level).
1315  * This happens on intermediate dungeon levels or on any top dungeon
1316  * level that has a stairwell style branch to the next higher dungeon.
1317  * Checks for amulets and such must be done elsewhere.
1318  */
1319 boolean
1320 Can_rise_up(x, y, lev)
1321 int x, y;
1322 d_level *lev;
1323 {
1324     /* can't rise up from inside the top of the Wizard's tower */
1325     /* KMH -- or in sokoban */
1326     if (In_endgame(lev) || In_sokoban(lev)
1327         || (Is_wiz1_level(lev) && In_W_tower(x, y, lev)))
1328         return FALSE;
1329     return (boolean) (lev->dlevel > 1
1330                       || (dungeons[lev->dnum].entry_lev == 1
1331                           && ledger_no(lev) != 1
1332                           && sstairs.sx && sstairs.up));
1333 }
1334
1335 boolean
1336 has_ceiling(lev)
1337 d_level *lev;
1338 {
1339     /* [what about level 1 of the quest?] */
1340     return (boolean) (!Is_airlevel(lev) && !Is_waterlevel(lev));
1341 }
1342
1343 /*
1344  * It is expected that the second argument of get_level is a depth value,
1345  * either supplied by the user (teleport control) or randomly generated.
1346  * But more than one level can be at the same depth.  If the target level
1347  * is "above" the present depth location, get_level must trace "up" from
1348  * the player's location (through the ancestors dungeons) the dungeon
1349  * within which the target level is located.  With only one exception
1350  * which does not pass through this routine (see level_tele), teleporting
1351  * "down" is confined to the current dungeon.  At present, level teleport
1352  * in dungeons that build up is confined within them.
1353  */
1354 void
1355 get_level(newlevel, levnum)
1356 d_level *newlevel;
1357 int levnum;
1358 {
1359     branch *br;
1360     xchar dgn = u.uz.dnum;
1361
1362     if (levnum <= 0) {
1363         /* can only currently happen in endgame */
1364         levnum = u.uz.dlevel;
1365     } else if (levnum
1366                > dungeons[dgn].depth_start + dungeons[dgn].num_dunlevs - 1) {
1367         /* beyond end of dungeon, jump to last level */
1368         levnum = dungeons[dgn].num_dunlevs;
1369     } else {
1370         /* The desired level is in this dungeon or a "higher" one. */
1371
1372         /*
1373          * Branch up the tree until we reach a dungeon that contains the
1374          * levnum.
1375          */
1376         if (levnum < dungeons[dgn].depth_start) {
1377             do {
1378                 /*
1379                  * Find the parent dungeon of this dungeon.
1380                  *
1381                  * This assumes that end2 is always the "child" and it is
1382                  * unique.
1383                  */
1384                 for (br = branches; br; br = br->next)
1385                     if (br->end2.dnum == dgn)
1386                         break;
1387                 if (!br)
1388                     panic("get_level: can't find parent dungeon");
1389
1390                 dgn = br->end1.dnum;
1391             } while (levnum < dungeons[dgn].depth_start);
1392         }
1393
1394         /* We're within the same dungeon; calculate the level. */
1395         levnum = levnum - dungeons[dgn].depth_start + 1;
1396     }
1397
1398     newlevel->dnum = dgn;
1399     newlevel->dlevel = levnum;
1400 }
1401
1402 /* are you in the quest dungeon? */
1403 boolean
1404 In_quest(lev)
1405 d_level *lev;
1406 {
1407     return (boolean) (lev->dnum == quest_dnum);
1408 }
1409
1410 /* are you in the mines dungeon? */
1411 boolean
1412 In_mines(lev)
1413 d_level *lev;
1414 {
1415     return (boolean) (lev->dnum == mines_dnum);
1416 }
1417
1418 /*
1419  * Return the branch for the given dungeon.
1420  *
1421  * This function assumes:
1422  *      + This is not called with "Dungeons of Doom".
1423  *      + There is only _one_ branch to a given dungeon.
1424  *      + Field end2 is the "child" dungeon.
1425  */
1426 branch *
1427 dungeon_branch(s)
1428 const char *s;
1429 {
1430     branch *br;
1431     xchar dnum;
1432
1433     dnum = dname_to_dnum(s);
1434
1435     /* Find the branch that connects to dungeon i's branch. */
1436     for (br = branches; br; br = br->next)
1437         if (br->end2.dnum == dnum)
1438             break;
1439
1440     if (!br)
1441         panic("dgn_entrance: can't find entrance to %s", s);
1442
1443     return br;
1444 }
1445
1446 /*
1447  * This returns true if the hero is on the same level as the entrance to
1448  * the named dungeon.
1449  *
1450  * Called from do.c and mklev.c.
1451  *
1452  * Assumes that end1 is always the "parent".
1453  */
1454 boolean
1455 at_dgn_entrance(s)
1456 const char *s;
1457 {
1458     branch *br;
1459
1460     br = dungeon_branch(s);
1461     return on_level(&u.uz, &br->end1) ? TRUE : FALSE;
1462 }
1463
1464 /* is `lev' part of Vlad's tower? */
1465 boolean
1466 In_V_tower(lev)
1467 d_level *lev;
1468 {
1469     return (boolean) (lev->dnum == tower_dnum);
1470 }
1471
1472 /* is `lev' a level containing the Wizard's tower? */
1473 boolean
1474 On_W_tower_level(lev)
1475 d_level *lev;
1476 {
1477     return (boolean) (Is_wiz1_level(lev)
1478                       || Is_wiz2_level(lev)
1479                       || Is_wiz3_level(lev));
1480 }
1481
1482 /* is <x,y> of `lev' inside the Wizard's tower? */
1483 boolean
1484 In_W_tower(x, y, lev)
1485 int x, y;
1486 d_level *lev;
1487 {
1488     if (!On_W_tower_level(lev))
1489         return FALSE;
1490     /*
1491      * Both of the exclusion regions for arriving via level teleport
1492      * (from above or below) define the tower's boundary.
1493      *  assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1494      */
1495     if (dndest.nlx > 0)
1496         return (boolean) within_bounded_area(x, y, dndest.nlx, dndest.nly,
1497                                              dndest.nhx, dndest.nhy);
1498     else
1499         impossible("No boundary for Wizard's Tower?");
1500     return FALSE;
1501 }
1502
1503 /* are you in one of the Hell levels? */
1504 boolean
1505 In_hell(lev)
1506 d_level *lev;
1507 {
1508     return (boolean) (dungeons[lev->dnum].flags.hellish);
1509 }
1510
1511 /* sets *lev to be the gateway to Gehennom... */
1512 void
1513 find_hell(lev)
1514 d_level *lev;
1515 {
1516     lev->dnum = valley_level.dnum;
1517     lev->dlevel = 1;
1518 }
1519
1520 /* go directly to hell... */
1521 void
1522 goto_hell(at_stairs, falling)
1523 boolean at_stairs, falling;
1524 {
1525     d_level lev;
1526
1527     find_hell(&lev);
1528     goto_level(&lev, at_stairs, falling, FALSE);
1529 }
1530
1531 /* equivalent to dest = source */
1532 void
1533 assign_level(dest, src)
1534 d_level *dest, *src;
1535 {
1536     dest->dnum = src->dnum;
1537     dest->dlevel = src->dlevel;
1538 }
1539
1540 /* dest = src + rn1(range) */
1541 void
1542 assign_rnd_level(dest, src, range)
1543 d_level *dest, *src;
1544 int range;
1545 {
1546     dest->dnum = src->dnum;
1547     dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range));
1548
1549     if (dest->dlevel > dunlevs_in_dungeon(dest))
1550         dest->dlevel = dunlevs_in_dungeon(dest);
1551     else if (dest->dlevel < 1)
1552         dest->dlevel = 1;
1553 }
1554
1555 int
1556 induced_align(pct)
1557 int pct;
1558 {
1559     s_level *lev = Is_special(&u.uz);
1560     aligntyp al;
1561
1562     if (lev && lev->flags.align)
1563         if (rn2(100) < pct)
1564             return lev->flags.align;
1565
1566     if (dungeons[u.uz.dnum].flags.align)
1567         if (rn2(100) < pct)
1568             return dungeons[u.uz.dnum].flags.align;
1569
1570     al = rn2(3) - 1;
1571     return Align2amask(al);
1572 }
1573
1574 boolean
1575 Invocation_lev(lev)
1576 d_level *lev;
1577 {
1578     return (boolean) (In_hell(lev)
1579                       && lev->dlevel == dungeons[lev->dnum].num_dunlevs - 1);
1580 }
1581
1582 /* use instead of depth() wherever a degree of difficulty is made
1583  * dependent on the location in the dungeon (eg. monster creation).
1584  */
1585 xchar
1586 level_difficulty()
1587 {
1588     int res;
1589
1590     if (In_endgame(&u.uz)) {
1591         res = depth(&sanctum_level) + u.ulevel / 2;
1592     } else if (u.uhave.amulet) {
1593         res = deepest_lev_reached(FALSE);
1594     } else {
1595         res = depth(&u.uz);
1596         /* depth() is the number of elevation units (levels) below
1597            the theoretical surface; in a builds-up branch, that value
1598            ends up making the harder to reach levels be treated as if
1599            they were easier; adjust for the extra effort involved in
1600            going down to the entrance and then up to the location */
1601         if (builds_up(&u.uz))
1602             res += 2 * (dungeons[u.uz.dnum].entry_lev - u.uz.dlevel + 1);
1603             /*
1604              * 'Proof' by example:  suppose the entrance to sokoban is
1605              * on dungeon level 9, leading up to bottom sokoban level
1606              * of 8 [entry_lev].  When the hero is on sokoban level 8
1607              * [uz.dlevel], depth() yields eight but he has ventured
1608              * one level beyond 9, so difficulty depth should be 10:
1609              *   8 + 2 * (8 - 8 + 1) => 10.
1610              * Going up to 7, depth is 7 but hero will be two beyond 9:
1611              *   7 + 2 * (8 - 7 + 1) => 11.
1612              * When he goes up to level 6, three levels beyond 9:
1613              *   6 + 2 * (8 - 6 + 1) => 12.
1614              * And the top level of sokoban at 5, four levels beyond 9:
1615              *   5 + 2 * (8 - 5 + 1) => 13.
1616              * The same applies to Vlad's Tower, although the increment
1617              * there is inconsequential compared to overall depth.
1618              */
1619     }
1620     return (xchar) res;
1621 }
1622
1623 /* Take one word and try to match it to a level.
1624  * Recognized levels are as shown by print_dungeon().
1625  */
1626 schar
1627 lev_by_name(nam)
1628 const char *nam;
1629 {
1630     schar lev = 0;
1631     s_level *slev;
1632     d_level dlev;
1633     const char *p;
1634     int idx, idxtoo;
1635     char buf[BUFSZ];
1636
1637     /* allow strings like "the oracle level" to find "oracle" */
1638     if (!strncmpi(nam, "the ", 4))
1639         nam += 4;
1640     if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
1641         nam = strcpy(buf, nam);
1642         *(eos(buf) - 6) = '\0';
1643     }
1644     /* hell is the old name, and wouldn't match; gehennom would match its
1645        branch, yielding the castle level instead of the valley of the dead */
1646     if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1647         if (In_V_tower(&u.uz))
1648             nam = " to Vlad's tower"; /* branch to... */
1649         else
1650             nam = "valley";
1651     }
1652
1653     if ((slev = find_level(nam)) != 0) {
1654         dlev = slev->dlevel;
1655         idx = ledger_no(&dlev);
1656         if ((dlev.dnum == u.uz.dnum
1657              /* within same branch, or else main dungeon <-> gehennom */
1658              || (u.uz.dnum == valley_level.dnum
1659                  && dlev.dnum == medusa_level.dnum)
1660              || (u.uz.dnum == medusa_level.dnum
1661                  && dlev.dnum == valley_level.dnum))
1662             && (/* either wizard mode or else seen and not forgotten */
1663                 wizard
1664                 || (level_info[idx].flags & (FORGOTTEN | VISITED))
1665                        == VISITED)) {
1666             lev = depth(&slev->dlevel);
1667         }
1668     } else { /* not a specific level; try branch names */
1669         idx = find_branch(nam, (struct proto_dungeon *) 0);
1670         /* "<branch> to Xyzzy" */
1671         if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1672             idx = find_branch(p + 4, (struct proto_dungeon *) 0);
1673
1674         if (idx >= 0) {
1675             idxtoo = (idx >> 8) & 0x00FF;
1676             idx &= 0x00FF;
1677             if (/* either wizard mode, or else _both_ sides of branch seen */
1678                 wizard
1679                 || ((level_info[idx].flags & (FORGOTTEN | VISITED)) == VISITED
1680                     && (level_info[idxtoo].flags & (FORGOTTEN | VISITED))
1681                            == VISITED)) {
1682                 if (ledger_to_dnum(idxtoo) == u.uz.dnum)
1683                     idx = idxtoo;
1684                 dlev.dnum = ledger_to_dnum(idx);
1685                 dlev.dlevel = ledger_to_dlev(idx);
1686                 lev = depth(&dlev);
1687             }
1688         }
1689     }
1690     return lev;
1691 }
1692
1693 STATIC_OVL boolean
1694 unplaced_floater(dptr)
1695 struct dungeon *dptr;
1696 {
1697     branch *br;
1698     int idx = (int) (dptr - dungeons);
1699
1700     /* if other floating branches are added, this will need to change */
1701     if (idx != knox_level.dnum)
1702         return FALSE;
1703     for (br = branches; br; br = br->next)
1704         if (br->end1.dnum == n_dgns && br->end2.dnum == idx)
1705             return TRUE;
1706     return FALSE;
1707 }
1708
1709 STATIC_OVL boolean
1710 unreachable_level(lvl_p, unplaced)
1711 d_level *lvl_p;
1712 boolean unplaced;
1713 {
1714     s_level *dummy;
1715
1716     if (unplaced)
1717         return TRUE;
1718     if (In_endgame(&u.uz) && !In_endgame(lvl_p))
1719         return TRUE;
1720     if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
1721         return TRUE;
1722     return FALSE;
1723 }
1724
1725 static void
1726 tport_menu(win, entry, lchoices, lvl_p, unreachable)
1727 winid win;
1728 char *entry;
1729 struct lchoice *lchoices;
1730 d_level *lvl_p;
1731 boolean unreachable;
1732 {
1733     char tmpbuf[BUFSZ];
1734     anything any;
1735
1736     lchoices->lev[lchoices->idx] = lvl_p->dlevel;
1737     lchoices->dgn[lchoices->idx] = lvl_p->dnum;
1738     lchoices->playerlev[lchoices->idx] = depth(lvl_p);
1739     any = zeroany;
1740     if (unreachable) {
1741         /* not selectable, but still consumes next menuletter;
1742            prepend padding in place of missing menu selector */
1743         Sprintf(tmpbuf, "    %s", entry);
1744         entry = tmpbuf;
1745     } else {
1746         any.a_int = lchoices->idx + 1;
1747     }
1748     add_menu(win, NO_GLYPH, &any, lchoices->menuletter, 0, ATR_NONE, entry,
1749              MENU_UNSELECTED);
1750     /* this assumes there are at most 52 interesting levels */
1751     if (lchoices->menuletter == 'z')
1752         lchoices->menuletter = 'A';
1753     else
1754         lchoices->menuletter++;
1755     lchoices->idx++;
1756     return;
1757 }
1758
1759 /* Convert a branch type to a string usable by print_dungeon(). */
1760 STATIC_OVL const char *
1761 br_string(type)
1762 int type;
1763 {
1764     switch (type) {
1765     case BR_PORTAL:
1766         return "Portal";
1767     case BR_NO_END1:
1768         return "Connection";
1769     case BR_NO_END2:
1770         return "One way stair";
1771     case BR_STAIR:
1772         return "Stair";
1773     }
1774     return " (unknown)";
1775 }
1776
1777 /* Print all child branches between the lower and upper bounds. */
1778 STATIC_OVL void
1779 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
1780 winid win;
1781 int dnum;
1782 int lower_bound;
1783 int upper_bound;
1784 boolean bymenu;
1785 struct lchoice *lchoices_p;
1786 {
1787     branch *br;
1788     char buf[BUFSZ];
1789
1790     /* This assumes that end1 is the "parent". */
1791     for (br = branches; br; br = br->next) {
1792         if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
1793             && br->end1.dlevel <= upper_bound) {
1794             Sprintf(buf, "   %s to %s: %d", br_string(br->type),
1795                     dungeons[br->end2.dnum].dname, depth(&br->end1));
1796             if (bymenu)
1797                 tport_menu(win, buf, lchoices_p, &br->end1,
1798                            unreachable_level(&br->end1, FALSE));
1799             else
1800                 putstr(win, 0, buf);
1801         }
1802     }
1803 }
1804
1805 /* Print available dungeon information. */
1806 schar
1807 print_dungeon(bymenu, rlev, rdgn)
1808 boolean bymenu;
1809 schar *rlev;
1810 xchar *rdgn;
1811 {
1812     int i, last_level, nlev;
1813     char buf[BUFSZ];
1814     const char *descr;
1815     boolean first, unplaced;
1816     s_level *slev;
1817     dungeon *dptr;
1818     branch *br;
1819     anything any;
1820     struct lchoice lchoices;
1821
1822     winid win = create_nhwindow(NHW_MENU);
1823     if (bymenu) {
1824         start_menu(win);
1825         lchoices.idx = 0;
1826         lchoices.menuletter = 'a';
1827     }
1828
1829     for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1830         if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum)
1831             continue;
1832         unplaced = unplaced_floater(dptr);
1833         descr = unplaced ? "depth" : "level";
1834         nlev = dptr->num_dunlevs;
1835         if (nlev > 1)
1836             Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
1837                     dptr->depth_start, dptr->depth_start + nlev - 1);
1838         else
1839             Sprintf(buf, "%s: %s %d", dptr->dname, descr, dptr->depth_start);
1840
1841         /* Most entrances are uninteresting. */
1842         if (dptr->entry_lev != 1) {
1843             if (dptr->entry_lev == nlev)
1844                 Strcat(buf, ", entrance from below");
1845             else
1846                 Sprintf(eos(buf), ", entrance on %d",
1847                         dptr->depth_start + dptr->entry_lev - 1);
1848         }
1849         if (bymenu) {
1850             any = zeroany;
1851             add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
1852                      MENU_UNSELECTED);
1853         } else
1854             putstr(win, 0, buf);
1855
1856         /*
1857          * Circle through the special levels to find levels that are in
1858          * this dungeon.
1859          */
1860         for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1861             if (slev->dlevel.dnum != i)
1862                 continue;
1863
1864             /* print any branches before this level */
1865             print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
1866                          &lchoices);
1867
1868             Sprintf(buf, "   %s: %d", slev->proto, depth(&slev->dlevel));
1869             if (Is_stronghold(&slev->dlevel))
1870                 Sprintf(eos(buf), " (tune %s)", tune);
1871             if (bymenu)
1872                 tport_menu(win, buf, &lchoices, &slev->dlevel,
1873                            unreachable_level(&slev->dlevel, unplaced));
1874             else
1875                 putstr(win, 0, buf);
1876
1877             last_level = slev->dlevel.dlevel;
1878         }
1879         /* print branches after the last special level */
1880         print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1881     }
1882
1883     if (bymenu) {
1884         int n;
1885         menu_item *selected;
1886         int idx;
1887
1888         end_menu(win, "Level teleport to where:");
1889         n = select_menu(win, PICK_ONE, &selected);
1890         destroy_nhwindow(win);
1891         if (n > 0) {
1892             idx = selected[0].item.a_int - 1;
1893             free((genericptr_t) selected);
1894             if (rlev && rdgn) {
1895                 *rlev = lchoices.lev[idx];
1896                 *rdgn = lchoices.dgn[idx];
1897                 return lchoices.playerlev[idx];
1898             }
1899         }
1900         return 0;
1901     }
1902
1903     /* Print out floating branches (if any). */
1904     for (first = TRUE, br = branches; br; br = br->next) {
1905         if (br->end1.dnum == n_dgns) {
1906             if (first) {
1907                 putstr(win, 0, "");
1908                 putstr(win, 0, "Floating branches");
1909                 first = FALSE;
1910             }
1911             Sprintf(buf, "   %s to %s", br_string(br->type),
1912                     dungeons[br->end2.dnum].dname);
1913             putstr(win, 0, buf);
1914         }
1915     }
1916
1917     /* I hate searching for the invocation pos while debugging. -dean */
1918     if (Invocation_lev(&u.uz)) {
1919         putstr(win, 0, "");
1920         Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1921                 inv_pos.x, inv_pos.y, u.ux, u.uy);
1922         putstr(win, 0, buf);
1923     }
1924     /*
1925      * The following is based on the assumption that the inter-level portals
1926      * created by the level compiler (not the dungeon compiler) only exist
1927      * one per level (currently true, of course).
1928      */
1929     else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
1930              || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
1931         struct trap *trap;
1932         for (trap = ftrap; trap; trap = trap->ntrap)
1933             if (trap->ttyp == MAGIC_PORTAL)
1934                 break;
1935
1936         putstr(win, 0, "");
1937         if (trap)
1938             Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)", trap->tx,
1939                     trap->ty, u.ux, u.uy);
1940         else
1941             Sprintf(buf, "No portal found.");
1942         putstr(win, 0, buf);
1943     }
1944
1945     display_nhwindow(win, TRUE);
1946     destroy_nhwindow(win);
1947     return 0;
1948 }
1949
1950 /* Record that the player knows about a branch from a level. This function
1951  * will determine whether or not it was a "real" branch that was taken.
1952  * This function should not be called for a transition done via level
1953  * teleport or via the Eye.
1954  */
1955 void
1956 recbranch_mapseen(source, dest)
1957 d_level *source;
1958 d_level *dest;
1959 {
1960     mapseen *mptr;
1961     branch *br;
1962
1963     /* not a branch */
1964     if (source->dnum == dest->dnum)
1965         return;
1966
1967     /* we only care about forward branches */
1968     for (br = branches; br; br = br->next) {
1969         if (on_level(source, &br->end1) && on_level(dest, &br->end2))
1970             break;
1971         if (on_level(source, &br->end2) && on_level(dest, &br->end1))
1972             return;
1973     }
1974
1975     /* branch not found, so not a real branch. */
1976     if (!br)
1977         return;
1978
1979     if ((mptr = find_mapseen(source)) != 0) {
1980         if (mptr->br && br != mptr->br)
1981             impossible("Two branches on the same level?");
1982         mptr->br = br;
1983     } else {
1984         impossible("Can't note branch for unseen level (%d, %d)",
1985                    source->dnum, source->dlevel);
1986     }
1987 }
1988
1989 char *
1990 get_annotation(lev)
1991 d_level *lev;
1992 {
1993     mapseen *mptr;
1994
1995     if ((mptr = find_mapseen(lev)))
1996         return mptr->custom;
1997     return NULL;
1998 }
1999
2000 /* #annotate command - add a custom name to the current level */
2001 int
2002 donamelevel()
2003 {
2004     mapseen *mptr;
2005     char nbuf[BUFSZ]; /* Buffer for response */
2006
2007     if (!(mptr = find_mapseen(&u.uz)))
2008         return 0;
2009
2010     if (mptr->custom) {
2011         char tmpbuf[BUFSZ];
2012         Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
2013                 strlen(mptr->custom) > 30 ? "..." : "");
2014         getlin(tmpbuf, nbuf);
2015     } else
2016         getlin("What do you want to call this dungeon level?", nbuf);
2017     if (index(nbuf, '\033'))
2018         return 0;
2019     (void) mungspaces(nbuf);
2020
2021     /* discard old annotation, if any */
2022     if (mptr->custom) {
2023         free((genericptr_t) mptr->custom);
2024         mptr->custom = (char *) 0;
2025         mptr->custom_lth = 0;
2026     }
2027     /* add new annotation, unless it's empty or a single space */
2028     if (*nbuf && strcmp(nbuf, " ")) {
2029         mptr->custom = dupstr(nbuf);
2030         mptr->custom_lth = strlen(mptr->custom);
2031     }
2032     return 0;
2033 }
2034
2035 /* find the particular mapseen object in the chain; may return null */
2036 STATIC_OVL mapseen *
2037 find_mapseen(lev)
2038 d_level *lev;
2039 {
2040     mapseen *mptr;
2041
2042     for (mptr = mapseenchn; mptr; mptr = mptr->next)
2043         if (on_level(&(mptr->lev), lev))
2044             break;
2045
2046     return mptr;
2047 }
2048
2049 void
2050 forget_mapseen(ledger_num)
2051 int ledger_num;
2052 {
2053     mapseen *mptr;
2054     struct cemetery *bp;
2055
2056     for (mptr = mapseenchn; mptr; mptr = mptr->next)
2057         if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
2058             == ledger_num)
2059             break;
2060
2061     /* if not found, then nothing to forget */
2062     if (mptr) {
2063         mptr->flags.forgot = 1;
2064         mptr->br = (branch *) 0;
2065
2066         /* custom names are erased, not just forgotten until revisited */
2067         if (mptr->custom) {
2068             mptr->custom_lth = 0;
2069             free((genericptr_t) mptr->custom);
2070             mptr->custom = (char *) 0;
2071         }
2072         (void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
2073         for (bp = mptr->final_resting_place; bp; bp = bp->next)
2074             bp->bonesknown = FALSE;
2075     }
2076 }
2077
2078 STATIC_OVL void
2079 save_mapseen(fd, mptr)
2080 int fd;
2081 mapseen *mptr;
2082 {
2083     branch *curr;
2084     int brindx;
2085
2086     for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2087         if (curr == mptr->br)
2088             break;
2089     bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
2090
2091     bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
2092     bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
2093     bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
2094     bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
2095     if (mptr->custom_lth)
2096         bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
2097     bwrite(fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
2098     savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
2099 }
2100
2101 STATIC_OVL mapseen *
2102 load_mapseen(fd)
2103 int fd;
2104 {
2105     int branchnum, brindx;
2106     mapseen *load;
2107     branch *curr;
2108
2109     load = (mapseen *) alloc(sizeof *load);
2110
2111     mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
2112     for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2113         if (brindx == branchnum)
2114             break;
2115     load->br = curr;
2116
2117     mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
2118     mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
2119     mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
2120     mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
2121     if (load->custom_lth) {
2122         /* length doesn't include terminator (which isn't saved & restored) */
2123         load->custom = (char *) alloc(load->custom_lth + 1);
2124         mread(fd, (genericptr_t) load->custom, load->custom_lth);
2125         load->custom[load->custom_lth] = '\0';
2126     } else
2127         load->custom = 0;
2128     mread(fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
2129     restcemetery(fd, &load->final_resting_place);
2130
2131     return load;
2132 }
2133
2134 /* Remove all mapseen objects for a particular dnum.
2135  * Useful during quest expulsion to remove quest levels.
2136  * [No longer deleted, just marked as unreachable.  #overview will
2137  * ignore such levels, end of game disclosure will include them.]
2138  */
2139 void
2140 remdun_mapseen(dnum)
2141 int dnum;
2142 {
2143     mapseen *mptr, **mptraddr;
2144
2145     mptraddr = &mapseenchn;
2146     while ((mptr = *mptraddr) != 0) {
2147         if (mptr->lev.dnum == dnum) {
2148 #if 1 /* use this... */
2149             mptr->flags.unreachable = 1;
2150         }
2151 #else /* old deletion code */
2152             *mptraddr = mptr->next;
2153             if (mptr->custom)
2154                 free((genericptr_t) mptr->custom);
2155             if (mptr->final_resting_place)
2156                 savecemetery(-1, FREE_SAVE, &mptr->final_resting_place);
2157             free((genericptr_t) mptr);
2158         } else
2159 #endif
2160         mptraddr = &mptr->next;
2161     }
2162 }
2163
2164 void
2165 init_mapseen(lev)
2166 d_level *lev;
2167 {
2168     /* Create a level and insert in "sorted" order.  This is an insertion
2169      * sort first by dungeon (in order of discovery) and then by level number.
2170      */
2171     mapseen *mptr, *init, *prev;
2172
2173     init = (mapseen *) alloc(sizeof *init);
2174     (void) memset((genericptr_t) init, 0, sizeof *init);
2175     /* memset is fine for feature bits, flags, and rooms array;
2176        explicitly initialize pointers to null */
2177     init->next = 0, init->br = 0, init->custom = 0;
2178     init->final_resting_place = 0;
2179     /* lastseentyp[][] is reused for each level, so get rid of
2180        previous level's data */
2181     (void) memset((genericptr_t) lastseentyp, 0, sizeof lastseentyp);
2182
2183     init->lev.dnum = lev->dnum;
2184     init->lev.dlevel = lev->dlevel;
2185
2186     /* walk until we get to the place where we should insert init */
2187     for (mptr = mapseenchn, prev = 0; mptr; prev = mptr, mptr = mptr->next)
2188         if (mptr->lev.dnum > init->lev.dnum
2189             || (mptr->lev.dnum == init->lev.dnum
2190                 && mptr->lev.dlevel > init->lev.dlevel))
2191             break;
2192     if (!prev) {
2193         init->next = mapseenchn;
2194         mapseenchn = init;
2195     } else {
2196         mptr = prev->next;
2197         prev->next = init;
2198         init->next = mptr;
2199     }
2200 }
2201
2202 #define INTEREST(feat)                                                \
2203     ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2204      || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2205   /* || (feat).water || (feat).ice || (feat).lava */
2206
2207 /* returns true if this level has something interesting to print out */
2208 STATIC_OVL boolean
2209 interest_mapseen(mptr)
2210 mapseen *mptr;
2211 {
2212     if (on_level(&u.uz, &mptr->lev))
2213         return TRUE;
2214     if (mptr->flags.unreachable || mptr->flags.forgot)
2215         return FALSE;
2216     /* level is of interest if it has an auto-generated annotation */
2217     if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
2218         || mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
2219         || mptr->flags.quest_summons || mptr->flags.questing)
2220         return TRUE;
2221     /* when in Sokoban, list all sokoban levels visited; when not in it,
2222        list any visited Sokoban level which remains unsolved (will usually
2223        only be furthest one reached, but it's possible to enter pits and
2224        climb out on the far side on the first Sokoban level; also, wizard
2225        mode overrides teleport restrictions) */
2226     if (In_sokoban(&mptr->lev)
2227         && (In_sokoban(&u.uz) || !mptr->flags.sokosolved))
2228         return TRUE;
2229     /* when in the endgame, list all endgame levels visited, whether they
2230        have annotations or not, so that #overview doesn't become extremely
2231        sparse once the rest of the dungeon has been flagged as unreachable */
2232     if (In_endgame(&u.uz))
2233         return (boolean) In_endgame(&mptr->lev);
2234     /* level is of interest if it has non-zero feature count or known bones
2235        or user annotation or known connection to another dungeon branch
2236        or is the furthest level reached in its branch */
2237     return (boolean) (INTEREST(mptr->feat)
2238                       || (mptr->final_resting_place
2239                           && (mptr->flags.knownbones || wizard))
2240                       || mptr->custom || mptr->br
2241                       || (mptr->lev.dlevel
2242                           == dungeons[mptr->lev.dnum].dunlev_ureached));
2243 }
2244
2245 /* recalculate mapseen for the current level */
2246 void
2247 recalc_mapseen()
2248 {
2249     mapseen *mptr;
2250     struct monst *mtmp;
2251     struct cemetery *bp, **bonesaddr;
2252     unsigned i, ridx;
2253     int x, y, ltyp, count, atmp;
2254
2255     /* Should not happen in general, but possible if in the process
2256      * of being booted from the quest.  The mapseen object gets
2257      * removed during the expulsion but prior to leaving the level
2258      * [Since quest expulsion no longer deletes quest mapseen data,
2259      * null return from find_mapseen() should now be impossible.]
2260      */
2261     if (!(mptr = find_mapseen(&u.uz)))
2262         return;
2263
2264     /* reset all features; mptr->feat.* = 0; */
2265     (void) memset((genericptr_t) &mptr->feat, 0, sizeof mptr->feat);
2266     /* reset most flags; some level-specific ones are left as-is */
2267     if (mptr->flags.unreachable) {
2268         mptr->flags.unreachable = 0; /* reached it; Eye of the Aethiopica? */
2269         if (In_quest(&u.uz)) {
2270             mapseen *mptrtmp = mapseenchn;
2271
2272             /* when quest was unreachable due to ejection and portal removal,
2273                getting back to it via arti-invoke should revive annotation
2274                data for all quest levels, not just the one we're on now */
2275             do {
2276                 if (mptrtmp->lev.dnum == mptr->lev.dnum)
2277                     mptrtmp->flags.unreachable = 0;
2278                 mptrtmp = mptrtmp->next;
2279             } while (mptrtmp);
2280         }
2281     }
2282     mptr->flags.knownbones = 0;
2283     mptr->flags.sokosolved = In_sokoban(&u.uz) && !Sokoban;
2284     /* mptr->flags.bigroom retains previous value when hero can't see */
2285     if (!Blind)
2286         mptr->flags.bigroom = Is_bigroom(&u.uz);
2287     else if (mptr->flags.forgot)
2288         mptr->flags.bigroom = 0;
2289     mptr->flags.roguelevel = Is_rogue_level(&u.uz);
2290     mptr->flags.oracle = 0; /* recalculated during room traversal below */
2291     mptr->flags.castletune = 0;
2292     /* flags.castle, flags.valley, flags.msanctum retain previous value */
2293     mptr->flags.forgot = 0;
2294     /* flags.quest_summons disabled once quest finished */
2295 /*JP
2296     mptr->flags.quest_summons = (at_dgn_entrance("The Quest")
2297 */
2298     mptr->flags.quest_summons = (at_dgn_entrance("\83N\83G\83X\83g")
2299                                  && u.uevent.qcalled
2300                                  && !(u.uevent.qcompleted
2301                                       || u.uevent.qexpelled
2302                                       || quest_status.leader_is_dead));
2303     mptr->flags.questing = (on_level(&u.uz, &qstart_level)
2304                             && quest_status.got_quest);
2305
2306     /* track rooms the hero is in */
2307     for (i = 0; i < SIZE(u.urooms); ++i) {
2308         if (!u.urooms[i])
2309             continue;
2310
2311         ridx = u.urooms[i] - ROOMOFFSET;
2312         mptr->msrooms[ridx].seen = 1;
2313         mptr->msrooms[ridx].untended =
2314             (rooms[ridx].rtype >= SHOPBASE)
2315                 ? (!(mtmp = shop_keeper(u.urooms[i])) || !inhishop(mtmp))
2316                 : (rooms[ridx].rtype == TEMPLE)
2317                       ? (!(mtmp = findpriest(u.urooms[i]))
2318                          || !inhistemple(mtmp))
2319                       : 0;
2320     }
2321
2322     /* recalculate room knowledge: for now, just shops and temples
2323      * this could be extended to an array of 0..SHOPBASE
2324      */
2325     for (i = 0; i < SIZE(mptr->msrooms); ++i) {
2326         if (mptr->msrooms[i].seen) {
2327             if (rooms[i].rtype >= SHOPBASE) {
2328                 if (mptr->msrooms[i].untended)
2329                     mptr->feat.shoptype = SHOPBASE - 1;
2330                 else if (!mptr->feat.nshop)
2331                     mptr->feat.shoptype = rooms[i].rtype;
2332                 else if (mptr->feat.shoptype != (unsigned) rooms[i].rtype)
2333                     mptr->feat.shoptype = 0;
2334                 count = mptr->feat.nshop + 1;
2335                 if (count <= 3)
2336                     mptr->feat.nshop = count;
2337             } else if (rooms[i].rtype == TEMPLE) {
2338                 /* altar and temple alignment handled below */
2339                 count = mptr->feat.ntemple + 1;
2340                 if (count <= 3)
2341                     mptr->feat.ntemple = count;
2342             } else if (rooms[i].orig_rtype == DELPHI) {
2343                 mptr->flags.oracle = 1;
2344             }
2345         }
2346     }
2347
2348     /* Update lastseentyp with typ if and only if it is in sight or the
2349      * hero can feel it on their current location (i.e. not levitating).
2350      * This *should* give the "last known typ" for each dungeon location.
2351      * (At the very least, it's a better assumption than determining what
2352      * the player knows from the glyph and the typ (which is isn't quite
2353      * enough information in some cases)).
2354      *
2355      * It was reluctantly added to struct rm to track.  Alternatively
2356      * we could track "features" and then update them all here, and keep
2357      * track of when new features are created or destroyed, but this
2358      * seemed the most elegant, despite adding more data to struct rm.
2359      * [3.6.0: we're using lastseentyp[][] rather than level.locations
2360      * to track the features seen.]
2361      *
2362      * Although no current windowing systems (can) do this, this would add
2363      * the ability to have non-dungeon glyphs float above the last known
2364      * dungeon glyph (i.e. items on fountains).
2365      */
2366     for (x = 1; x < COLNO; x++) {
2367         for (y = 0; y < ROWNO; y++) {
2368             if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
2369                 ltyp = levl[x][y].typ;
2370                 if (ltyp == DRAWBRIDGE_UP)
2371                     ltyp = db_under_typ(levl[x][y].drawbridgemask);
2372                 if ((mtmp = m_at(x, y)) != 0
2373                     && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
2374                     ltyp = cmap_to_type(mtmp->mappearance);
2375                 lastseentyp[x][y] = ltyp;
2376             }
2377
2378             switch (lastseentyp[x][y]) {
2379 #if 0
2380             case ICE:
2381                 count = mptr->feat.ice + 1;
2382                 if (count <= 3)
2383                     mptr->feat.ice = count;
2384                 break;
2385             case POOL:
2386             case MOAT:
2387             case WATER:
2388                 count = mptr->feat.water + 1;
2389                 if (count <= 3)
2390                     mptr->feat.water = count;
2391                 break;
2392             case LAVAPOOL:
2393                 count = mptr->feat.lava + 1;
2394                 if (count <= 3)
2395                     mptr->feat.lava = count;
2396                 break;
2397 #endif
2398             case TREE:
2399                 count = mptr->feat.ntree + 1;
2400                 if (count <= 3)
2401                     mptr->feat.ntree = count;
2402                 break;
2403             case FOUNTAIN:
2404                 count = mptr->feat.nfount + 1;
2405                 if (count <= 3)
2406                     mptr->feat.nfount = count;
2407                 break;
2408             case THRONE:
2409                 count = mptr->feat.nthrone + 1;
2410                 if (count <= 3)
2411                     mptr->feat.nthrone = count;
2412                 break;
2413             case SINK:
2414                 count = mptr->feat.nsink + 1;
2415                 if (count <= 3)
2416                     mptr->feat.nsink = count;
2417                 break;
2418             case GRAVE:
2419                 count = mptr->feat.ngrave + 1;
2420                 if (count <= 3)
2421                     mptr->feat.ngrave = count;
2422                 break;
2423             case ALTAR:
2424                 atmp = (Is_astralevel(&u.uz)
2425                         && (levl[x][y].seenv & SVALL) != SVALL)
2426                          ? MSA_NONE
2427                          : Amask2msa(levl[x][y].altarmask);
2428                 if (!mptr->feat.naltar)
2429                     mptr->feat.msalign = atmp;
2430                 else if (mptr->feat.msalign != atmp)
2431                     mptr->feat.msalign = MSA_NONE;
2432                 count = mptr->feat.naltar + 1;
2433                 if (count <= 3)
2434                     mptr->feat.naltar = count;
2435                 break;
2436             /*  An automatic annotation is added to the Castle and
2437              *  to Fort Ludios once their structure's main entrance
2438              *  has been seen (in person or via magic mapping).
2439              * DOOR: possibly a lowered drawbridge's open portcullis;
2440              * DBWALL: a raised drawbridge's "closed door";
2441              * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2442              *  with moat or other terrain hidden underneath;
2443              * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2444              *  not recognizable as a bridge location unless/until
2445              *  the adjacent DBWALL has been seen.
2446              */
2447             case DOOR:
2448                 if (is_drawbridge_wall(x, y) < 0)
2449                     break;
2450             /* else FALLTHRU */
2451             case DBWALL:
2452             case DRAWBRIDGE_DOWN:
2453                 if (Is_stronghold(&u.uz))
2454                     mptr->flags.castle = 1, mptr->flags.castletune = 1;
2455                 else if (Is_knox(&u.uz))
2456                     mptr->flags.ludios = 1;
2457                 break;
2458             default:
2459                 break;
2460             }
2461         }
2462     }
2463
2464     if (level.bonesinfo && !mptr->final_resting_place) {
2465         /* clone the bonesinfo so we aren't dependent upon this
2466            level being in memory */
2467         bonesaddr = &mptr->final_resting_place;
2468         bp = level.bonesinfo;
2469         do {
2470             *bonesaddr = (struct cemetery *) alloc(sizeof **bonesaddr);
2471             **bonesaddr = *bp;
2472             bp = bp->next;
2473             bonesaddr = &(*bonesaddr)->next;
2474         } while (bp);
2475         *bonesaddr = 0;
2476     }
2477     /* decide which past hero deaths have become known; there's no
2478        guarantee of either a grave or a ghost, so we go by whether the
2479        current hero has seen the map location where each old one died */
2480     for (bp = mptr->final_resting_place; bp; bp = bp->next)
2481         if (lastseentyp[bp->frpx][bp->frpy]) {
2482             bp->bonesknown = TRUE;
2483             mptr->flags.knownbones = 1;
2484         }
2485 }
2486
2487 /*ARGUSED*/
2488 /* valley and sanctum levels get automatic annotation once temple is entered
2489  */
2490 void
2491 mapseen_temple(priest)
2492 struct monst *priest UNUSED; /* currently unused; might be useful someday */
2493 {
2494     mapseen *mptr = find_mapseen(&u.uz);
2495
2496     if (Is_valley(&u.uz))
2497         mptr->flags.valley = 1;
2498     else if (Is_sanctum(&u.uz))
2499         mptr->flags.msanctum = 1;
2500 }
2501
2502 /* room entry message has just been delivered so learn room even if blind */
2503 void
2504 room_discovered(roomno)
2505 int roomno;
2506 {
2507     mapseen *mptr = find_mapseen(&u.uz);
2508
2509     mptr->msrooms[roomno].seen = 1;
2510 }
2511
2512 /* #overview command */
2513 int
2514 dooverview()
2515 {
2516     show_overview(0, 0);
2517     return 0;
2518 }
2519
2520 /* called for #overview or for end of game disclosure */
2521 void
2522 show_overview(why, reason)
2523 int why;    /* 0 => #overview command,
2524                1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2525 int reason; /* how hero died; used when disclosing end-of-game level */
2526 {
2527     winid win;
2528     int lastdun = -1;
2529
2530     /* lazy initialization */
2531     (void) recalc_mapseen();
2532
2533     win = create_nhwindow(NHW_MENU);
2534     /* show the endgame levels before the rest of the dungeon,
2535        so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2536     if (In_endgame(&u.uz))
2537         traverse_mapseenchn(TRUE, win, why, reason, &lastdun);
2538     /* if game is over or we're not in the endgame yet, show the dungeon */
2539     if (why > 0 || !In_endgame(&u.uz))
2540         traverse_mapseenchn(FALSE, win, why, reason, &lastdun);
2541     display_nhwindow(win, TRUE);
2542     destroy_nhwindow(win);
2543 }
2544
2545 /* display endgame levels or non-endgame levels, not both */
2546 STATIC_OVL void
2547 traverse_mapseenchn(viewendgame, win, why, reason, lastdun_p)
2548 boolean viewendgame;
2549 winid win;
2550 int why, reason, *lastdun_p;
2551 {
2552     mapseen *mptr;
2553     boolean showheader;
2554
2555     for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2556         if (viewendgame ^ In_endgame(&mptr->lev))
2557             continue;
2558
2559         /* only print out info for a level or a dungeon if interest */
2560         if (why > 0 || interest_mapseen(mptr)) {
2561             showheader = (boolean) (mptr->lev.dnum != *lastdun_p);
2562             print_mapseen(win, mptr, why, reason, showheader);
2563             *lastdun_p = mptr->lev.dnum;
2564         }
2565     }
2566 }
2567
2568 STATIC_OVL const char *
2569 seen_string(x, obj)
2570 xchar x;
2571 const char *obj;
2572 {
2573     /* players are computer scientists: 0, 1, 2, n */
2574     switch (x) {
2575     case 0:
2576         return "no";
2577     /* an() returns too much.  index is ok in this case */
2578     case 1:
2579         return index(vowels, *obj) ? "an" : "a";
2580     case 2:
2581         return "some";
2582     case 3:
2583         return "many";
2584     }
2585
2586     return "(unknown)";
2587 }
2588
2589 /* better br_string */
2590 STATIC_OVL const char *
2591 br_string2(br)
2592 branch *br;
2593 {
2594     /* Special case: quest portal says closed if kicked from quest */
2595     boolean closed_portal = (br->end2.dnum == quest_dnum
2596                              && u.uevent.qexpelled);
2597
2598     switch (br->type) {
2599     case BR_PORTAL:
2600         return closed_portal ? "Sealed portal" : "Portal";
2601     case BR_NO_END1:
2602         return "Connection";
2603     case BR_NO_END2:
2604         return br->end1_up ? "One way stairs up" : "One way stairs down";
2605     case BR_STAIR:
2606         return br->end1_up ? "Stairs up" : "Stairs down";
2607     }
2608
2609     return "(unknown)";
2610 }
2611
2612 /* get the name of an endgame level; topten.c does something similar */
2613 STATIC_OVL const char *
2614 endgamelevelname(outbuf, indx)
2615 char *outbuf;
2616 int indx;
2617 {
2618     const char *planename = 0;
2619
2620     *outbuf = '\0';
2621     switch (indx) {
2622     case -5:
2623         Strcpy(outbuf, "Astral Plane");
2624         break;
2625     case -4:
2626         planename = "Water";
2627         break;
2628     case -3:
2629         planename = "Fire";
2630         break;
2631     case -2:
2632         planename = "Air";
2633         break;
2634     case -1:
2635         planename = "Earth";
2636         break;
2637     }
2638     if (planename)
2639         Sprintf(outbuf, "Plane of %s", planename);
2640     else if (!*outbuf)
2641         Sprintf(outbuf, "unknown plane #%d", indx);
2642     return outbuf;
2643 }
2644
2645 STATIC_OVL const char *
2646 shop_string(rtype)
2647 int rtype;
2648 {
2649     const char *str = "shop"; /* catchall */
2650
2651     /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2652     switch (rtype) {
2653     case SHOPBASE - 1:
2654         str = "untended shop";
2655         break; /* see recalc_mapseen */
2656     case SHOPBASE:
2657         str = "general store";
2658         break;
2659     case ARMORSHOP:
2660         str = "armor shop";
2661         break;
2662     case SCROLLSHOP:
2663         str = "scroll shop";
2664         break;
2665     case POTIONSHOP:
2666         str = "potion shop";
2667         break;
2668     case WEAPONSHOP:
2669         str = "weapon shop";
2670         break;
2671     case FOODSHOP:
2672         str = "delicatessen";
2673         break;
2674     case RINGSHOP:
2675         str = "jewelers";
2676         break;
2677     case WANDSHOP:
2678         str = "wand shop";
2679         break;
2680     case BOOKSHOP:
2681         str = "bookstore";
2682         break;
2683     case FODDERSHOP:
2684         str = "health food store";
2685         break;
2686     case CANDLESHOP:
2687         str = "lighting shop";
2688         break;
2689     default:
2690         break;
2691     }
2692     return str;
2693 }
2694
2695 /* if player knows about the mastermind tune, append it to Castle annotation;
2696    if drawbridge has been destroyed, flags.castletune will be zero */
2697 STATIC_OVL char *
2698 tunesuffix(mptr, outbuf)
2699 mapseen *mptr;
2700 char *outbuf;
2701 {
2702     *outbuf = '\0';
2703     if (mptr->flags.castletune && u.uevent.uheard_tune) {
2704         char tmp[BUFSZ];
2705
2706         if (u.uevent.uheard_tune == 2)
2707             Sprintf(tmp, "notes \"%s\"", tune);
2708         else
2709             Strcpy(tmp, "5-note tune");
2710         Sprintf(outbuf, " (play %s to open or close drawbridge)", tmp);
2711     }
2712     return outbuf;
2713 }
2714
2715 /* some utility macros for print_mapseen */
2716 #define TAB "   " /* three spaces */
2717 #if 0
2718 #define BULLET "" /* empty; otherwise output becomes cluttered */
2719 #define PREFIX TAB TAB BULLET
2720 #else                   /*!0*/
2721 /* K&R: don't require support for concatenation of adjacent string literals */
2722 #define PREFIX "      " /* two TABs + empty BULLET: six spaces */
2723 #endif
2724 #define COMMA (i++ > 0 ? ", " : PREFIX)
2725 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2726 #define ADDNTOBUF(nam, var)                                                  \
2727     do {                                                                     \
2728         if (var)                                                             \
2729             Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2730                     (nam), plur(var));                                       \
2731     } while (0)
2732 #define ADDTOBUF(nam, var)                           \
2733     do {                                             \
2734         if (var)                                     \
2735             Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
2736     } while (0)
2737
2738 STATIC_OVL void
2739 print_mapseen(win, mptr, final, how, printdun)
2740 winid win;
2741 mapseen *mptr;
2742 int final; /* 0: not final; 1: game over, alive; 2: game over, dead */
2743 int how;   /* cause of death; only used if final==2 and mptr->lev==u.uz */
2744 boolean printdun;
2745 {
2746     char buf[BUFSZ], tmpbuf[BUFSZ];
2747     int i, depthstart, dnum;
2748     boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
2749
2750     /* Damnable special cases */
2751     /* The quest and knox should appear to be level 1 to match
2752      * other text.
2753      */
2754     dnum = mptr->lev.dnum;
2755     if (dnum == quest_dnum || dnum == knox_level.dnum)
2756         depthstart = 1;
2757     else
2758         depthstart = dungeons[dnum].depth_start;
2759
2760     if (printdun) {
2761         if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
2762             /* suppress the negative numbers in the endgame */
2763             || In_endgame(&mptr->lev))
2764             Sprintf(buf, "%s:", dungeons[dnum].dname);
2765         else if (builds_up(&mptr->lev))
2766             Sprintf(buf, "%s: levels %d up to %d",
2767                     dungeons[dnum].dname,
2768                     depthstart + dungeons[dnum].entry_lev - 1,
2769                     depthstart + dungeons[dnum].dunlev_ureached - 1);
2770         else
2771             Sprintf(buf, "%s: levels %d to %d",
2772                     dungeons[dnum].dname, depthstart,
2773                     depthstart + dungeons[dnum].dunlev_ureached - 1);
2774         putstr(win, !final ? ATR_INVERSE : 0, buf);
2775     }
2776
2777     /* calculate level number */
2778     i = depthstart + mptr->lev.dlevel - 1;
2779     if (In_endgame(&mptr->lev))
2780         Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
2781     else
2782         /* FIXME: when this branch has only one level (Ft.Ludios),
2783          * listing "Level 1:" for it might confuse inexperienced
2784          * players into thinking there's more than one.
2785          */
2786         Sprintf(buf, "%sLevel %d:", TAB, i);
2787
2788     /* wizmode prints out proto dungeon names for clarity */
2789     if (wizard) {
2790         s_level *slev;
2791
2792         if ((slev = Is_special(&mptr->lev)) != 0)
2793             Sprintf(eos(buf), " [%s]", slev->proto);
2794     }
2795     /* [perhaps print custom annotation on its own line when it's long] */
2796     if (mptr->custom)
2797         Sprintf(eos(buf), " (%s)", mptr->custom);
2798     if (on_level(&u.uz, &mptr->lev))
2799         Sprintf(eos(buf), " <- You %s here.",
2800                 (!final || (final == 1 && how == ASCENDED)) ? "are" : "were");
2801     putstr(win, !final ? ATR_BOLD : 0, buf);
2802
2803     if (mptr->flags.forgot)
2804         return;
2805
2806     if (INTEREST(mptr->feat)) {
2807         buf[0] = 0;
2808
2809         i = 0; /* interest counter */
2810         /* List interests in an order vaguely corresponding to
2811          * how important they are.
2812          */
2813         if (mptr->feat.nshop > 0) {
2814             if (mptr->feat.nshop > 1)
2815                 ADDNTOBUF("shop", mptr->feat.nshop);
2816             else
2817                 Sprintf(eos(buf), "%s%s", COMMA,
2818                         an(shop_string(mptr->feat.shoptype)));
2819         }
2820         if (mptr->feat.naltar > 0) {
2821             /* Temples + non-temple altars get munged into just "altars" */
2822             if (mptr->feat.ntemple != mptr->feat.naltar)
2823                 ADDNTOBUF("altar", mptr->feat.naltar);
2824             else
2825                 ADDNTOBUF("temple", mptr->feat.ntemple);
2826
2827             /* only print out altar's god if they are all to your god */
2828             if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
2829                 Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
2830         }
2831         ADDNTOBUF("throne", mptr->feat.nthrone);
2832         ADDNTOBUF("fountain", mptr->feat.nfount);
2833         ADDNTOBUF("sink", mptr->feat.nsink);
2834         ADDNTOBUF("grave", mptr->feat.ngrave);
2835         ADDNTOBUF("tree", mptr->feat.ntree);
2836 #if 0
2837         ADDTOBUF("water", mptr->feat.water);
2838         ADDTOBUF("lava", mptr->feat.lava);
2839         ADDTOBUF("ice", mptr->feat.ice);
2840 #endif
2841         /* capitalize afterwards */
2842         i = strlen(PREFIX);
2843         buf[i] = highc(buf[i]);
2844         /* capitalizing it makes it a sentence; terminate with '.' */
2845         Strcat(buf, ".");
2846         putstr(win, 0, buf);
2847     }
2848
2849     /* we assume that these are mutually exclusive */
2850     *buf = '\0';
2851     if (mptr->flags.oracle) {
2852         Sprintf(buf, "%sOracle of Delphi.", PREFIX);
2853     } else if (In_sokoban(&mptr->lev)) {
2854         Sprintf(buf, "%s%s.", PREFIX,
2855                 mptr->flags.sokosolved ? "Solved" : "Unsolved");
2856     } else if (mptr->flags.bigroom) {
2857         Sprintf(buf, "%sA very big room.", PREFIX);
2858     } else if (mptr->flags.roguelevel) {
2859         Sprintf(buf, "%sA primitive area.", PREFIX);
2860     } else if (mptr->flags.quest_summons) {
2861         Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
2862     } else if (on_level(&mptr->lev, &qstart_level)) {
2863         Sprintf(buf, "%sHome%s.", PREFIX,
2864                 mptr->flags.unreachable ? " (no way back...)" : "");
2865         if (u.uevent.qcompleted)
2866             Sprintf(buf, "%sCompleted quest for %s.", PREFIX, ldrname());
2867         else if (mptr->flags.questing)
2868             Sprintf(buf, "%sGiven quest by %s.", PREFIX, ldrname());
2869     } else if (mptr->flags.ludios) {
2870         /* presence of the ludios branch in #overview output indicates that
2871            the player has made it onto the level; presence of this annotation
2872            indicates that the fort's entrance has been seen (or mapped) */
2873         Sprintf(buf, "%sFort Ludios.", PREFIX);
2874     } else if (mptr->flags.castle) {
2875         Sprintf(buf, "%sThe castle%s.", PREFIX, tunesuffix(mptr, tmpbuf));
2876     } else if (mptr->flags.valley) {
2877         Sprintf(buf, "%sValley of the Dead.", PREFIX);
2878     } else if (mptr->flags.msanctum) {
2879         Sprintf(buf, "%sMoloch's Sanctum.", PREFIX);
2880     }
2881     if (*buf)
2882         putstr(win, 0, buf);
2883
2884     /* print out branches */
2885     if (mptr->br) {
2886         Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br),
2887                 dungeons[mptr->br->end2.dnum].dname);
2888
2889         /* Since mapseen objects are printed out in increasing order
2890          * of dlevel, clarify which level this branch is going to
2891          * if the branch goes upwards.  Unless it's the end game.
2892          */
2893         if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
2894             Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
2895         Strcat(buf, ".");
2896         putstr(win, 0, buf);
2897     }
2898
2899     /* maybe print out bones details */
2900     if (mptr->final_resting_place || final) {
2901         struct cemetery *bp;
2902         int kncnt = !died_here ? 0 : 1;
2903
2904         for (bp = mptr->final_resting_place; bp; bp = bp->next)
2905             if (bp->bonesknown || wizard || final)
2906                 ++kncnt;
2907         if (kncnt) {
2908             Sprintf(buf, "%s%s", PREFIX, "Final resting place for");
2909             putstr(win, 0, buf);
2910             if (died_here) {
2911                 /* disclosure occurs before bones creation, so listing dead
2912                    hero here doesn't give away whether bones are produced */
2913                 formatkiller(tmpbuf, sizeof tmpbuf, how);
2914                 /* rephrase a few death reasons to work with "you" */
2915                 (void) strsubst(tmpbuf, " himself", " yourself");
2916                 (void) strsubst(tmpbuf, " herself", " yourself");
2917                 (void) strsubst(tmpbuf, " his ", " your ");
2918                 (void) strsubst(tmpbuf, " her ", " your ");
2919                 Sprintf(buf, "%s%syou, %s%c", PREFIX, TAB, tmpbuf,
2920                         --kncnt ? ',' : '.');
2921                 putstr(win, 0, buf);
2922             }
2923             for (bp = mptr->final_resting_place; bp; bp = bp->next) {
2924                 if (bp->bonesknown || wizard || final) {
2925                     Sprintf(buf, "%s%s%s, %s%c", PREFIX, TAB, bp->who,
2926                             bp->how, --kncnt ? ',' : '.');
2927                     putstr(win, 0, buf);
2928                 }
2929             }
2930         }
2931     }
2932 }
2933
2934 /*dungeon.c*/