OSDN Git Service

import nethack-3.6.0
[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     quest_dnum = dname_to_dnum("The Quest");
952     sokoban_dnum = dname_to_dnum("Sokoban");
953     mines_dnum = dname_to_dnum("The Gnomish Mines");
954     tower_dnum = dname_to_dnum("Vlad's Tower");
955
956     /* one special fixup for dummy surface level */
957     if ((x = find_level("dummy")) != 0) {
958         i = x->dlevel.dnum;
959         /* the code above puts earth one level above dungeon level #1,
960            making the dummy level overlay level 1; but the whole reason
961            for having the dummy level is to make earth have depth -1
962            instead of 0, so adjust the start point to shift endgame up */
963         if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
964             dungeons[i].depth_start -= 1;
965         /* TO DO: strip "dummy" out all the way here,
966            so that it's hidden from <ctrl/O> feedback. */
967     }
968
969 #ifdef DEBUG
970     dumpit();
971 #endif
972 }
973
974 /* return the level number for lev in *this* dungeon */
975 xchar
976 dunlev(lev)
977 d_level *lev;
978 {
979     return lev->dlevel;
980 }
981
982 /* return the lowest level number for *this* dungeon */
983 xchar
984 dunlevs_in_dungeon(lev)
985 d_level *lev;
986 {
987     return dungeons[lev->dnum].num_dunlevs;
988 }
989
990 /* return the lowest level explored in the game*/
991 xchar
992 deepest_lev_reached(noquest)
993 boolean noquest;
994 {
995     /* this function is used for three purposes: to provide a factor
996      * of difficulty in monster generation; to provide a factor of
997      * difficulty in experience calculations (botl.c and end.c); and
998      * to insert the deepest level reached in the game in the topten
999      * display.  the 'noquest' arg switch is required for the latter.
1000      *
1001      * from the player's point of view, going into the Quest is _not_
1002      * going deeper into the dungeon -- it is going back "home", where
1003      * the dungeon starts at level 1.  given the setup in dungeon.def,
1004      * the depth of the Quest (thought of as starting at level 1) is
1005      * never lower than the level of entry into the Quest, so we exclude
1006      * the Quest from the topten "deepest level reached" display
1007      * calculation.  _However_ the Quest is a difficult dungeon, so we
1008      * include it in the factor of difficulty calculations.
1009      */
1010     register int i;
1011     d_level tmp;
1012     register schar ret = 0;
1013
1014     for (i = 0; i < n_dgns; i++) {
1015         if (noquest && i == quest_dnum)
1016             continue;
1017         tmp.dlevel = dungeons[i].dunlev_ureached;
1018         if (tmp.dlevel == 0)
1019             continue;
1020         tmp.dnum = i;
1021         if (depth(&tmp) > ret)
1022             ret = depth(&tmp);
1023     }
1024     return (xchar) ret;
1025 }
1026
1027 /* return a bookkeeping level number for purpose of comparisons and
1028    save/restore */
1029 xchar
1030 ledger_no(lev)
1031 d_level *lev;
1032 {
1033     return (xchar) (lev->dlevel + dungeons[lev->dnum].ledger_start);
1034 }
1035
1036 /*
1037  * The last level in the bookkeeping list of level is the bottom of the last
1038  * dungeon in the dungeons[] array.
1039  *
1040  * Maxledgerno() -- which is the max number of levels in the bookkeeping
1041  * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1042  * returns the max number of levels in lev's dungeon, and both should
1043  * not be confused with deepest_lev_reached() -- which returns the lowest
1044  * depth visited by the player.
1045  */
1046 xchar
1047 maxledgerno()
1048 {
1049     return (xchar) (dungeons[n_dgns - 1].ledger_start
1050                     + dungeons[n_dgns - 1].num_dunlevs);
1051 }
1052
1053 /* return the dungeon that this ledgerno exists in */
1054 xchar
1055 ledger_to_dnum(ledgerno)
1056 xchar ledgerno;
1057 {
1058     register int i;
1059
1060     /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1061     for (i = 0; i < n_dgns; i++)
1062         if (dungeons[i].ledger_start < ledgerno
1063             && ledgerno <= dungeons[i].ledger_start + dungeons[i].num_dunlevs)
1064             return (xchar) i;
1065
1066     panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno);
1067     /*NOT REACHED*/
1068     return (xchar) 0;
1069 }
1070
1071 /* return the level of the dungeon this ledgerno exists in */
1072 xchar
1073 ledger_to_dlev(ledgerno)
1074 xchar ledgerno;
1075 {
1076     return (xchar) (ledgerno
1077                     - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
1078 }
1079
1080 /* returns the depth of a level, in floors below the surface
1081    (note levels in different dungeons can have the same depth) */
1082 schar
1083 depth(lev)
1084 d_level *lev;
1085 {
1086     return (schar) (dungeons[lev->dnum].depth_start + lev->dlevel - 1);
1087 }
1088
1089 /* are "lev1" and "lev2" actually the same? */
1090 boolean
1091 on_level(lev1, lev2)
1092 d_level *lev1, *lev2;
1093 {
1094     return (boolean) (lev1->dnum == lev2->dnum
1095                       && lev1->dlevel == lev2->dlevel);
1096 }
1097
1098 /* is this level referenced in the special level chain? */
1099 s_level *
1100 Is_special(lev)
1101 d_level *lev;
1102 {
1103     s_level *levtmp;
1104
1105     for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
1106         if (on_level(lev, &levtmp->dlevel))
1107             return levtmp;
1108
1109     return (s_level *) 0;
1110 }
1111
1112 /*
1113  * Is this a multi-dungeon branch level?  If so, return a pointer to the
1114  * branch.  Otherwise, return null.
1115  */
1116 branch *
1117 Is_branchlev(lev)
1118 d_level *lev;
1119 {
1120     branch *curr;
1121
1122     for (curr = branches; curr; curr = curr->next) {
1123         if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
1124             return curr;
1125     }
1126     return (branch *) 0;
1127 }
1128
1129 /* returns True iff the branch 'lev' is in a branch which builds up */
1130 boolean
1131 builds_up(lev)
1132 d_level *lev;
1133 {
1134     dungeon *dptr = &dungeons[lev->dnum];
1135     /*
1136      * FIXME:  this misclassifies a single level branch reached via stairs
1137      * from below.  Saving grace is that no such branches currently exist.
1138      */
1139     return (boolean) (dptr->num_dunlevs > 1
1140                       && dptr->entry_lev == dptr->num_dunlevs);
1141 }
1142
1143 /* goto the next level (or appropriate dungeon) */
1144 void
1145 next_level(at_stairs)
1146 boolean at_stairs;
1147 {
1148     if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1149         /* Taking a down dungeon branch. */
1150         goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1151     } else {
1152         /* Going down a stairs or jump in a trap door. */
1153         d_level newlevel;
1154
1155         newlevel.dnum = u.uz.dnum;
1156         newlevel.dlevel = u.uz.dlevel + 1;
1157         goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
1158     }
1159 }
1160
1161 /* goto the previous level (or appropriate dungeon) */
1162 void
1163 prev_level(at_stairs)
1164 boolean at_stairs;
1165 {
1166     if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1167         /* Taking an up dungeon branch. */
1168         /* KMH -- Upwards branches are okay if not level 1 */
1169         /* (Just make sure it doesn't go above depth 1) */
1170         if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
1171             done(ESCAPED);
1172         else
1173             goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1174     } else {
1175         /* Going up a stairs or rising through the ceiling. */
1176         d_level newlevel;
1177         newlevel.dnum = u.uz.dnum;
1178         newlevel.dlevel = u.uz.dlevel - 1;
1179         goto_level(&newlevel, at_stairs, FALSE, FALSE);
1180     }
1181 }
1182
1183 void
1184 u_on_newpos(x, y)
1185 int x, y;
1186 {
1187     u.ux = x;
1188     u.uy = y;
1189 #ifdef CLIPPING
1190     cliparound(u.ux, u.uy);
1191 #endif
1192     /* ridden steed always shares hero's location */
1193     if (u.usteed)
1194         u.usteed->mx = u.ux, u.usteed->my = u.uy;
1195     /* when changing levels, don't leave old position set with
1196        stale values from previous level */
1197     if (!on_level(&u.uz, &u.uz0))
1198         u.ux0 = u.ux, u.uy0 = u.uy;
1199 }
1200
1201 /* place you on a random location */
1202 void
1203 u_on_rndspot(upflag)
1204 int upflag;
1205 {
1206     int up = (upflag & 1), was_in_W_tower = (upflag & 2);
1207
1208     /*
1209      * Place the hero at a random location within the relevant region.
1210      * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1211      * Unspecified region (.lx == 0) defaults to entire level.
1212      */
1213     if (was_in_W_tower && On_W_tower_level(&u.uz))
1214         /* Stay inside the Wizard's tower when feasible.
1215            We use the W Tower's exclusion region for the
1216            destination instead of its enclosing region.
1217            Note: up vs down doesn't matter in this case
1218            because both specify the same exclusion area. */
1219         place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy, 0, 0, 0,
1220                       0, LR_DOWNTELE, (d_level *) 0);
1221     else if (up)
1222         place_lregion(updest.lx, updest.ly, updest.hx, updest.hy, updest.nlx,
1223                       updest.nly, updest.nhx, updest.nhy, LR_UPTELE,
1224                       (d_level *) 0);
1225     else
1226         place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy, dndest.nlx,
1227                       dndest.nly, dndest.nhx, dndest.nhy, LR_DOWNTELE,
1228                       (d_level *) 0);
1229 }
1230
1231 /* place you on the special staircase */
1232 void
1233 u_on_sstairs(upflag)
1234 int upflag;
1235 {
1236     if (sstairs.sx)
1237         u_on_newpos(sstairs.sx, sstairs.sy);
1238     else
1239         u_on_rndspot(upflag);
1240 }
1241
1242 /* place you on upstairs (or special equivalent) */
1243 void
1244 u_on_upstairs()
1245 {
1246     if (xupstair)
1247         u_on_newpos(xupstair, yupstair);
1248     else
1249         u_on_sstairs(0); /* destination upstairs implies moving down */
1250 }
1251
1252 /* place you on dnstairs (or special equivalent) */
1253 void
1254 u_on_dnstairs()
1255 {
1256     if (xdnstair)
1257         u_on_newpos(xdnstair, ydnstair);
1258     else
1259         u_on_sstairs(1); /* destination dnstairs implies moving up */
1260 }
1261
1262 boolean
1263 On_stairs(x, y)
1264 xchar x, y;
1265 {
1266     return (boolean) ((x == xupstair && y == yupstair)
1267                       || (x == xdnstair && y == ydnstair)
1268                       || (x == xdnladder && y == ydnladder)
1269                       || (x == xupladder && y == yupladder)
1270                       || (x == sstairs.sx && y == sstairs.sy));
1271 }
1272
1273 boolean
1274 Is_botlevel(lev)
1275 d_level *lev;
1276 {
1277     return (boolean) (lev->dlevel == dungeons[lev->dnum].num_dunlevs);
1278 }
1279
1280 boolean
1281 Can_dig_down(lev)
1282 d_level *lev;
1283 {
1284     return (boolean) (!level.flags.hardfloor
1285                       && !Is_botlevel(lev)
1286                       && !Invocation_lev(lev));
1287 }
1288
1289 /*
1290  * Like Can_dig_down (above), but also allows falling through on the
1291  * stronghold level.  Normally, the bottom level of a dungeon resists
1292  * both digging and falling.
1293  */
1294 boolean
1295 Can_fall_thru(lev)
1296 d_level *lev;
1297 {
1298     return (boolean) (Can_dig_down(lev) || Is_stronghold(lev));
1299 }
1300
1301 /*
1302  * True if one can rise up a level (e.g. cursed gain level).
1303  * This happens on intermediate dungeon levels or on any top dungeon
1304  * level that has a stairwell style branch to the next higher dungeon.
1305  * Checks for amulets and such must be done elsewhere.
1306  */
1307 boolean
1308 Can_rise_up(x, y, lev)
1309 int x, y;
1310 d_level *lev;
1311 {
1312     /* can't rise up from inside the top of the Wizard's tower */
1313     /* KMH -- or in sokoban */
1314     if (In_endgame(lev) || In_sokoban(lev)
1315         || (Is_wiz1_level(lev) && In_W_tower(x, y, lev)))
1316         return FALSE;
1317     return (boolean) (lev->dlevel > 1
1318                       || (dungeons[lev->dnum].entry_lev == 1
1319                           && ledger_no(lev) != 1
1320                           && sstairs.sx && sstairs.up));
1321 }
1322
1323 boolean
1324 has_ceiling(lev)
1325 d_level *lev;
1326 {
1327     /* [what about level 1 of the quest?] */
1328     return (boolean) (!Is_airlevel(lev) && !Is_waterlevel(lev));
1329 }
1330
1331 /*
1332  * It is expected that the second argument of get_level is a depth value,
1333  * either supplied by the user (teleport control) or randomly generated.
1334  * But more than one level can be at the same depth.  If the target level
1335  * is "above" the present depth location, get_level must trace "up" from
1336  * the player's location (through the ancestors dungeons) the dungeon
1337  * within which the target level is located.  With only one exception
1338  * which does not pass through this routine (see level_tele), teleporting
1339  * "down" is confined to the current dungeon.  At present, level teleport
1340  * in dungeons that build up is confined within them.
1341  */
1342 void
1343 get_level(newlevel, levnum)
1344 d_level *newlevel;
1345 int levnum;
1346 {
1347     branch *br;
1348     xchar dgn = u.uz.dnum;
1349
1350     if (levnum <= 0) {
1351         /* can only currently happen in endgame */
1352         levnum = u.uz.dlevel;
1353     } else if (levnum
1354                > dungeons[dgn].depth_start + dungeons[dgn].num_dunlevs - 1) {
1355         /* beyond end of dungeon, jump to last level */
1356         levnum = dungeons[dgn].num_dunlevs;
1357     } else {
1358         /* The desired level is in this dungeon or a "higher" one. */
1359
1360         /*
1361          * Branch up the tree until we reach a dungeon that contains the
1362          * levnum.
1363          */
1364         if (levnum < dungeons[dgn].depth_start) {
1365             do {
1366                 /*
1367                  * Find the parent dungeon of this dungeon.
1368                  *
1369                  * This assumes that end2 is always the "child" and it is
1370                  * unique.
1371                  */
1372                 for (br = branches; br; br = br->next)
1373                     if (br->end2.dnum == dgn)
1374                         break;
1375                 if (!br)
1376                     panic("get_level: can't find parent dungeon");
1377
1378                 dgn = br->end1.dnum;
1379             } while (levnum < dungeons[dgn].depth_start);
1380         }
1381
1382         /* We're within the same dungeon; calculate the level. */
1383         levnum = levnum - dungeons[dgn].depth_start + 1;
1384     }
1385
1386     newlevel->dnum = dgn;
1387     newlevel->dlevel = levnum;
1388 }
1389
1390 /* are you in the quest dungeon? */
1391 boolean
1392 In_quest(lev)
1393 d_level *lev;
1394 {
1395     return (boolean) (lev->dnum == quest_dnum);
1396 }
1397
1398 /* are you in the mines dungeon? */
1399 boolean
1400 In_mines(lev)
1401 d_level *lev;
1402 {
1403     return (boolean) (lev->dnum == mines_dnum);
1404 }
1405
1406 /*
1407  * Return the branch for the given dungeon.
1408  *
1409  * This function assumes:
1410  *      + This is not called with "Dungeons of Doom".
1411  *      + There is only _one_ branch to a given dungeon.
1412  *      + Field end2 is the "child" dungeon.
1413  */
1414 branch *
1415 dungeon_branch(s)
1416 const char *s;
1417 {
1418     branch *br;
1419     xchar dnum;
1420
1421     dnum = dname_to_dnum(s);
1422
1423     /* Find the branch that connects to dungeon i's branch. */
1424     for (br = branches; br; br = br->next)
1425         if (br->end2.dnum == dnum)
1426             break;
1427
1428     if (!br)
1429         panic("dgn_entrance: can't find entrance to %s", s);
1430
1431     return br;
1432 }
1433
1434 /*
1435  * This returns true if the hero is on the same level as the entrance to
1436  * the named dungeon.
1437  *
1438  * Called from do.c and mklev.c.
1439  *
1440  * Assumes that end1 is always the "parent".
1441  */
1442 boolean
1443 at_dgn_entrance(s)
1444 const char *s;
1445 {
1446     branch *br;
1447
1448     br = dungeon_branch(s);
1449     return on_level(&u.uz, &br->end1) ? TRUE : FALSE;
1450 }
1451
1452 /* is `lev' part of Vlad's tower? */
1453 boolean
1454 In_V_tower(lev)
1455 d_level *lev;
1456 {
1457     return (boolean) (lev->dnum == tower_dnum);
1458 }
1459
1460 /* is `lev' a level containing the Wizard's tower? */
1461 boolean
1462 On_W_tower_level(lev)
1463 d_level *lev;
1464 {
1465     return (boolean) (Is_wiz1_level(lev)
1466                       || Is_wiz2_level(lev)
1467                       || Is_wiz3_level(lev));
1468 }
1469
1470 /* is <x,y> of `lev' inside the Wizard's tower? */
1471 boolean
1472 In_W_tower(x, y, lev)
1473 int x, y;
1474 d_level *lev;
1475 {
1476     if (!On_W_tower_level(lev))
1477         return FALSE;
1478     /*
1479      * Both of the exclusion regions for arriving via level teleport
1480      * (from above or below) define the tower's boundary.
1481      *  assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1482      */
1483     if (dndest.nlx > 0)
1484         return (boolean) within_bounded_area(x, y, dndest.nlx, dndest.nly,
1485                                              dndest.nhx, dndest.nhy);
1486     else
1487         impossible("No boundary for Wizard's Tower?");
1488     return FALSE;
1489 }
1490
1491 /* are you in one of the Hell levels? */
1492 boolean
1493 In_hell(lev)
1494 d_level *lev;
1495 {
1496     return (boolean) (dungeons[lev->dnum].flags.hellish);
1497 }
1498
1499 /* sets *lev to be the gateway to Gehennom... */
1500 void
1501 find_hell(lev)
1502 d_level *lev;
1503 {
1504     lev->dnum = valley_level.dnum;
1505     lev->dlevel = 1;
1506 }
1507
1508 /* go directly to hell... */
1509 void
1510 goto_hell(at_stairs, falling)
1511 boolean at_stairs, falling;
1512 {
1513     d_level lev;
1514
1515     find_hell(&lev);
1516     goto_level(&lev, at_stairs, falling, FALSE);
1517 }
1518
1519 /* equivalent to dest = source */
1520 void
1521 assign_level(dest, src)
1522 d_level *dest, *src;
1523 {
1524     dest->dnum = src->dnum;
1525     dest->dlevel = src->dlevel;
1526 }
1527
1528 /* dest = src + rn1(range) */
1529 void
1530 assign_rnd_level(dest, src, range)
1531 d_level *dest, *src;
1532 int range;
1533 {
1534     dest->dnum = src->dnum;
1535     dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range));
1536
1537     if (dest->dlevel > dunlevs_in_dungeon(dest))
1538         dest->dlevel = dunlevs_in_dungeon(dest);
1539     else if (dest->dlevel < 1)
1540         dest->dlevel = 1;
1541 }
1542
1543 int
1544 induced_align(pct)
1545 int pct;
1546 {
1547     s_level *lev = Is_special(&u.uz);
1548     aligntyp al;
1549
1550     if (lev && lev->flags.align)
1551         if (rn2(100) < pct)
1552             return lev->flags.align;
1553
1554     if (dungeons[u.uz.dnum].flags.align)
1555         if (rn2(100) < pct)
1556             return dungeons[u.uz.dnum].flags.align;
1557
1558     al = rn2(3) - 1;
1559     return Align2amask(al);
1560 }
1561
1562 boolean
1563 Invocation_lev(lev)
1564 d_level *lev;
1565 {
1566     return (boolean) (In_hell(lev)
1567                       && lev->dlevel == dungeons[lev->dnum].num_dunlevs - 1);
1568 }
1569
1570 /* use instead of depth() wherever a degree of difficulty is made
1571  * dependent on the location in the dungeon (eg. monster creation).
1572  */
1573 xchar
1574 level_difficulty()
1575 {
1576     int res;
1577
1578     if (In_endgame(&u.uz)) {
1579         res = depth(&sanctum_level) + u.ulevel / 2;
1580     } else if (u.uhave.amulet) {
1581         res = deepest_lev_reached(FALSE);
1582     } else {
1583         res = depth(&u.uz);
1584         /* depth() is the number of elevation units (levels) below
1585            the theoretical surface; in a builds-up branch, that value
1586            ends up making the harder to reach levels be treated as if
1587            they were easier; adjust for the extra effort involved in
1588            going down to the entrance and then up to the location */
1589         if (builds_up(&u.uz))
1590             res += 2 * (dungeons[u.uz.dnum].entry_lev - u.uz.dlevel + 1);
1591             /*
1592              * 'Proof' by example:  suppose the entrance to sokoban is
1593              * on dungeon level 9, leading up to bottom sokoban level
1594              * of 8 [entry_lev].  When the hero is on sokoban level 8
1595              * [uz.dlevel], depth() yields eight but he has ventured
1596              * one level beyond 9, so difficulty depth should be 10:
1597              *   8 + 2 * (8 - 8 + 1) => 10.
1598              * Going up to 7, depth is 7 but hero will be two beyond 9:
1599              *   7 + 2 * (8 - 7 + 1) => 11.
1600              * When he goes up to level 6, three levels beyond 9:
1601              *   6 + 2 * (8 - 6 + 1) => 12.
1602              * And the top level of sokoban at 5, four levels beyond 9:
1603              *   5 + 2 * (8 - 5 + 1) => 13.
1604              * The same applies to Vlad's Tower, although the increment
1605              * there is inconsequential compared to overall depth.
1606              */
1607     }
1608     return (xchar) res;
1609 }
1610
1611 /* Take one word and try to match it to a level.
1612  * Recognized levels are as shown by print_dungeon().
1613  */
1614 schar
1615 lev_by_name(nam)
1616 const char *nam;
1617 {
1618     schar lev = 0;
1619     s_level *slev;
1620     d_level dlev;
1621     const char *p;
1622     int idx, idxtoo;
1623     char buf[BUFSZ];
1624
1625     /* allow strings like "the oracle level" to find "oracle" */
1626     if (!strncmpi(nam, "the ", 4))
1627         nam += 4;
1628     if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
1629         nam = strcpy(buf, nam);
1630         *(eos(buf) - 6) = '\0';
1631     }
1632     /* hell is the old name, and wouldn't match; gehennom would match its
1633        branch, yielding the castle level instead of the valley of the dead */
1634     if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1635         if (In_V_tower(&u.uz))
1636             nam = " to Vlad's tower"; /* branch to... */
1637         else
1638             nam = "valley";
1639     }
1640
1641     if ((slev = find_level(nam)) != 0) {
1642         dlev = slev->dlevel;
1643         idx = ledger_no(&dlev);
1644         if ((dlev.dnum == u.uz.dnum
1645              /* within same branch, or else main dungeon <-> gehennom */
1646              || (u.uz.dnum == valley_level.dnum
1647                  && dlev.dnum == medusa_level.dnum)
1648              || (u.uz.dnum == medusa_level.dnum
1649                  && dlev.dnum == valley_level.dnum))
1650             && (/* either wizard mode or else seen and not forgotten */
1651                 wizard
1652                 || (level_info[idx].flags & (FORGOTTEN | VISITED))
1653                        == VISITED)) {
1654             lev = depth(&slev->dlevel);
1655         }
1656     } else { /* not a specific level; try branch names */
1657         idx = find_branch(nam, (struct proto_dungeon *) 0);
1658         /* "<branch> to Xyzzy" */
1659         if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1660             idx = find_branch(p + 4, (struct proto_dungeon *) 0);
1661
1662         if (idx >= 0) {
1663             idxtoo = (idx >> 8) & 0x00FF;
1664             idx &= 0x00FF;
1665             if (/* either wizard mode, or else _both_ sides of branch seen */
1666                 wizard
1667                 || ((level_info[idx].flags & (FORGOTTEN | VISITED)) == VISITED
1668                     && (level_info[idxtoo].flags & (FORGOTTEN | VISITED))
1669                            == VISITED)) {
1670                 if (ledger_to_dnum(idxtoo) == u.uz.dnum)
1671                     idx = idxtoo;
1672                 dlev.dnum = ledger_to_dnum(idx);
1673                 dlev.dlevel = ledger_to_dlev(idx);
1674                 lev = depth(&dlev);
1675             }
1676         }
1677     }
1678     return lev;
1679 }
1680
1681 STATIC_OVL boolean
1682 unplaced_floater(dptr)
1683 struct dungeon *dptr;
1684 {
1685     branch *br;
1686     int idx = (int) (dptr - dungeons);
1687
1688     /* if other floating branches are added, this will need to change */
1689     if (idx != knox_level.dnum)
1690         return FALSE;
1691     for (br = branches; br; br = br->next)
1692         if (br->end1.dnum == n_dgns && br->end2.dnum == idx)
1693             return TRUE;
1694     return FALSE;
1695 }
1696
1697 STATIC_OVL boolean
1698 unreachable_level(lvl_p, unplaced)
1699 d_level *lvl_p;
1700 boolean unplaced;
1701 {
1702     s_level *dummy;
1703
1704     if (unplaced)
1705         return TRUE;
1706     if (In_endgame(&u.uz) && !In_endgame(lvl_p))
1707         return TRUE;
1708     if ((dummy = find_level("dummy")) != 0 && on_level(lvl_p, &dummy->dlevel))
1709         return TRUE;
1710     return FALSE;
1711 }
1712
1713 static void
1714 tport_menu(win, entry, lchoices, lvl_p, unreachable)
1715 winid win;
1716 char *entry;
1717 struct lchoice *lchoices;
1718 d_level *lvl_p;
1719 boolean unreachable;
1720 {
1721     char tmpbuf[BUFSZ];
1722     anything any;
1723
1724     lchoices->lev[lchoices->idx] = lvl_p->dlevel;
1725     lchoices->dgn[lchoices->idx] = lvl_p->dnum;
1726     lchoices->playerlev[lchoices->idx] = depth(lvl_p);
1727     any = zeroany;
1728     if (unreachable) {
1729         /* not selectable, but still consumes next menuletter;
1730            prepend padding in place of missing menu selector */
1731         Sprintf(tmpbuf, "    %s", entry);
1732         entry = tmpbuf;
1733     } else {
1734         any.a_int = lchoices->idx + 1;
1735     }
1736     add_menu(win, NO_GLYPH, &any, lchoices->menuletter, 0, ATR_NONE, entry,
1737              MENU_UNSELECTED);
1738     /* this assumes there are at most 52 interesting levels */
1739     if (lchoices->menuletter == 'z')
1740         lchoices->menuletter = 'A';
1741     else
1742         lchoices->menuletter++;
1743     lchoices->idx++;
1744     return;
1745 }
1746
1747 /* Convert a branch type to a string usable by print_dungeon(). */
1748 STATIC_OVL const char *
1749 br_string(type)
1750 int type;
1751 {
1752     switch (type) {
1753     case BR_PORTAL:
1754         return "Portal";
1755     case BR_NO_END1:
1756         return "Connection";
1757     case BR_NO_END2:
1758         return "One way stair";
1759     case BR_STAIR:
1760         return "Stair";
1761     }
1762     return " (unknown)";
1763 }
1764
1765 /* Print all child branches between the lower and upper bounds. */
1766 STATIC_OVL void
1767 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
1768 winid win;
1769 int dnum;
1770 int lower_bound;
1771 int upper_bound;
1772 boolean bymenu;
1773 struct lchoice *lchoices_p;
1774 {
1775     branch *br;
1776     char buf[BUFSZ];
1777
1778     /* This assumes that end1 is the "parent". */
1779     for (br = branches; br; br = br->next) {
1780         if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
1781             && br->end1.dlevel <= upper_bound) {
1782             Sprintf(buf, "   %s to %s: %d", br_string(br->type),
1783                     dungeons[br->end2.dnum].dname, depth(&br->end1));
1784             if (bymenu)
1785                 tport_menu(win, buf, lchoices_p, &br->end1,
1786                            unreachable_level(&br->end1, FALSE));
1787             else
1788                 putstr(win, 0, buf);
1789         }
1790     }
1791 }
1792
1793 /* Print available dungeon information. */
1794 schar
1795 print_dungeon(bymenu, rlev, rdgn)
1796 boolean bymenu;
1797 schar *rlev;
1798 xchar *rdgn;
1799 {
1800     int i, last_level, nlev;
1801     char buf[BUFSZ];
1802     const char *descr;
1803     boolean first, unplaced;
1804     s_level *slev;
1805     dungeon *dptr;
1806     branch *br;
1807     anything any;
1808     struct lchoice lchoices;
1809
1810     winid win = create_nhwindow(NHW_MENU);
1811     if (bymenu) {
1812         start_menu(win);
1813         lchoices.idx = 0;
1814         lchoices.menuletter = 'a';
1815     }
1816
1817     for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1818         if (bymenu && In_endgame(&u.uz) && i != astral_level.dnum)
1819             continue;
1820         unplaced = unplaced_floater(dptr);
1821         descr = unplaced ? "depth" : "level";
1822         nlev = dptr->num_dunlevs;
1823         if (nlev > 1)
1824             Sprintf(buf, "%s: %s %d to %d", dptr->dname, makeplural(descr),
1825                     dptr->depth_start, dptr->depth_start + nlev - 1);
1826         else
1827             Sprintf(buf, "%s: %s %d", dptr->dname, descr, dptr->depth_start);
1828
1829         /* Most entrances are uninteresting. */
1830         if (dptr->entry_lev != 1) {
1831             if (dptr->entry_lev == nlev)
1832                 Strcat(buf, ", entrance from below");
1833             else
1834                 Sprintf(eos(buf), ", entrance on %d",
1835                         dptr->depth_start + dptr->entry_lev - 1);
1836         }
1837         if (bymenu) {
1838             any = zeroany;
1839             add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
1840                      MENU_UNSELECTED);
1841         } else
1842             putstr(win, 0, buf);
1843
1844         /*
1845          * Circle through the special levels to find levels that are in
1846          * this dungeon.
1847          */
1848         for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1849             if (slev->dlevel.dnum != i)
1850                 continue;
1851
1852             /* print any branches before this level */
1853             print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
1854                          &lchoices);
1855
1856             Sprintf(buf, "   %s: %d", slev->proto, depth(&slev->dlevel));
1857             if (Is_stronghold(&slev->dlevel))
1858                 Sprintf(eos(buf), " (tune %s)", tune);
1859             if (bymenu)
1860                 tport_menu(win, buf, &lchoices, &slev->dlevel,
1861                            unreachable_level(&slev->dlevel, unplaced));
1862             else
1863                 putstr(win, 0, buf);
1864
1865             last_level = slev->dlevel.dlevel;
1866         }
1867         /* print branches after the last special level */
1868         print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1869     }
1870
1871     if (bymenu) {
1872         int n;
1873         menu_item *selected;
1874         int idx;
1875
1876         end_menu(win, "Level teleport to where:");
1877         n = select_menu(win, PICK_ONE, &selected);
1878         destroy_nhwindow(win);
1879         if (n > 0) {
1880             idx = selected[0].item.a_int - 1;
1881             free((genericptr_t) selected);
1882             if (rlev && rdgn) {
1883                 *rlev = lchoices.lev[idx];
1884                 *rdgn = lchoices.dgn[idx];
1885                 return lchoices.playerlev[idx];
1886             }
1887         }
1888         return 0;
1889     }
1890
1891     /* Print out floating branches (if any). */
1892     for (first = TRUE, br = branches; br; br = br->next) {
1893         if (br->end1.dnum == n_dgns) {
1894             if (first) {
1895                 putstr(win, 0, "");
1896                 putstr(win, 0, "Floating branches");
1897                 first = FALSE;
1898             }
1899             Sprintf(buf, "   %s to %s", br_string(br->type),
1900                     dungeons[br->end2.dnum].dname);
1901             putstr(win, 0, buf);
1902         }
1903     }
1904
1905     /* I hate searching for the invocation pos while debugging. -dean */
1906     if (Invocation_lev(&u.uz)) {
1907         putstr(win, 0, "");
1908         Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1909                 inv_pos.x, inv_pos.y, u.ux, u.uy);
1910         putstr(win, 0, buf);
1911     }
1912     /*
1913      * The following is based on the assumption that the inter-level portals
1914      * created by the level compiler (not the dungeon compiler) only exist
1915      * one per level (currently true, of course).
1916      */
1917     else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
1918              || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
1919         struct trap *trap;
1920         for (trap = ftrap; trap; trap = trap->ntrap)
1921             if (trap->ttyp == MAGIC_PORTAL)
1922                 break;
1923
1924         putstr(win, 0, "");
1925         if (trap)
1926             Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)", trap->tx,
1927                     trap->ty, u.ux, u.uy);
1928         else
1929             Sprintf(buf, "No portal found.");
1930         putstr(win, 0, buf);
1931     }
1932
1933     display_nhwindow(win, TRUE);
1934     destroy_nhwindow(win);
1935     return 0;
1936 }
1937
1938 /* Record that the player knows about a branch from a level. This function
1939  * will determine whether or not it was a "real" branch that was taken.
1940  * This function should not be called for a transition done via level
1941  * teleport or via the Eye.
1942  */
1943 void
1944 recbranch_mapseen(source, dest)
1945 d_level *source;
1946 d_level *dest;
1947 {
1948     mapseen *mptr;
1949     branch *br;
1950
1951     /* not a branch */
1952     if (source->dnum == dest->dnum)
1953         return;
1954
1955     /* we only care about forward branches */
1956     for (br = branches; br; br = br->next) {
1957         if (on_level(source, &br->end1) && on_level(dest, &br->end2))
1958             break;
1959         if (on_level(source, &br->end2) && on_level(dest, &br->end1))
1960             return;
1961     }
1962
1963     /* branch not found, so not a real branch. */
1964     if (!br)
1965         return;
1966
1967     if ((mptr = find_mapseen(source)) != 0) {
1968         if (mptr->br && br != mptr->br)
1969             impossible("Two branches on the same level?");
1970         mptr->br = br;
1971     } else {
1972         impossible("Can't note branch for unseen level (%d, %d)",
1973                    source->dnum, source->dlevel);
1974     }
1975 }
1976
1977 char *
1978 get_annotation(lev)
1979 d_level *lev;
1980 {
1981     mapseen *mptr;
1982
1983     if ((mptr = find_mapseen(lev)))
1984         return mptr->custom;
1985     return NULL;
1986 }
1987
1988 /* #annotate command - add a custom name to the current level */
1989 int
1990 donamelevel()
1991 {
1992     mapseen *mptr;
1993     char nbuf[BUFSZ]; /* Buffer for response */
1994
1995     if (!(mptr = find_mapseen(&u.uz)))
1996         return 0;
1997
1998     if (mptr->custom) {
1999         char tmpbuf[BUFSZ];
2000         Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
2001                 strlen(mptr->custom) > 30 ? "..." : "");
2002         getlin(tmpbuf, nbuf);
2003     } else
2004         getlin("What do you want to call this dungeon level?", nbuf);
2005     if (index(nbuf, '\033'))
2006         return 0;
2007     (void) mungspaces(nbuf);
2008
2009     /* discard old annotation, if any */
2010     if (mptr->custom) {
2011         free((genericptr_t) mptr->custom);
2012         mptr->custom = (char *) 0;
2013         mptr->custom_lth = 0;
2014     }
2015     /* add new annotation, unless it's empty or a single space */
2016     if (*nbuf && strcmp(nbuf, " ")) {
2017         mptr->custom = dupstr(nbuf);
2018         mptr->custom_lth = strlen(mptr->custom);
2019     }
2020     return 0;
2021 }
2022
2023 /* find the particular mapseen object in the chain; may return null */
2024 STATIC_OVL mapseen *
2025 find_mapseen(lev)
2026 d_level *lev;
2027 {
2028     mapseen *mptr;
2029
2030     for (mptr = mapseenchn; mptr; mptr = mptr->next)
2031         if (on_level(&(mptr->lev), lev))
2032             break;
2033
2034     return mptr;
2035 }
2036
2037 void
2038 forget_mapseen(ledger_num)
2039 int ledger_num;
2040 {
2041     mapseen *mptr;
2042     struct cemetery *bp;
2043
2044     for (mptr = mapseenchn; mptr; mptr = mptr->next)
2045         if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel
2046             == ledger_num)
2047             break;
2048
2049     /* if not found, then nothing to forget */
2050     if (mptr) {
2051         mptr->flags.forgot = 1;
2052         mptr->br = (branch *) 0;
2053
2054         /* custom names are erased, not just forgotten until revisited */
2055         if (mptr->custom) {
2056             mptr->custom_lth = 0;
2057             free((genericptr_t) mptr->custom);
2058             mptr->custom = (char *) 0;
2059         }
2060         (void) memset((genericptr_t) mptr->msrooms, 0, sizeof mptr->msrooms);
2061         for (bp = mptr->final_resting_place; bp; bp = bp->next)
2062             bp->bonesknown = FALSE;
2063     }
2064 }
2065
2066 STATIC_OVL void
2067 save_mapseen(fd, mptr)
2068 int fd;
2069 mapseen *mptr;
2070 {
2071     branch *curr;
2072     int brindx;
2073
2074     for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2075         if (curr == mptr->br)
2076             break;
2077     bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
2078
2079     bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
2080     bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
2081     bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
2082     bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
2083     if (mptr->custom_lth)
2084         bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
2085     bwrite(fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
2086     savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
2087 }
2088
2089 STATIC_OVL mapseen *
2090 load_mapseen(fd)
2091 int fd;
2092 {
2093     int branchnum, brindx;
2094     mapseen *load;
2095     branch *curr;
2096
2097     load = (mapseen *) alloc(sizeof *load);
2098
2099     mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
2100     for (brindx = 0, curr = branches; curr; curr = curr->next, ++brindx)
2101         if (brindx == branchnum)
2102             break;
2103     load->br = curr;
2104
2105     mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
2106     mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
2107     mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
2108     mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
2109     if (load->custom_lth) {
2110         /* length doesn't include terminator (which isn't saved & restored) */
2111         load->custom = (char *) alloc(load->custom_lth + 1);
2112         mread(fd, (genericptr_t) load->custom, load->custom_lth);
2113         load->custom[load->custom_lth] = '\0';
2114     } else
2115         load->custom = 0;
2116     mread(fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
2117     restcemetery(fd, &load->final_resting_place);
2118
2119     return load;
2120 }
2121
2122 /* Remove all mapseen objects for a particular dnum.
2123  * Useful during quest expulsion to remove quest levels.
2124  * [No longer deleted, just marked as unreachable.  #overview will
2125  * ignore such levels, end of game disclosure will include them.]
2126  */
2127 void
2128 remdun_mapseen(dnum)
2129 int dnum;
2130 {
2131     mapseen *mptr, **mptraddr;
2132
2133     mptraddr = &mapseenchn;
2134     while ((mptr = *mptraddr) != 0) {
2135         if (mptr->lev.dnum == dnum) {
2136 #if 1 /* use this... */
2137             mptr->flags.unreachable = 1;
2138         }
2139 #else /* old deletion code */
2140             *mptraddr = mptr->next;
2141             if (mptr->custom)
2142                 free((genericptr_t) mptr->custom);
2143             if (mptr->final_resting_place)
2144                 savecemetery(-1, FREE_SAVE, &mptr->final_resting_place);
2145             free((genericptr_t) mptr);
2146         } else
2147 #endif
2148         mptraddr = &mptr->next;
2149     }
2150 }
2151
2152 void
2153 init_mapseen(lev)
2154 d_level *lev;
2155 {
2156     /* Create a level and insert in "sorted" order.  This is an insertion
2157      * sort first by dungeon (in order of discovery) and then by level number.
2158      */
2159     mapseen *mptr, *init, *prev;
2160
2161     init = (mapseen *) alloc(sizeof *init);
2162     (void) memset((genericptr_t) init, 0, sizeof *init);
2163     /* memset is fine for feature bits, flags, and rooms array;
2164        explicitly initialize pointers to null */
2165     init->next = 0, init->br = 0, init->custom = 0;
2166     init->final_resting_place = 0;
2167     /* lastseentyp[][] is reused for each level, so get rid of
2168        previous level's data */
2169     (void) memset((genericptr_t) lastseentyp, 0, sizeof lastseentyp);
2170
2171     init->lev.dnum = lev->dnum;
2172     init->lev.dlevel = lev->dlevel;
2173
2174     /* walk until we get to the place where we should insert init */
2175     for (mptr = mapseenchn, prev = 0; mptr; prev = mptr, mptr = mptr->next)
2176         if (mptr->lev.dnum > init->lev.dnum
2177             || (mptr->lev.dnum == init->lev.dnum
2178                 && mptr->lev.dlevel > init->lev.dlevel))
2179             break;
2180     if (!prev) {
2181         init->next = mapseenchn;
2182         mapseenchn = init;
2183     } else {
2184         mptr = prev->next;
2185         prev->next = init;
2186         init->next = mptr;
2187     }
2188 }
2189
2190 #define INTEREST(feat)                                                \
2191     ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2192      || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2193   /* || (feat).water || (feat).ice || (feat).lava */
2194
2195 /* returns true if this level has something interesting to print out */
2196 STATIC_OVL boolean
2197 interest_mapseen(mptr)
2198 mapseen *mptr;
2199 {
2200     if (on_level(&u.uz, &mptr->lev))
2201         return TRUE;
2202     if (mptr->flags.unreachable || mptr->flags.forgot)
2203         return FALSE;
2204     /* level is of interest if it has an auto-generated annotation */
2205     if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
2206         || mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
2207         || mptr->flags.quest_summons || mptr->flags.questing)
2208         return TRUE;
2209     /* when in Sokoban, list all sokoban levels visited; when not in it,
2210        list any visited Sokoban level which remains unsolved (will usually
2211        only be furthest one reached, but it's possible to enter pits and
2212        climb out on the far side on the first Sokoban level; also, wizard
2213        mode overrides teleport restrictions) */
2214     if (In_sokoban(&mptr->lev)
2215         && (In_sokoban(&u.uz) || !mptr->flags.sokosolved))
2216         return TRUE;
2217     /* when in the endgame, list all endgame levels visited, whether they
2218        have annotations or not, so that #overview doesn't become extremely
2219        sparse once the rest of the dungeon has been flagged as unreachable */
2220     if (In_endgame(&u.uz))
2221         return (boolean) In_endgame(&mptr->lev);
2222     /* level is of interest if it has non-zero feature count or known bones
2223        or user annotation or known connection to another dungeon branch
2224        or is the furthest level reached in its branch */
2225     return (boolean) (INTEREST(mptr->feat)
2226                       || (mptr->final_resting_place
2227                           && (mptr->flags.knownbones || wizard))
2228                       || mptr->custom || mptr->br
2229                       || (mptr->lev.dlevel
2230                           == dungeons[mptr->lev.dnum].dunlev_ureached));
2231 }
2232
2233 /* recalculate mapseen for the current level */
2234 void
2235 recalc_mapseen()
2236 {
2237     mapseen *mptr;
2238     struct monst *mtmp;
2239     struct cemetery *bp, **bonesaddr;
2240     unsigned i, ridx;
2241     int x, y, ltyp, count, atmp;
2242
2243     /* Should not happen in general, but possible if in the process
2244      * of being booted from the quest.  The mapseen object gets
2245      * removed during the expulsion but prior to leaving the level
2246      * [Since quest expulsion no longer deletes quest mapseen data,
2247      * null return from find_mapseen() should now be impossible.]
2248      */
2249     if (!(mptr = find_mapseen(&u.uz)))
2250         return;
2251
2252     /* reset all features; mptr->feat.* = 0; */
2253     (void) memset((genericptr_t) &mptr->feat, 0, sizeof mptr->feat);
2254     /* reset most flags; some level-specific ones are left as-is */
2255     if (mptr->flags.unreachable) {
2256         mptr->flags.unreachable = 0; /* reached it; Eye of the Aethiopica? */
2257         if (In_quest(&u.uz)) {
2258             mapseen *mptrtmp = mapseenchn;
2259
2260             /* when quest was unreachable due to ejection and portal removal,
2261                getting back to it via arti-invoke should revive annotation
2262                data for all quest levels, not just the one we're on now */
2263             do {
2264                 if (mptrtmp->lev.dnum == mptr->lev.dnum)
2265                     mptrtmp->flags.unreachable = 0;
2266                 mptrtmp = mptrtmp->next;
2267             } while (mptrtmp);
2268         }
2269     }
2270     mptr->flags.knownbones = 0;
2271     mptr->flags.sokosolved = In_sokoban(&u.uz) && !Sokoban;
2272     /* mptr->flags.bigroom retains previous value when hero can't see */
2273     if (!Blind)
2274         mptr->flags.bigroom = Is_bigroom(&u.uz);
2275     else if (mptr->flags.forgot)
2276         mptr->flags.bigroom = 0;
2277     mptr->flags.roguelevel = Is_rogue_level(&u.uz);
2278     mptr->flags.oracle = 0; /* recalculated during room traversal below */
2279     mptr->flags.castletune = 0;
2280     /* flags.castle, flags.valley, flags.msanctum retain previous value */
2281     mptr->flags.forgot = 0;
2282     /* flags.quest_summons disabled once quest finished */
2283     mptr->flags.quest_summons = (at_dgn_entrance("The Quest")
2284                                  && u.uevent.qcalled
2285                                  && !(u.uevent.qcompleted
2286                                       || u.uevent.qexpelled
2287                                       || quest_status.leader_is_dead));
2288     mptr->flags.questing = (on_level(&u.uz, &qstart_level)
2289                             && quest_status.got_quest);
2290
2291     /* track rooms the hero is in */
2292     for (i = 0; i < SIZE(u.urooms); ++i) {
2293         if (!u.urooms[i])
2294             continue;
2295
2296         ridx = u.urooms[i] - ROOMOFFSET;
2297         mptr->msrooms[ridx].seen = 1;
2298         mptr->msrooms[ridx].untended =
2299             (rooms[ridx].rtype >= SHOPBASE)
2300                 ? (!(mtmp = shop_keeper(u.urooms[i])) || !inhishop(mtmp))
2301                 : (rooms[ridx].rtype == TEMPLE)
2302                       ? (!(mtmp = findpriest(u.urooms[i]))
2303                          || !inhistemple(mtmp))
2304                       : 0;
2305     }
2306
2307     /* recalculate room knowledge: for now, just shops and temples
2308      * this could be extended to an array of 0..SHOPBASE
2309      */
2310     for (i = 0; i < SIZE(mptr->msrooms); ++i) {
2311         if (mptr->msrooms[i].seen) {
2312             if (rooms[i].rtype >= SHOPBASE) {
2313                 if (mptr->msrooms[i].untended)
2314                     mptr->feat.shoptype = SHOPBASE - 1;
2315                 else if (!mptr->feat.nshop)
2316                     mptr->feat.shoptype = rooms[i].rtype;
2317                 else if (mptr->feat.shoptype != (unsigned) rooms[i].rtype)
2318                     mptr->feat.shoptype = 0;
2319                 count = mptr->feat.nshop + 1;
2320                 if (count <= 3)
2321                     mptr->feat.nshop = count;
2322             } else if (rooms[i].rtype == TEMPLE) {
2323                 /* altar and temple alignment handled below */
2324                 count = mptr->feat.ntemple + 1;
2325                 if (count <= 3)
2326                     mptr->feat.ntemple = count;
2327             } else if (rooms[i].orig_rtype == DELPHI) {
2328                 mptr->flags.oracle = 1;
2329             }
2330         }
2331     }
2332
2333     /* Update lastseentyp with typ if and only if it is in sight or the
2334      * hero can feel it on their current location (i.e. not levitating).
2335      * This *should* give the "last known typ" for each dungeon location.
2336      * (At the very least, it's a better assumption than determining what
2337      * the player knows from the glyph and the typ (which is isn't quite
2338      * enough information in some cases)).
2339      *
2340      * It was reluctantly added to struct rm to track.  Alternatively
2341      * we could track "features" and then update them all here, and keep
2342      * track of when new features are created or destroyed, but this
2343      * seemed the most elegant, despite adding more data to struct rm.
2344      * [3.6.0: we're using lastseentyp[][] rather than level.locations
2345      * to track the features seen.]
2346      *
2347      * Although no current windowing systems (can) do this, this would add
2348      * the ability to have non-dungeon glyphs float above the last known
2349      * dungeon glyph (i.e. items on fountains).
2350      */
2351     for (x = 1; x < COLNO; x++) {
2352         for (y = 0; y < ROWNO; y++) {
2353             if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
2354                 ltyp = levl[x][y].typ;
2355                 if (ltyp == DRAWBRIDGE_UP)
2356                     ltyp = db_under_typ(levl[x][y].drawbridgemask);
2357                 if ((mtmp = m_at(x, y)) != 0
2358                     && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
2359                     ltyp = cmap_to_type(mtmp->mappearance);
2360                 lastseentyp[x][y] = ltyp;
2361             }
2362
2363             switch (lastseentyp[x][y]) {
2364 #if 0
2365             case ICE:
2366                 count = mptr->feat.ice + 1;
2367                 if (count <= 3)
2368                     mptr->feat.ice = count;
2369                 break;
2370             case POOL:
2371             case MOAT:
2372             case WATER:
2373                 count = mptr->feat.water + 1;
2374                 if (count <= 3)
2375                     mptr->feat.water = count;
2376                 break;
2377             case LAVAPOOL:
2378                 count = mptr->feat.lava + 1;
2379                 if (count <= 3)
2380                     mptr->feat.lava = count;
2381                 break;
2382 #endif
2383             case TREE:
2384                 count = mptr->feat.ntree + 1;
2385                 if (count <= 3)
2386                     mptr->feat.ntree = count;
2387                 break;
2388             case FOUNTAIN:
2389                 count = mptr->feat.nfount + 1;
2390                 if (count <= 3)
2391                     mptr->feat.nfount = count;
2392                 break;
2393             case THRONE:
2394                 count = mptr->feat.nthrone + 1;
2395                 if (count <= 3)
2396                     mptr->feat.nthrone = count;
2397                 break;
2398             case SINK:
2399                 count = mptr->feat.nsink + 1;
2400                 if (count <= 3)
2401                     mptr->feat.nsink = count;
2402                 break;
2403             case GRAVE:
2404                 count = mptr->feat.ngrave + 1;
2405                 if (count <= 3)
2406                     mptr->feat.ngrave = count;
2407                 break;
2408             case ALTAR:
2409                 atmp = (Is_astralevel(&u.uz)
2410                         && (levl[x][y].seenv & SVALL) != SVALL)
2411                          ? MSA_NONE
2412                          : Amask2msa(levl[x][y].altarmask);
2413                 if (!mptr->feat.naltar)
2414                     mptr->feat.msalign = atmp;
2415                 else if (mptr->feat.msalign != atmp)
2416                     mptr->feat.msalign = MSA_NONE;
2417                 count = mptr->feat.naltar + 1;
2418                 if (count <= 3)
2419                     mptr->feat.naltar = count;
2420                 break;
2421             /*  An automatic annotation is added to the Castle and
2422              *  to Fort Ludios once their structure's main entrance
2423              *  has been seen (in person or via magic mapping).
2424              * DOOR: possibly a lowered drawbridge's open portcullis;
2425              * DBWALL: a raised drawbridge's "closed door";
2426              * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2427              *  with moat or other terrain hidden underneath;
2428              * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2429              *  not recognizable as a bridge location unless/until
2430              *  the adjacent DBWALL has been seen.
2431              */
2432             case DOOR:
2433                 if (is_drawbridge_wall(x, y) < 0)
2434                     break;
2435             /* else FALLTHRU */
2436             case DBWALL:
2437             case DRAWBRIDGE_DOWN:
2438                 if (Is_stronghold(&u.uz))
2439                     mptr->flags.castle = 1, mptr->flags.castletune = 1;
2440                 else if (Is_knox(&u.uz))
2441                     mptr->flags.ludios = 1;
2442                 break;
2443             default:
2444                 break;
2445             }
2446         }
2447     }
2448
2449     if (level.bonesinfo && !mptr->final_resting_place) {
2450         /* clone the bonesinfo so we aren't dependent upon this
2451            level being in memory */
2452         bonesaddr = &mptr->final_resting_place;
2453         bp = level.bonesinfo;
2454         do {
2455             *bonesaddr = (struct cemetery *) alloc(sizeof **bonesaddr);
2456             **bonesaddr = *bp;
2457             bp = bp->next;
2458             bonesaddr = &(*bonesaddr)->next;
2459         } while (bp);
2460         *bonesaddr = 0;
2461     }
2462     /* decide which past hero deaths have become known; there's no
2463        guarantee of either a grave or a ghost, so we go by whether the
2464        current hero has seen the map location where each old one died */
2465     for (bp = mptr->final_resting_place; bp; bp = bp->next)
2466         if (lastseentyp[bp->frpx][bp->frpy]) {
2467             bp->bonesknown = TRUE;
2468             mptr->flags.knownbones = 1;
2469         }
2470 }
2471
2472 /*ARGUSED*/
2473 /* valley and sanctum levels get automatic annotation once temple is entered
2474  */
2475 void
2476 mapseen_temple(priest)
2477 struct monst *priest UNUSED; /* currently unused; might be useful someday */
2478 {
2479     mapseen *mptr = find_mapseen(&u.uz);
2480
2481     if (Is_valley(&u.uz))
2482         mptr->flags.valley = 1;
2483     else if (Is_sanctum(&u.uz))
2484         mptr->flags.msanctum = 1;
2485 }
2486
2487 /* room entry message has just been delivered so learn room even if blind */
2488 void
2489 room_discovered(roomno)
2490 int roomno;
2491 {
2492     mapseen *mptr = find_mapseen(&u.uz);
2493
2494     mptr->msrooms[roomno].seen = 1;
2495 }
2496
2497 /* #overview command */
2498 int
2499 dooverview()
2500 {
2501     show_overview(0, 0);
2502     return 0;
2503 }
2504
2505 /* called for #overview or for end of game disclosure */
2506 void
2507 show_overview(why, reason)
2508 int why;    /* 0 => #overview command,
2509                1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2510 int reason; /* how hero died; used when disclosing end-of-game level */
2511 {
2512     winid win;
2513     int lastdun = -1;
2514
2515     /* lazy initialization */
2516     (void) recalc_mapseen();
2517
2518     win = create_nhwindow(NHW_MENU);
2519     /* show the endgame levels before the rest of the dungeon,
2520        so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2521     if (In_endgame(&u.uz))
2522         traverse_mapseenchn(TRUE, win, why, reason, &lastdun);
2523     /* if game is over or we're not in the endgame yet, show the dungeon */
2524     if (why > 0 || !In_endgame(&u.uz))
2525         traverse_mapseenchn(FALSE, win, why, reason, &lastdun);
2526     display_nhwindow(win, TRUE);
2527     destroy_nhwindow(win);
2528 }
2529
2530 /* display endgame levels or non-endgame levels, not both */
2531 STATIC_OVL void
2532 traverse_mapseenchn(viewendgame, win, why, reason, lastdun_p)
2533 boolean viewendgame;
2534 winid win;
2535 int why, reason, *lastdun_p;
2536 {
2537     mapseen *mptr;
2538     boolean showheader;
2539
2540     for (mptr = mapseenchn; mptr; mptr = mptr->next) {
2541         if (viewendgame ^ In_endgame(&mptr->lev))
2542             continue;
2543
2544         /* only print out info for a level or a dungeon if interest */
2545         if (why > 0 || interest_mapseen(mptr)) {
2546             showheader = (boolean) (mptr->lev.dnum != *lastdun_p);
2547             print_mapseen(win, mptr, why, reason, showheader);
2548             *lastdun_p = mptr->lev.dnum;
2549         }
2550     }
2551 }
2552
2553 STATIC_OVL const char *
2554 seen_string(x, obj)
2555 xchar x;
2556 const char *obj;
2557 {
2558     /* players are computer scientists: 0, 1, 2, n */
2559     switch (x) {
2560     case 0:
2561         return "no";
2562     /* an() returns too much.  index is ok in this case */
2563     case 1:
2564         return index(vowels, *obj) ? "an" : "a";
2565     case 2:
2566         return "some";
2567     case 3:
2568         return "many";
2569     }
2570
2571     return "(unknown)";
2572 }
2573
2574 /* better br_string */
2575 STATIC_OVL const char *
2576 br_string2(br)
2577 branch *br;
2578 {
2579     /* Special case: quest portal says closed if kicked from quest */
2580     boolean closed_portal = (br->end2.dnum == quest_dnum
2581                              && u.uevent.qexpelled);
2582
2583     switch (br->type) {
2584     case BR_PORTAL:
2585         return closed_portal ? "Sealed portal" : "Portal";
2586     case BR_NO_END1:
2587         return "Connection";
2588     case BR_NO_END2:
2589         return br->end1_up ? "One way stairs up" : "One way stairs down";
2590     case BR_STAIR:
2591         return br->end1_up ? "Stairs up" : "Stairs down";
2592     }
2593
2594     return "(unknown)";
2595 }
2596
2597 /* get the name of an endgame level; topten.c does something similar */
2598 STATIC_OVL const char *
2599 endgamelevelname(outbuf, indx)
2600 char *outbuf;
2601 int indx;
2602 {
2603     const char *planename = 0;
2604
2605     *outbuf = '\0';
2606     switch (indx) {
2607     case -5:
2608         Strcpy(outbuf, "Astral Plane");
2609         break;
2610     case -4:
2611         planename = "Water";
2612         break;
2613     case -3:
2614         planename = "Fire";
2615         break;
2616     case -2:
2617         planename = "Air";
2618         break;
2619     case -1:
2620         planename = "Earth";
2621         break;
2622     }
2623     if (planename)
2624         Sprintf(outbuf, "Plane of %s", planename);
2625     else if (!*outbuf)
2626         Sprintf(outbuf, "unknown plane #%d", indx);
2627     return outbuf;
2628 }
2629
2630 STATIC_OVL const char *
2631 shop_string(rtype)
2632 int rtype;
2633 {
2634     const char *str = "shop"; /* catchall */
2635
2636     /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2637     switch (rtype) {
2638     case SHOPBASE - 1:
2639         str = "untended shop";
2640         break; /* see recalc_mapseen */
2641     case SHOPBASE:
2642         str = "general store";
2643         break;
2644     case ARMORSHOP:
2645         str = "armor shop";
2646         break;
2647     case SCROLLSHOP:
2648         str = "scroll shop";
2649         break;
2650     case POTIONSHOP:
2651         str = "potion shop";
2652         break;
2653     case WEAPONSHOP:
2654         str = "weapon shop";
2655         break;
2656     case FOODSHOP:
2657         str = "delicatessen";
2658         break;
2659     case RINGSHOP:
2660         str = "jewelers";
2661         break;
2662     case WANDSHOP:
2663         str = "wand shop";
2664         break;
2665     case BOOKSHOP:
2666         str = "bookstore";
2667         break;
2668     case FODDERSHOP:
2669         str = "health food store";
2670         break;
2671     case CANDLESHOP:
2672         str = "lighting shop";
2673         break;
2674     default:
2675         break;
2676     }
2677     return str;
2678 }
2679
2680 /* if player knows about the mastermind tune, append it to Castle annotation;
2681    if drawbridge has been destroyed, flags.castletune will be zero */
2682 STATIC_OVL char *
2683 tunesuffix(mptr, outbuf)
2684 mapseen *mptr;
2685 char *outbuf;
2686 {
2687     *outbuf = '\0';
2688     if (mptr->flags.castletune && u.uevent.uheard_tune) {
2689         char tmp[BUFSZ];
2690
2691         if (u.uevent.uheard_tune == 2)
2692             Sprintf(tmp, "notes \"%s\"", tune);
2693         else
2694             Strcpy(tmp, "5-note tune");
2695         Sprintf(outbuf, " (play %s to open or close drawbridge)", tmp);
2696     }
2697     return outbuf;
2698 }
2699
2700 /* some utility macros for print_mapseen */
2701 #define TAB "   " /* three spaces */
2702 #if 0
2703 #define BULLET "" /* empty; otherwise output becomes cluttered */
2704 #define PREFIX TAB TAB BULLET
2705 #else                   /*!0*/
2706 /* K&R: don't require support for concatenation of adjacent string literals */
2707 #define PREFIX "      " /* two TABs + empty BULLET: six spaces */
2708 #endif
2709 #define COMMA (i++ > 0 ? ", " : PREFIX)
2710 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2711 #define ADDNTOBUF(nam, var)                                                  \
2712     do {                                                                     \
2713         if (var)                                                             \
2714             Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2715                     (nam), plur(var));                                       \
2716     } while (0)
2717 #define ADDTOBUF(nam, var)                           \
2718     do {                                             \
2719         if (var)                                     \
2720             Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
2721     } while (0)
2722
2723 STATIC_OVL void
2724 print_mapseen(win, mptr, final, how, printdun)
2725 winid win;
2726 mapseen *mptr;
2727 int final; /* 0: not final; 1: game over, alive; 2: game over, dead */
2728 int how;   /* cause of death; only used if final==2 and mptr->lev==u.uz */
2729 boolean printdun;
2730 {
2731     char buf[BUFSZ], tmpbuf[BUFSZ];
2732     int i, depthstart, dnum;
2733     boolean died_here = (final == 2 && on_level(&u.uz, &mptr->lev));
2734
2735     /* Damnable special cases */
2736     /* The quest and knox should appear to be level 1 to match
2737      * other text.
2738      */
2739     dnum = mptr->lev.dnum;
2740     if (dnum == quest_dnum || dnum == knox_level.dnum)
2741         depthstart = 1;
2742     else
2743         depthstart = dungeons[dnum].depth_start;
2744
2745     if (printdun) {
2746         if (dungeons[dnum].dunlev_ureached == dungeons[dnum].entry_lev
2747             /* suppress the negative numbers in the endgame */
2748             || In_endgame(&mptr->lev))
2749             Sprintf(buf, "%s:", dungeons[dnum].dname);
2750         else if (builds_up(&mptr->lev))
2751             Sprintf(buf, "%s: levels %d up to %d",
2752                     dungeons[dnum].dname,
2753                     depthstart + dungeons[dnum].entry_lev - 1,
2754                     depthstart + dungeons[dnum].dunlev_ureached - 1);
2755         else
2756             Sprintf(buf, "%s: levels %d to %d",
2757                     dungeons[dnum].dname, depthstart,
2758                     depthstart + dungeons[dnum].dunlev_ureached - 1);
2759         putstr(win, !final ? ATR_INVERSE : 0, buf);
2760     }
2761
2762     /* calculate level number */
2763     i = depthstart + mptr->lev.dlevel - 1;
2764     if (In_endgame(&mptr->lev))
2765         Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
2766     else
2767         /* FIXME: when this branch has only one level (Ft.Ludios),
2768          * listing "Level 1:" for it might confuse inexperienced
2769          * players into thinking there's more than one.
2770          */
2771         Sprintf(buf, "%sLevel %d:", TAB, i);
2772
2773     /* wizmode prints out proto dungeon names for clarity */
2774     if (wizard) {
2775         s_level *slev;
2776
2777         if ((slev = Is_special(&mptr->lev)) != 0)
2778             Sprintf(eos(buf), " [%s]", slev->proto);
2779     }
2780     /* [perhaps print custom annotation on its own line when it's long] */
2781     if (mptr->custom)
2782         Sprintf(eos(buf), " (%s)", mptr->custom);
2783     if (on_level(&u.uz, &mptr->lev))
2784         Sprintf(eos(buf), " <- You %s here.",
2785                 (!final || (final == 1 && how == ASCENDED)) ? "are" : "were");
2786     putstr(win, !final ? ATR_BOLD : 0, buf);
2787
2788     if (mptr->flags.forgot)
2789         return;
2790
2791     if (INTEREST(mptr->feat)) {
2792         buf[0] = 0;
2793
2794         i = 0; /* interest counter */
2795         /* List interests in an order vaguely corresponding to
2796          * how important they are.
2797          */
2798         if (mptr->feat.nshop > 0) {
2799             if (mptr->feat.nshop > 1)
2800                 ADDNTOBUF("shop", mptr->feat.nshop);
2801             else
2802                 Sprintf(eos(buf), "%s%s", COMMA,
2803                         an(shop_string(mptr->feat.shoptype)));
2804         }
2805         if (mptr->feat.naltar > 0) {
2806             /* Temples + non-temple altars get munged into just "altars" */
2807             if (mptr->feat.ntemple != mptr->feat.naltar)
2808                 ADDNTOBUF("altar", mptr->feat.naltar);
2809             else
2810                 ADDNTOBUF("temple", mptr->feat.ntemple);
2811
2812             /* only print out altar's god if they are all to your god */
2813             if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
2814                 Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
2815         }
2816         ADDNTOBUF("throne", mptr->feat.nthrone);
2817         ADDNTOBUF("fountain", mptr->feat.nfount);
2818         ADDNTOBUF("sink", mptr->feat.nsink);
2819         ADDNTOBUF("grave", mptr->feat.ngrave);
2820         ADDNTOBUF("tree", mptr->feat.ntree);
2821 #if 0
2822         ADDTOBUF("water", mptr->feat.water);
2823         ADDTOBUF("lava", mptr->feat.lava);
2824         ADDTOBUF("ice", mptr->feat.ice);
2825 #endif
2826         /* capitalize afterwards */
2827         i = strlen(PREFIX);
2828         buf[i] = highc(buf[i]);
2829         /* capitalizing it makes it a sentence; terminate with '.' */
2830         Strcat(buf, ".");
2831         putstr(win, 0, buf);
2832     }
2833
2834     /* we assume that these are mutually exclusive */
2835     *buf = '\0';
2836     if (mptr->flags.oracle) {
2837         Sprintf(buf, "%sOracle of Delphi.", PREFIX);
2838     } else if (In_sokoban(&mptr->lev)) {
2839         Sprintf(buf, "%s%s.", PREFIX,
2840                 mptr->flags.sokosolved ? "Solved" : "Unsolved");
2841     } else if (mptr->flags.bigroom) {
2842         Sprintf(buf, "%sA very big room.", PREFIX);
2843     } else if (mptr->flags.roguelevel) {
2844         Sprintf(buf, "%sA primitive area.", PREFIX);
2845     } else if (mptr->flags.quest_summons) {
2846         Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
2847     } else if (on_level(&mptr->lev, &qstart_level)) {
2848         Sprintf(buf, "%sHome%s.", PREFIX,
2849                 mptr->flags.unreachable ? " (no way back...)" : "");
2850         if (u.uevent.qcompleted)
2851             Sprintf(buf, "%sCompleted quest for %s.", PREFIX, ldrname());
2852         else if (mptr->flags.questing)
2853             Sprintf(buf, "%sGiven quest by %s.", PREFIX, ldrname());
2854     } else if (mptr->flags.ludios) {
2855         /* presence of the ludios branch in #overview output indicates that
2856            the player has made it onto the level; presence of this annotation
2857            indicates that the fort's entrance has been seen (or mapped) */
2858         Sprintf(buf, "%sFort Ludios.", PREFIX);
2859     } else if (mptr->flags.castle) {
2860         Sprintf(buf, "%sThe castle%s.", PREFIX, tunesuffix(mptr, tmpbuf));
2861     } else if (mptr->flags.valley) {
2862         Sprintf(buf, "%sValley of the Dead.", PREFIX);
2863     } else if (mptr->flags.msanctum) {
2864         Sprintf(buf, "%sMoloch's Sanctum.", PREFIX);
2865     }
2866     if (*buf)
2867         putstr(win, 0, buf);
2868
2869     /* print out branches */
2870     if (mptr->br) {
2871         Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br),
2872                 dungeons[mptr->br->end2.dnum].dname);
2873
2874         /* Since mapseen objects are printed out in increasing order
2875          * of dlevel, clarify which level this branch is going to
2876          * if the branch goes upwards.  Unless it's the end game.
2877          */
2878         if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
2879             Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
2880         Strcat(buf, ".");
2881         putstr(win, 0, buf);
2882     }
2883
2884     /* maybe print out bones details */
2885     if (mptr->final_resting_place || final) {
2886         struct cemetery *bp;
2887         int kncnt = !died_here ? 0 : 1;
2888
2889         for (bp = mptr->final_resting_place; bp; bp = bp->next)
2890             if (bp->bonesknown || wizard || final)
2891                 ++kncnt;
2892         if (kncnt) {
2893             Sprintf(buf, "%s%s", PREFIX, "Final resting place for");
2894             putstr(win, 0, buf);
2895             if (died_here) {
2896                 /* disclosure occurs before bones creation, so listing dead
2897                    hero here doesn't give away whether bones are produced */
2898                 formatkiller(tmpbuf, sizeof tmpbuf, how);
2899                 /* rephrase a few death reasons to work with "you" */
2900                 (void) strsubst(tmpbuf, " himself", " yourself");
2901                 (void) strsubst(tmpbuf, " herself", " yourself");
2902                 (void) strsubst(tmpbuf, " his ", " your ");
2903                 (void) strsubst(tmpbuf, " her ", " your ");
2904                 Sprintf(buf, "%s%syou, %s%c", PREFIX, TAB, tmpbuf,
2905                         --kncnt ? ',' : '.');
2906                 putstr(win, 0, buf);
2907             }
2908             for (bp = mptr->final_resting_place; bp; bp = bp->next) {
2909                 if (bp->bonesknown || wizard || final) {
2910                     Sprintf(buf, "%s%s%s, %s%c", PREFIX, TAB, bp->who,
2911                             bp->how, --kncnt ? ',' : '.');
2912                     putstr(win, 0, buf);
2913                 }
2914             }
2915         }
2916     }
2917 }
2918
2919 /*dungeon.c*/