OSDN Git Service

no E-word
[nethackexpress/trunk.git] / src / dungeon.c
1 /*      SCCS Id: @(#)dungeon.c  3.4     1999/10/30      */
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
9 #ifdef OVL1
10
11 #define DUNGEON_FILE    "dungeon"
12
13 #define X_START         "x-strt"
14 #define X_LOCATE        "x-loca"
15 #define X_GOAL          "x-goal"
16
17 struct proto_dungeon {
18         struct  tmpdungeon tmpdungeon[MAXDUNGEON];
19         struct  tmplevel   tmplevel[LEV_LIMIT];
20         s_level *final_lev[LEV_LIMIT];  /* corresponding level pointers */
21         struct  tmpbranch  tmpbranch[BRANCH_LIMIT];
22
23         int     start;  /* starting index of current dungeon sp levels */
24         int     n_levs; /* number of tmplevel entries */
25         int     n_brs;  /* number of tmpbranch entries */
26 };
27
28 int n_dgns;                             /* number of dungeons (used here,  */
29                                         /*   and mklev.c)                  */
30 static branch *branches = (branch *) 0; /* dungeon branch list             */
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,struct proto_dungeon *,int *));
45 STATIC_DCL xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *));
46 STATIC_DCL int FDECL(correct_branch_type, (struct tmpbranch *));
47 STATIC_DCL branch *FDECL(add_branch, (int, int, struct proto_dungeon *));
48 STATIC_DCL void FDECL(add_level, (s_level *));
49 STATIC_DCL void FDECL(init_level, (int,int,struct proto_dungeon *));
50 STATIC_DCL int FDECL(possible_places, (int, boolean *, struct proto_dungeon *));
51 STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
52 STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
53 #ifdef WIZARD
54 STATIC_DCL const char *FDECL(br_string, (int));
55 STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, struct lchoice *));
56 #endif
57
58 #ifdef DEBUG
59 #define DD      dungeons[i]
60 STATIC_DCL void NDECL(dumpit);
61
62 STATIC_OVL void
63 dumpit()
64 {
65         int     i;
66         s_level *x;
67         branch *br;
68
69         for(i = 0; i < n_dgns; i++)  {
70             fprintf(stderr, "\n#%d \"%s\" (%s):\n", i,
71                                 DD.dname, DD.proto);
72             fprintf(stderr, "    num_dunlevs %d, dunlev_ureached %d\n",
73                                 DD.num_dunlevs, DD.dunlev_ureached);
74             fprintf(stderr, "    depth_start %d, ledger_start %d\n",
75                                 DD.depth_start, DD.ledger_start);
76             fprintf(stderr, "    flags:%s%s%s\n",
77                     DD.flags.rogue_like ? " rogue_like" : "",
78                     DD.flags.maze_like  ? " maze_like"  : "",
79                     DD.flags.hellish    ? " hellish"    : "");
80             getchar();
81         }
82         fprintf(stderr,"\nSpecial levels:\n");
83         for(x = sp_levchn; x; x = x->next) {
84             fprintf(stderr, "%s (%d): ", x->proto, x->rndlevs);
85             fprintf(stderr, "on %d, %d; ", x->dlevel.dnum, x->dlevel.dlevel);
86             fprintf(stderr, "flags:%s%s%s%s\n",
87                     x->flags.rogue_like ? " rogue_like" : "",
88                     x->flags.maze_like  ? " maze_like"  : "",
89                     x->flags.hellish    ? " hellish"    : "",
90                     x->flags.town       ? " town"       : "");
91             getchar();
92         }
93         fprintf(stderr,"\nBranches:\n");
94         for (br = branches; br; br = br->next) {
95             fprintf(stderr, "%d: %s, end1 %d %d, end2 %d %d, %s\n",
96                 br->id,
97                 br->type == BR_STAIR ? "stair" :
98                     br->type == BR_NO_END1 ? "no end1" :
99                     br->type == BR_NO_END2 ? "no end2" :
100                     br->type == BR_PORTAL  ? "portal"  :
101                                              "unknown",
102                 br->end1.dnum, br->end1.dlevel,
103                 br->end2.dnum, br->end2.dlevel,
104                 br->end1_up ? "end1 up" : "end1 down");
105         }
106         getchar();
107         fprintf(stderr,"\nDone\n");
108         getchar();
109 }
110 #endif
111
112 /* Save the dungeon structures. */
113 void
114 save_dungeon(fd, perform_write, free_data)
115     int fd;
116     boolean perform_write, free_data;
117 {
118     branch *curr, *next;
119     int    count;
120
121     if (perform_write) {
122         bwrite(fd, (genericptr_t) &n_dgns, sizeof n_dgns);
123         bwrite(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned)n_dgns);
124         bwrite(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
125         bwrite(fd, (genericptr_t) tune, sizeof tune);
126
127         for (count = 0, curr = branches; curr; curr = curr->next)
128             count++;
129         bwrite(fd, (genericptr_t) &count, sizeof(count));
130
131         for (curr = branches; curr; curr = curr->next)
132             bwrite(fd, (genericptr_t) curr, sizeof (branch));
133
134         count = maxledgerno();
135         bwrite(fd, (genericptr_t) &count, sizeof count);
136         bwrite(fd, (genericptr_t) level_info,
137                         (unsigned)count * sizeof (struct linfo));
138         bwrite(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
139     }
140
141     if (free_data) {
142         for (curr = branches; curr; curr = next) {
143             next = curr->next;
144             free((genericptr_t) curr);
145         }
146         branches = 0;
147     }
148 }
149
150 /* Restore the dungeon structures. */
151 void
152 restore_dungeon(fd)
153     int fd;
154 {
155     branch *curr, *last;
156     int    count, i;
157
158     mread(fd, (genericptr_t) &n_dgns, sizeof(n_dgns));
159     mread(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned)n_dgns);
160     mread(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
161     mread(fd, (genericptr_t) tune, sizeof tune);
162
163     last = branches = (branch *) 0;
164
165     mread(fd, (genericptr_t) &count, sizeof(count));
166     for (i = 0; i < count; i++) {
167         curr = (branch *) alloc(sizeof(branch));
168         mread(fd, (genericptr_t) curr, sizeof(branch));
169         curr->next = (branch *) 0;
170         if (last)
171             last->next = curr;
172         else
173             branches = curr;
174         last = curr;
175     }
176
177     mread(fd, (genericptr_t) &count, sizeof(count));
178     if (count >= MAXLINFO)
179         panic("level information count larger (%d) than allocated size", count);
180     mread(fd, (genericptr_t) level_info, (unsigned)count*sizeof(struct linfo));
181     mread(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
182 }
183
184 static void
185 Fread(ptr, size, nitems, stream)
186         genericptr_t    ptr;
187         int     size, nitems;
188         dlb     *stream;
189 {
190         int cnt;
191
192         if((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) {
193             panic(
194  "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
195                   (size * nitems), (size * cnt));
196             terminate(EXIT_FAILURE);
197         }
198 }
199
200 STATIC_OVL xchar
201 dname_to_dnum(s)
202 const char      *s;
203 {
204         xchar   i;
205
206         for (i = 0; i < n_dgns; i++)
207             if (!strcmp(dungeons[i].dname, s)) return i;
208
209         panic("Couldn't resolve dungeon number for name \"%s\".", s);
210         /*NOT REACHED*/
211         return (xchar)0;
212 }
213
214 s_level *
215 find_level(s)
216         const char *s;
217 {
218         s_level *curr;
219         for(curr = sp_levchn; curr; curr = curr->next)
220             if (!strcmpi(s, curr->proto)) break;
221         return curr;
222 }
223
224 /* Find the branch that links the named dungeon. */
225 STATIC_OVL int
226 find_branch(s, pd)
227         const char *s;          /* dungeon name */
228         struct proto_dungeon *pd;
229 {
230         int i;
231
232         if (pd) {
233             for (i = 0; i < pd->n_brs; i++)
234                 if (!strcmp(pd->tmpbranch[i].name, s)) break;
235             if (i == pd->n_brs) panic("find_branch: can't find %s", s);
236         } else {
237             /* support for level tport by name */
238             branch *br;
239             const char *dnam;
240
241             for (br = branches; br; br = br->next) {
242                 dnam = dungeons[br->end2.dnum].dname;
243                 if (!strcmpi(dnam, s) ||
244                         (!strncmpi(dnam, "The ", 4) && !strcmpi(dnam + 4, s)))
245                     break;
246             }
247             i = br ? ((ledger_no(&br->end1) << 8) | ledger_no(&br->end2)) : -1;
248         }
249         return i;
250 }
251
252
253 /*
254  * Find the "parent" by searching the prototype branch list for the branch
255  * listing, then figuring out to which dungeon it belongs.
256  */
257 STATIC_OVL xchar
258 parent_dnum(s, pd)
259 const char         *s;  /* dungeon name */
260 struct proto_dungeon *pd;
261 {
262         int     i;
263         xchar   pdnum;
264
265         i = find_branch(s, pd);
266         /*
267          * Got branch, now find parent dungeon.  Stop if we have reached
268          * "this" dungeon (if we haven't found it by now it is an error).
269          */
270         for (pdnum = 0; strcmp(pd->tmpdungeon[pdnum].name, s); pdnum++)
271             if ((i -= pd->tmpdungeon[pdnum].branches) < 0)
272                 return(pdnum);
273
274         panic("parent_dnum: couldn't resolve branch.");
275         /*NOT REACHED*/
276         return (xchar)0;
277 }
278
279 /*
280  * Return a starting point and number of successive positions a level
281  * or dungeon entrance can occupy.
282  *
283  * Note: This follows the acouple (instead of the rcouple) rules for a
284  *       negative random component (rand < 0).  These rules are found
285  *       in dgn_comp.y.  The acouple [absolute couple] section says that
286  *       a negative random component means from the (adjusted) base to the
287  *       end of the dungeon.
288  */
289 STATIC_OVL int
290 level_range(dgn, base, rand, chain, pd, adjusted_base)
291         xchar   dgn;
292         int     base, rand, chain;
293         struct proto_dungeon *pd;
294         int *adjusted_base;
295 {
296         int lmax = dungeons[dgn].num_dunlevs;
297
298         if (chain >= 0) {                /* relative to a special level */
299             s_level *levtmp = pd->final_lev[chain];
300             if (!levtmp) panic("level_range: empty chain level!");
301
302             base += levtmp->dlevel.dlevel;
303         } else {                        /* absolute in the dungeon */
304             /* from end of dungeon */
305             if (base < 0) base = (lmax + base + 1);
306         }
307
308         if (base < 1 || base > lmax)
309             panic("level_range: base value out of range");
310
311         *adjusted_base = base;
312
313         if (rand == -1) {       /* from base to end of dungeon */
314             return (lmax - base + 1);
315         } else if (rand) {
316             /* make sure we don't run off the end of the dungeon */
317             return (((base + rand - 1) > lmax) ? lmax-base+1 : rand);
318         } /* else only one choice */
319         return 1;
320 }
321
322 STATIC_OVL xchar
323 parent_dlevel(s, pd)
324         const char      *s;
325         struct proto_dungeon *pd;
326 {
327         int i, j, num, base, dnum = parent_dnum(s, pd);
328         branch *curr;
329
330
331         i = find_branch(s, pd);
332         num = level_range(dnum, pd->tmpbranch[i].lev.base,
333                                               pd->tmpbranch[i].lev.rand,
334                                               pd->tmpbranch[i].chain,
335                                               pd, &base);
336
337         /* KMH -- Try our best to find a level without an existing branch */
338         i = j = rn2(num);
339         do {
340                 if (++i >= num) i = 0;
341                 for (curr = branches; curr; curr = curr->next)
342                         if ((curr->end1.dnum == dnum && curr->end1.dlevel == base+i) ||
343                                 (curr->end2.dnum == dnum && curr->end2.dlevel == base+i))
344                                 break;
345         } while (curr && i != j);
346         return (base + i);
347 }
348
349 /* Convert from the temporary branch type to the dungeon branch type. */
350 STATIC_OVL int
351 correct_branch_type(tbr)
352     struct tmpbranch *tbr;
353 {
354     switch (tbr->type) {
355         case TBR_STAIR:         return BR_STAIR;
356         case TBR_NO_UP:         return tbr->up ? BR_NO_END1 : BR_NO_END2;
357         case TBR_NO_DOWN:       return tbr->up ? BR_NO_END2 : BR_NO_END1;
358         case TBR_PORTAL:        return BR_PORTAL;
359     }
360     impossible("correct_branch_type: unknown branch type");
361     return BR_STAIR;
362 }
363
364 /*
365  * Add the given branch to the branch list.  The branch list is ordered
366  * by end1 dungeon and level followed by end2 dungeon and level.  If
367  * extract_first is true, then the branch is already part of the list
368  * but needs to be repositioned.
369  */
370 void
371 insert_branch(new_branch, extract_first)
372    branch *new_branch;
373    boolean extract_first;
374 {
375     branch *curr, *prev;
376     long new_val, curr_val, prev_val;
377
378     if (extract_first) {
379         for (prev = 0, curr = branches; curr; prev = curr, curr = curr->next)
380             if (curr == new_branch) break;
381
382         if (!curr) panic("insert_branch: not found");
383         if (prev)
384             prev->next = curr->next;
385         else
386             branches = curr->next;
387     }
388     new_branch->next = (branch *) 0;
389
390 /* Convert the branch into a unique number so we can sort them. */
391 #define branch_val(bp) \
392         ((((long)(bp)->end1.dnum * (MAXLEVEL+1) + \
393           (long)(bp)->end1.dlevel) * (MAXDUNGEON+1) * (MAXLEVEL+1)) + \
394          ((long)(bp)->end2.dnum * (MAXLEVEL+1) + (long)(bp)->end2.dlevel))
395
396     /*
397      * Insert the new branch into the correct place in the branch list.
398      */
399     prev = (branch *) 0;
400     prev_val = -1;
401     new_val = branch_val(new_branch);
402     for (curr = branches; curr;
403                     prev_val = curr_val, prev = curr, curr = curr->next) {
404         curr_val = branch_val(curr);
405         if (prev_val < new_val && new_val <= curr_val) break;
406     }
407     if (prev) {
408         new_branch->next = curr;
409         prev->next = new_branch;
410     } else {
411         new_branch->next = branches;
412         branches = new_branch;
413     }
414 }
415
416 /* Add a dungeon branch to the branch list. */
417 STATIC_OVL branch *
418 add_branch(dgn, child_entry_level, pd)
419     int dgn;
420     int child_entry_level;
421     struct proto_dungeon *pd;
422 {
423     static int branch_id = 0;
424     int branch_num;
425     branch *new_branch;
426
427     branch_num = find_branch(dungeons[dgn].dname,pd);
428     new_branch = (branch *) alloc(sizeof(branch));
429     new_branch->next = (branch *) 0;
430     new_branch->id = branch_id++;
431     new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
432     new_branch->end1.dnum = parent_dnum(dungeons[dgn].dname, pd);
433     new_branch->end1.dlevel = parent_dlevel(dungeons[dgn].dname, pd);
434     new_branch->end2.dnum = dgn;
435     new_branch->end2.dlevel = child_entry_level;
436     new_branch->end1_up = pd->tmpbranch[branch_num].up ? TRUE : FALSE;
437
438     insert_branch(new_branch, FALSE);
439     return new_branch;
440 }
441
442 /*
443  * Add new level to special level chain.  Insert it in level order with the
444  * other levels in this dungeon.  This assumes that we are never given a
445  * level that has a dungeon number less than the dungeon number of the
446  * last entry.
447  */
448 STATIC_OVL void
449 add_level(new_lev)
450     s_level *new_lev;
451 {
452         s_level *prev, *curr;
453
454         prev = (s_level *) 0;
455         for (curr = sp_levchn; curr; curr = curr->next) {
456             if (curr->dlevel.dnum == new_lev->dlevel.dnum &&
457                     curr->dlevel.dlevel > new_lev->dlevel.dlevel)
458                 break;
459             prev = curr;
460         }
461         if (!prev) {
462             new_lev->next = sp_levchn;
463             sp_levchn = new_lev;
464         } else {
465             new_lev->next = curr;
466             prev->next = new_lev;
467         }
468 }
469
470 STATIC_OVL void
471 init_level(dgn, proto_index, pd)
472         int dgn, proto_index;
473         struct proto_dungeon *pd;
474 {
475         s_level *new_level;
476         struct tmplevel *tlevel = &pd->tmplevel[proto_index];
477
478         pd->final_lev[proto_index] = (s_level *) 0; /* no "real" level */
479 #ifdef WIZARD
480         if (!wizard)
481 #endif
482             if (tlevel->chance <= rn2(100)) return;
483
484         pd->final_lev[proto_index] = new_level =
485                                         (s_level *) alloc(sizeof(s_level));
486         /* load new level with data */
487         Strcpy(new_level->proto, tlevel->name);
488         new_level->boneid = tlevel->boneschar;
489         new_level->dlevel.dnum = dgn;
490         new_level->dlevel.dlevel = 0;   /* for now */
491
492         new_level->flags.town = !!(tlevel->flags & TOWN);
493         new_level->flags.hellish = !!(tlevel->flags & HELLISH);
494         new_level->flags.maze_like = !!(tlevel->flags & MAZELIKE);
495         new_level->flags.rogue_like = !!(tlevel->flags & ROGUELIKE);
496         new_level->flags.align = ((tlevel->flags & D_ALIGN_MASK) >> 4);
497         if (!new_level->flags.align) 
498             new_level->flags.align =
499                 ((pd->tmpdungeon[dgn].flags & D_ALIGN_MASK) >> 4);
500
501         new_level->rndlevs = tlevel->rndlevs;
502         new_level->next    = (s_level *) 0;
503 }
504
505 STATIC_OVL int
506 possible_places(idx, map, pd)
507     int idx;            /* prototype index */
508     boolean *map;       /* array MAXLEVEL+1 in length */
509     struct proto_dungeon *pd;
510 {
511     int i, start, count;
512     s_level *lev = pd->final_lev[idx];
513
514     /* init level possibilities */
515     for (i = 0; i <= MAXLEVEL; i++) map[i] = FALSE;
516
517     /* get base and range and set those entried to true */
518     count = level_range(lev->dlevel.dnum, pd->tmplevel[idx].lev.base,
519                                         pd->tmplevel[idx].lev.rand,
520                                         pd->tmplevel[idx].chain,
521                                         pd, &start);
522     for (i = start; i < start+count; i++)
523         map[i] = TRUE;
524
525     /* mark off already placed levels */
526     for (i = pd->start; i < idx; i++) {
527         if (pd->final_lev[i] && map[pd->final_lev[i]->dlevel.dlevel]) {
528             map[pd->final_lev[i]->dlevel.dlevel] = FALSE;
529             --count;
530         }
531     }
532
533     return count;
534 }
535
536 /* Pick the nth TRUE entry in the given boolean array. */
537 STATIC_OVL xchar
538 pick_level(map, nth)
539     boolean *map;       /* an array MAXLEVEL+1 in size */
540     int nth;
541 {
542     int i;
543     for (i = 1; i <= MAXLEVEL; i++)
544         if (map[i] && !nth--) return (xchar) i;
545     panic("pick_level:  ran out of valid levels");
546     return 0;
547 }
548
549 #ifdef DDEBUG
550 static void FDECL(indent,(int));
551
552 static void
553 indent(d)
554 int d;
555 {
556     while (d-- > 0) fputs("    ", stderr);
557 }
558 #endif
559
560 /*
561  * Place a level.  First, find the possible places on a dungeon map
562  * template.  Next pick one.  Then try to place the next level.  If
563  * sucessful, we're done.  Otherwise, try another (and another) until
564  * all possible places have been tried.  If all possible places have
565  * been exausted, return false.
566  */
567 STATIC_OVL boolean
568 place_level(proto_index, pd)
569     int proto_index;
570     struct proto_dungeon *pd;
571 {
572     boolean map[MAXLEVEL+1];    /* valid levels are 1..MAXLEVEL inclusive */
573     s_level *lev;
574     int npossible;
575 #ifdef DDEBUG
576     int i;
577 #endif
578
579     if (proto_index == pd->n_levs) return TRUE; /* at end of proto levels */
580
581     lev = pd->final_lev[proto_index];
582
583     /* No level created for this prototype, goto next. */
584     if (!lev) return place_level(proto_index+1, pd);
585
586     npossible = possible_places(proto_index, map, pd);
587
588     for (; npossible; --npossible) {
589         lev->dlevel.dlevel = pick_level(map, rn2(npossible));
590 #ifdef DDEBUG
591         indent(proto_index-pd->start);
592         fprintf(stderr,"%s: trying %d [ ", lev->proto, lev->dlevel.dlevel);
593         for (i = 1; i <= MAXLEVEL; i++)
594             if (map[i]) fprintf(stderr,"%d ", i);
595         fprintf(stderr,"]\n");
596 #endif
597         if (place_level(proto_index+1, pd)) return TRUE;
598         map[lev->dlevel.dlevel] = FALSE;        /* this choice didn't work */
599     }
600 #ifdef DDEBUG
601     indent(proto_index-pd->start);
602     fprintf(stderr,"%s: failed\n", lev->proto);
603 #endif
604     return FALSE;
605 }
606
607
608 struct level_map {
609         const char *lev_name;
610         d_level *lev_spec;
611 } level_map[] = {
612         { "air",        &air_level },
613         { "asmodeus",   &asmodeus_level },
614         { "astral",     &astral_level },
615         { "baalz",      &baalzebub_level },
616         { "bigroom",    &bigroom_level },
617         { "castle",     &stronghold_level },
618         { "earth",      &earth_level },
619         { "fakewiz1",   &portal_level },
620         { "fire",       &fire_level },
621         { "juiblex",    &juiblex_level },
622         { "knox",       &knox_level },
623         { "medusa",     &medusa_level },
624         { "oracle",     &oracle_level },
625         { "orcus",      &orcus_level },
626 #ifdef REINCARNATION
627         { "rogue",      &rogue_level },
628 #endif
629         { "sanctum",    &sanctum_level },
630         { "valley",     &valley_level },
631         { "water",      &water_level },
632         { "wizard1",    &wiz1_level },
633         { "wizard2",    &wiz2_level },
634         { "wizard3",    &wiz3_level },
635         { X_START,      &qstart_level },
636         { X_LOCATE,     &qlocate_level },
637         { X_GOAL,       &nemesis_level },
638         { "",           (d_level *)0 }
639 };
640
641 void
642 init_dungeons()         /* initialize the "dungeon" structs */
643 {
644         dlb     *dgn_file;
645         register int i, cl = 0, cb = 0;
646         register s_level *x;
647         struct proto_dungeon pd;
648         struct level_map *lev_map;
649         struct version_info vers_info;
650
651         pd.n_levs = pd.n_brs = 0;
652
653         dgn_file = dlb_fopen(DUNGEON_FILE, RDBMODE);
654         if (!dgn_file) {
655             char tbuf[BUFSZ];
656             Sprintf(tbuf, "Cannot open dungeon description - \"%s",
657                 DUNGEON_FILE);
658 #ifdef DLBRSRC /* using a resource from the executable */
659             Strcat(tbuf, "\" resource!");
660 #else /* using a file or DLB file */
661 # if defined(DLB)
662             Strcat(tbuf, "\" from ");
663 #  ifdef PREFIXES_IN_USE
664             Strcat(tbuf, "\n\"");
665             if (fqn_prefix[DATAPREFIX]) Strcat(tbuf, fqn_prefix[DATAPREFIX]);
666 #  else
667             Strcat(tbuf, "\"");
668 #  endif
669             Strcat(tbuf, DLBFILE);
670 # endif
671             Strcat(tbuf, "\" file!");
672 #endif
673 #ifdef WIN32
674             interject_assistance(1, INTERJECT_PANIC, (genericptr_t)tbuf,
675                                  (genericptr_t)fqn_prefix[DATAPREFIX]);
676 #endif
677             panic(tbuf);
678         }
679
680         /* validate the data's version against the program's version */
681         Fread((genericptr_t) &vers_info, sizeof vers_info, 1, dgn_file);
682         /* we'd better clear the screen now, since when error messages come from
683          * check_version() they will be printed using pline(), which doesn't
684          * mix with the raw messages that might be already on the screen
685          */
686         if (iflags.window_inited) clear_nhwindow(WIN_MAP);
687         if (!check_version(&vers_info, DUNGEON_FILE, TRUE))
688             panic("Dungeon description not valid.");
689
690         /*
691          * Read in each dungeon and transfer the results to the internal
692          * dungeon arrays.
693          */
694         sp_levchn = (s_level *) 0;
695         Fread((genericptr_t)&n_dgns, sizeof(int), 1, dgn_file);
696         if (n_dgns >= MAXDUNGEON)
697             panic("init_dungeons: too many dungeons");
698
699         for (i = 0; i < n_dgns; i++) {
700             Fread((genericptr_t)&pd.tmpdungeon[i],
701                                     sizeof(struct tmpdungeon), 1, dgn_file);
702 #ifdef WIZARD
703             if(!wizard)
704 #endif
705               if(pd.tmpdungeon[i].chance && (pd.tmpdungeon[i].chance <= rn2(100))) {
706                 int j;
707
708                 /* skip over any levels or branches */
709                 for(j = 0; j < pd.tmpdungeon[i].levels; j++)
710                     Fread((genericptr_t)&pd.tmplevel[cl], sizeof(struct tmplevel),
711                                                         1, dgn_file);
712
713                 for(j = 0; j < pd.tmpdungeon[i].branches; j++)
714                     Fread((genericptr_t)&pd.tmpbranch[cb],
715                                         sizeof(struct tmpbranch), 1, dgn_file);
716                 n_dgns--; i--;
717                 continue;
718               }
719
720             Strcpy(dungeons[i].dname, pd.tmpdungeon[i].name);
721             Strcpy(dungeons[i].proto, pd.tmpdungeon[i].protoname);
722             dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
723
724             if(pd.tmpdungeon[i].lev.rand)
725                 dungeons[i].num_dunlevs = (xchar)rn1(pd.tmpdungeon[i].lev.rand,
726                                                      pd.tmpdungeon[i].lev.base);
727             else dungeons[i].num_dunlevs = (xchar)pd.tmpdungeon[i].lev.base;
728
729             if(!i) {
730                 dungeons[i].ledger_start = 0;
731                 dungeons[i].depth_start = 1;
732                 dungeons[i].dunlev_ureached = 1;
733             } else {
734                 dungeons[i].ledger_start = dungeons[i-1].ledger_start +
735                                               dungeons[i-1].num_dunlevs;
736                 dungeons[i].dunlev_ureached = 0;
737             }
738
739             dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH);
740             dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE);
741             dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE);
742             dungeons[i].flags.align = ((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4);
743             /*
744              * Set the entry level for this dungeon.  The pd.tmpdungeon entry
745              * value means:
746              *          < 0     from bottom (-1 == bottom level)
747              *            0     default (top)
748              *          > 0     actual level (1 = top)
749              *
750              * Note that the entry_lev field in the dungeon structure is
751              * redundant.  It is used only here and in print_dungeon().
752              */
753             if (pd.tmpdungeon[i].entry_lev < 0) {
754                 dungeons[i].entry_lev = dungeons[i].num_dunlevs +
755                                                 pd.tmpdungeon[i].entry_lev + 1;
756                 if (dungeons[i].entry_lev <= 0) dungeons[i].entry_lev = 1;
757             } else if (pd.tmpdungeon[i].entry_lev > 0) {
758                 dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
759                 if (dungeons[i].entry_lev > dungeons[i].num_dunlevs)
760                     dungeons[i].entry_lev = dungeons[i].num_dunlevs;
761             } else { /* default */
762                 dungeons[i].entry_lev = 1;      /* defaults to top level */
763             }
764
765             if (i) {    /* set depth */
766                 branch *br;
767                 schar from_depth;
768                 boolean from_up;
769
770                 br = add_branch(i, dungeons[i].entry_lev, &pd);
771
772                 /* Get the depth of the connecting end. */
773                 if (br->end1.dnum == i) {
774                     from_depth = depth(&br->end2);
775                     from_up = !br->end1_up;
776                 } else {
777                     from_depth = depth(&br->end1);
778                     from_up = br->end1_up;
779                 }
780
781                 /*
782                  * Calculate the depth of the top of the dungeon via
783                  * its branch.  First, the depth of the entry point:
784                  *
785                  *      depth of branch from "parent" dungeon
786                  *      + -1 or 1 depending on a up or down stair or
787                  *        0 if portal
788                  *
789                  * Followed by the depth of the top of the dungeon:
790                  *
791                  *      - (entry depth - 1)
792                  *
793                  * We'll say that portals stay on the same depth.
794                  */
795                 dungeons[i].depth_start = from_depth
796                                         + (br->type == BR_PORTAL ? 0 :
797                                                         (from_up ? -1 : 1))
798                                         - (dungeons[i].entry_lev - 1);
799             }
800
801             /* this is redundant - it should have been flagged by dgn_comp */
802             if(dungeons[i].num_dunlevs > MAXLEVEL)
803                 dungeons[i].num_dunlevs = MAXLEVEL;
804
805             pd.start = pd.n_levs;       /* save starting point */
806             pd.n_levs += pd.tmpdungeon[i].levels;
807             if (pd.n_levs > LEV_LIMIT)
808                 panic("init_dungeon: too many special levels");
809             /*
810              * Read in the prototype special levels.  Don't add generated
811              * special levels until they are all placed.
812              */
813             for(; cl < pd.n_levs; cl++) {
814                 Fread((genericptr_t)&pd.tmplevel[cl],
815                                         sizeof(struct tmplevel), 1, dgn_file);
816                 init_level(i, cl, &pd);
817             }
818             /*
819              * Recursively place the generated levels for this dungeon.  This
820              * routine will attempt all possible combinations before giving
821              * up.
822              */
823             if (!place_level(pd.start, &pd))
824                 panic("init_dungeon:  couldn't place levels");
825 #ifdef DDEBUG
826             fprintf(stderr, "--- end of dungeon %d ---\n", i);
827             fflush(stderr);
828             getchar();
829 #endif
830             for (; pd.start < pd.n_levs; pd.start++)
831                 if (pd.final_lev[pd.start]) add_level(pd.final_lev[pd.start]);
832
833
834             pd.n_brs += pd.tmpdungeon[i].branches;
835             if (pd.n_brs > BRANCH_LIMIT)
836                 panic("init_dungeon: too many branches");
837             for(; cb < pd.n_brs; cb++)
838                 Fread((genericptr_t)&pd.tmpbranch[cb],
839                                         sizeof(struct tmpbranch), 1, dgn_file);
840         }
841         (void) dlb_fclose(dgn_file);
842
843         for (i = 0; i < 5; i++) tune[i] = 'A' + rn2(7);
844         tune[5] = 0;
845
846         /*
847          * Find most of the special levels and dungeons so we can access their
848          * locations quickly.
849          */
850         for (lev_map = level_map; lev_map->lev_name[0]; lev_map++) {
851                 x = find_level(lev_map->lev_name);
852                 if (x) {
853                         assign_level(lev_map->lev_spec, &x->dlevel);
854                         if (!strncmp(lev_map->lev_name, "x-", 2)) {
855                                 /* This is where the name substitution on the
856                                  * levels of the quest dungeon occur.
857                                  */
858                                 Sprintf(x->proto, "%s%s", urole.filecode, &lev_map->lev_name[1]);
859                         } else if (lev_map->lev_spec == &knox_level) {
860                                 branch *br;
861                                 /*
862                                  * Kludge to allow floating Knox entrance.  We
863                                  * specify a floating entrance by the fact that
864                                  * its entrance (end1) has a bogus dnum, namely
865                                  * n_dgns.
866                                  */
867                                 for (br = branches; br; br = br->next)
868                                     if (on_level(&br->end2, &knox_level)) break;
869
870                                 if (br) br->end1.dnum = n_dgns;
871                                 /* adjust the branch's position on the list */
872                                 insert_branch(br, TRUE);
873                         }
874                 }
875         }
876 /*
877  *      I hate hardwiring these names. :-(
878  */
879         quest_dnum = dname_to_dnum("The Quest");
880         sokoban_dnum = dname_to_dnum("Sokoban");
881         mines_dnum = dname_to_dnum("The Gnomish Mines");
882         tower_dnum = dname_to_dnum("Vlad's Tower");
883
884         /* one special fixup for dummy surface level */
885         if ((x = find_level("dummy")) != 0) {
886             i = x->dlevel.dnum;
887             /* the code above puts earth one level above dungeon level #1,
888                making the dummy level overlay level 1; but the whole reason
889                for having the dummy level is to make earth have depth -1
890                instead of 0, so adjust the start point to shift endgame up */
891             if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
892                 dungeons[i].depth_start -= 1;
893             /* TO DO: strip "dummy" out all the way here,
894                so that it's hidden from <ctrl/O> feedback. */
895         }
896
897 #ifdef DEBUG
898         dumpit();
899 #endif
900 }
901
902 xchar
903 dunlev(lev)     /* return the level number for lev in *this* dungeon */
904 d_level *lev;
905 {
906         return(lev->dlevel);
907 }
908
909 xchar
910 dunlevs_in_dungeon(lev) /* return the lowest level number for *this* dungeon*/
911 d_level *lev;
912 {
913         return(dungeons[lev->dnum].num_dunlevs);
914 }
915
916 xchar
917 deepest_lev_reached(noquest) /* return the lowest level explored in the game*/
918 boolean noquest;
919 {
920         /* this function is used for three purposes: to provide a factor
921          * of difficulty in monster generation; to provide a factor of
922          * difficulty in experience calculations (botl.c and end.c); and
923          * to insert the deepest level reached in the game in the topten
924          * display.  the 'noquest' arg switch is required for the latter.
925          *
926          * from the player's point of view, going into the Quest is _not_
927          * going deeper into the dungeon -- it is going back "home", where
928          * the dungeon starts at level 1.  given the setup in dungeon.def,
929          * the depth of the Quest (thought of as starting at level 1) is
930          * never lower than the level of entry into the Quest, so we exclude
931          * the Quest from the topten "deepest level reached" display
932          * calculation.  _However_ the Quest is a difficult dungeon, so we
933          * include it in the factor of difficulty calculations.
934          */
935         register int i;
936         d_level tmp;
937         register schar ret = 0;
938
939         for(i = 0; i < n_dgns; i++) {
940             if((tmp.dlevel = dungeons[i].dunlev_ureached) == 0) continue;
941             if(!strcmp(dungeons[i].dname, "The Quest") && noquest) continue;
942
943             tmp.dnum = i;
944             if(depth(&tmp) > ret) ret = depth(&tmp);
945         }
946         return((xchar) ret);
947 }
948
949 /* return a bookkeeping level number for purpose of comparisons and
950  * save/restore */
951 xchar
952 ledger_no(lev)
953 d_level *lev;
954 {
955         return((xchar)(lev->dlevel + dungeons[lev->dnum].ledger_start));
956 }
957
958 /*
959  * The last level in the bookkeeping list of level is the bottom of the last
960  * dungeon in the dungeons[] array.
961  *
962  * Maxledgerno() -- which is the max number of levels in the bookkeeping
963  * list, should not be confused with dunlevs_in_dungeon(lev) -- which
964  * returns the max number of levels in lev's dungeon, and both should
965  * not be confused with deepest_lev_reached() -- which returns the lowest
966  * depth visited by the player.
967  */
968 xchar
969 maxledgerno()
970 {
971     return (xchar) (dungeons[n_dgns-1].ledger_start +
972                                 dungeons[n_dgns-1].num_dunlevs);
973 }
974
975 /* return the dungeon that this ledgerno exists in */
976 xchar
977 ledger_to_dnum(ledgerno)
978 xchar   ledgerno;
979 {
980         register int i;
981
982         /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
983         for (i = 0; i < n_dgns; i++)
984             if (dungeons[i].ledger_start < ledgerno &&
985                 ledgerno <= dungeons[i].ledger_start + dungeons[i].num_dunlevs)
986                 return (xchar)i;
987
988         panic("level number out of range [ledger_to_dnum(%d)]", (int)ledgerno);
989         /*NOT REACHED*/
990         return (xchar)0;
991 }
992
993 /* return the level of the dungeon this ledgerno exists in */
994 xchar
995 ledger_to_dlev(ledgerno)
996 xchar   ledgerno;
997 {
998         return((xchar)(ledgerno - dungeons[ledger_to_dnum(ledgerno)].ledger_start));
999 }
1000
1001 #endif /* OVL1 */
1002 #ifdef OVL0
1003
1004 /* returns the depth of a level, in floors below the surface    */
1005 /* (note levels in different dungeons can have the same depth). */
1006 schar
1007 depth(lev)
1008 d_level *lev;
1009 {
1010         return((schar)( dungeons[lev->dnum].depth_start + lev->dlevel - 1));
1011 }
1012
1013 boolean
1014 on_level(lev1, lev2)    /* are "lev1" and "lev2" actually the same? */
1015 d_level *lev1, *lev2;
1016 {
1017         return((boolean)((lev1->dnum == lev2->dnum) && (lev1->dlevel == lev2->dlevel)));
1018 }
1019
1020 #endif /* OVL0 */
1021 #ifdef OVL1
1022
1023 /* is this level referenced in the special level chain? */
1024 s_level *
1025 Is_special(lev)
1026 d_level *lev;
1027 {
1028         s_level *levtmp;
1029
1030         for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
1031             if (on_level(lev, &levtmp->dlevel)) return(levtmp);
1032
1033         return((s_level *)0);
1034 }
1035
1036 /*
1037  * Is this a multi-dungeon branch level?  If so, return a pointer to the
1038  * branch.  Otherwise, return null.
1039  */
1040 branch *
1041 Is_branchlev(lev)
1042         d_level *lev;
1043 {
1044         branch *curr;
1045
1046         for (curr = branches; curr; curr = curr->next) {
1047             if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
1048                 return curr;
1049         }
1050         return (branch *) 0;
1051 }
1052
1053 /* goto the next level (or appropriate dungeon) */
1054 void
1055 next_level(at_stairs)
1056 boolean at_stairs;
1057 {
1058         if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1059                 /* Taking a down dungeon branch. */
1060                 goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1061         } else {
1062                 /* Going down a stairs or jump in a trap door. */
1063                 d_level newlevel;
1064
1065                 newlevel.dnum = u.uz.dnum;
1066                 newlevel.dlevel = u.uz.dlevel + 1;
1067                 goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
1068         }
1069 }
1070
1071 /* goto the previous level (or appropriate dungeon) */
1072 void
1073 prev_level(at_stairs)
1074 boolean at_stairs;
1075 {
1076         if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
1077                 /* Taking an up dungeon branch. */
1078                 /* KMH -- Upwards branches are okay if not level 1 */
1079                 /* (Just make sure it doesn't go above depth 1) */
1080                 if(!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet) done(ESCAPED);
1081                 else goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
1082         } else {
1083                 /* Going up a stairs or rising through the ceiling. */
1084                 d_level newlevel;
1085                 newlevel.dnum = u.uz.dnum;
1086                 newlevel.dlevel = u.uz.dlevel - 1;
1087                 goto_level(&newlevel, at_stairs, FALSE, FALSE);
1088         }
1089 }
1090
1091 void
1092 u_on_newpos(x, y)
1093 int x, y;
1094 {
1095         u.ux = x;
1096         u.uy = y;
1097 #ifdef CLIPPING
1098         cliparound(u.ux, u.uy);
1099 #endif
1100 #ifdef STEED
1101         /* ridden steed always shares hero's location */
1102         if (u.usteed) u.usteed->mx = u.ux, u.usteed->my = u.uy;
1103 #endif
1104 }
1105
1106 void
1107 u_on_sstairs() {        /* place you on the special staircase */
1108
1109         if (sstairs.sx) {
1110             u_on_newpos(sstairs.sx, sstairs.sy);
1111         } else {
1112             /* code stolen from goto_level */
1113             int trycnt = 0;
1114             xchar x, y;
1115 #ifdef DEBUG
1116             pline("u_on_sstairs: picking random spot");
1117 #endif
1118 #define badspot(x,y) ((levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y))
1119             do {
1120                 x = rnd(COLNO-1);
1121                 y = rn2(ROWNO);
1122                 if (!badspot(x, y)) {
1123                     u_on_newpos(x, y);
1124                     return;
1125                 }
1126             } while (++trycnt <= 500);
1127             panic("u_on_sstairs: could not relocate player!");
1128 #undef badspot
1129         }
1130 }
1131
1132 void
1133 u_on_upstairs() /* place you on upstairs (or special equivalent) */
1134 {
1135         if (xupstair) {
1136                 u_on_newpos(xupstair, yupstair);
1137         } else
1138                 u_on_sstairs();
1139 }
1140
1141 void
1142 u_on_dnstairs() /* place you on dnstairs (or special equivalent) */
1143 {
1144         if (xdnstair) {
1145                 u_on_newpos(xdnstair, ydnstair);
1146         } else
1147                 u_on_sstairs();
1148 }
1149
1150 boolean
1151 On_stairs(x, y)
1152 xchar x, y;
1153 {
1154         return((boolean)((x == xupstair && y == yupstair) ||
1155                (x == xdnstair && y == ydnstair) ||
1156                (x == xdnladder && y == ydnladder) ||
1157                (x == xupladder && y == yupladder) ||
1158                (x == sstairs.sx && y == sstairs.sy)));
1159 }
1160
1161 boolean
1162 Is_botlevel(lev)
1163 d_level *lev;
1164 {
1165         return((boolean)(lev->dlevel == dungeons[lev->dnum].num_dunlevs));
1166 }
1167
1168 boolean
1169 Can_dig_down(lev)
1170 d_level *lev;
1171 {
1172         return((boolean)(!level.flags.hardfloor
1173             && !Is_botlevel(lev) && !Invocation_lev(lev)));
1174 }
1175
1176 /*
1177  * Like Can_dig_down (above), but also allows falling through on the
1178  * stronghold level.  Normally, the bottom level of a dungeon resists
1179  * both digging and falling.
1180  */
1181 boolean
1182 Can_fall_thru(lev)
1183 d_level *lev;
1184 {
1185         return((boolean)(Can_dig_down(lev) || Is_stronghold(lev)));
1186 }
1187
1188 /*
1189  * True if one can rise up a level (e.g. cursed gain level).
1190  * This happens on intermediate dungeon levels or on any top dungeon
1191  * level that has a stairwell style branch to the next higher dungeon.
1192  * Checks for amulets and such must be done elsewhere.
1193  */
1194 boolean
1195 Can_rise_up(x, y, lev)
1196 int     x, y;
1197 d_level *lev;
1198 {
1199     /* can't rise up from inside the top of the Wizard's tower */
1200     /* KMH -- or in sokoban */
1201     if (In_endgame(lev) || In_sokoban(lev) ||
1202                         (Is_wiz1_level(lev) && In_W_tower(x, y, lev)))
1203         return FALSE;
1204     return (boolean)(lev->dlevel > 1 ||
1205                 (dungeons[lev->dnum].entry_lev == 1 && ledger_no(lev) != 1 &&
1206                  sstairs.sx && sstairs.up));
1207 }
1208
1209 /*
1210  * It is expected that the second argument of get_level is a depth value,
1211  * either supplied by the user (teleport control) or randomly generated.
1212  * But more than one level can be at the same depth.  If the target level
1213  * is "above" the present depth location, get_level must trace "up" from
1214  * the player's location (through the ancestors dungeons) the dungeon
1215  * within which the target level is located.  With only one exception
1216  * which does not pass through this routine (see level_tele), teleporting
1217  * "down" is confined to the current dungeon.  At present, level teleport
1218  * in dungeons that build up is confined within them.
1219  */
1220 void
1221 get_level(newlevel, levnum)
1222 d_level *newlevel;
1223 int levnum;
1224 {
1225         branch *br;
1226         xchar dgn = u.uz.dnum;
1227
1228         if (levnum <= 0) {
1229             /* can only currently happen in endgame */
1230             levnum = u.uz.dlevel;
1231         } else if (levnum > dungeons[dgn].depth_start
1232                             + dungeons[dgn].num_dunlevs - 1) {
1233             /* beyond end of dungeon, jump to last level */
1234             levnum = dungeons[dgn].num_dunlevs;
1235         } else {
1236             /* The desired level is in this dungeon or a "higher" one. */
1237
1238             /*
1239              * Branch up the tree until we reach a dungeon that contains the
1240              * levnum.
1241              */
1242             if (levnum < dungeons[dgn].depth_start) {
1243
1244                 do {
1245                     /*
1246                      * Find the parent dungeon of this dungeon.
1247                      *
1248                      * This assumes that end2 is always the "child" and it is
1249                      * unique.
1250                      */
1251                     for (br = branches; br; br = br->next)
1252                         if (br->end2.dnum == dgn) break;
1253                     if (!br)
1254                         panic("get_level: can't find parent dungeon");
1255
1256                     dgn = br->end1.dnum;
1257                 } while (levnum < dungeons[dgn].depth_start);
1258             }
1259
1260             /* We're within the same dungeon; calculate the level. */
1261             levnum = levnum - dungeons[dgn].depth_start + 1;
1262         }
1263
1264         newlevel->dnum = dgn;
1265         newlevel->dlevel = levnum;
1266 }
1267
1268 #endif /* OVL1 */
1269 #ifdef OVL0
1270
1271 boolean
1272 In_quest(lev)   /* are you in the quest dungeon? */
1273 d_level *lev;
1274 {
1275         return((boolean)(lev->dnum == quest_dnum));
1276 }
1277
1278 #endif /* OVL0 */
1279 #ifdef OVL1
1280
1281 boolean
1282 In_mines(lev)   /* are you in the mines dungeon? */
1283 d_level *lev;
1284 {
1285         return((boolean)(lev->dnum == mines_dnum));
1286 }
1287
1288 /*
1289  * Return the branch for the given dungeon.
1290  *
1291  * This function assumes:
1292  *      + This is not called with "Dungeons of Doom".
1293  *      + There is only _one_ branch to a given dungeon.
1294  *      + Field end2 is the "child" dungeon.
1295  */
1296 branch *
1297 dungeon_branch(s)
1298     const char *s;
1299 {
1300     branch *br;
1301     xchar  dnum;
1302
1303     dnum = dname_to_dnum(s);
1304
1305     /* Find the branch that connects to dungeon i's branch. */
1306     for (br = branches; br; br = br->next)
1307         if (br->end2.dnum == dnum) break;
1308
1309     if (!br) panic("dgn_entrance: can't find entrance to %s", s);
1310
1311     return br;
1312 }
1313
1314 /*
1315  * This returns true if the hero is on the same level as the entrance to
1316  * the named dungeon.
1317  *
1318  * Called from do.c and mklev.c.
1319  *
1320  * Assumes that end1 is always the "parent".
1321  */
1322 boolean
1323 at_dgn_entrance(s)
1324     const char *s;
1325 {
1326     branch *br;
1327
1328     br = dungeon_branch(s);
1329     return((boolean)(on_level(&u.uz, &br->end1) ? TRUE : FALSE));
1330 }
1331
1332 boolean
1333 In_V_tower(lev) /* is `lev' part of Vlad's tower? */
1334 d_level *lev;
1335 {
1336         return((boolean)(lev->dnum == tower_dnum));
1337 }
1338
1339 boolean
1340 On_W_tower_level(lev)   /* is `lev' a level containing the Wizard's tower? */
1341 d_level *lev;
1342 {
1343         return (boolean)(Is_wiz1_level(lev) ||
1344                          Is_wiz2_level(lev) ||
1345                          Is_wiz3_level(lev));
1346 }
1347
1348 boolean
1349 In_W_tower(x, y, lev)   /* is <x,y> of `lev' inside the Wizard's tower? */
1350 int     x, y;
1351 d_level *lev;
1352 {
1353         if (!On_W_tower_level(lev)) return FALSE;
1354         /*
1355          * Both of the exclusion regions for arriving via level teleport
1356          * (from above or below) define the tower's boundary.
1357          *      assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1358          */
1359         if (dndest.nlx > 0)
1360             return (boolean)within_bounded_area(x, y, dndest.nlx, dndest.nly,
1361                                                 dndest.nhx, dndest.nhy);
1362         else
1363             impossible("No boundary for Wizard's Tower?");
1364         return FALSE;
1365 }
1366
1367 #endif /* OVL1 */
1368 #ifdef OVL0
1369
1370 boolean
1371 In_hell(lev)    /* are you in one of the Hell levels? */
1372 d_level *lev;
1373 {
1374         return((boolean)(dungeons[lev->dnum].flags.hellish));
1375 }
1376
1377 #endif /* OVL0 */
1378 #ifdef OVL1
1379
1380 void
1381 find_hell(lev)  /* sets *lev to be the gateway to Gehennom... */
1382 d_level *lev;
1383 {
1384         lev->dnum = valley_level.dnum;
1385         lev->dlevel = 1;
1386 }
1387
1388 void
1389 goto_hell(at_stairs, falling)   /* go directly to hell... */
1390 boolean at_stairs, falling;
1391 {
1392         d_level lev;
1393
1394         find_hell(&lev);
1395         goto_level(&lev, at_stairs, falling, FALSE);
1396 }
1397
1398 void
1399 assign_level(dest, src)         /* equivalent to dest = source */
1400 d_level *dest, *src;
1401 {
1402         dest->dnum = src->dnum;
1403         dest->dlevel = src->dlevel;
1404 }
1405
1406 void
1407 assign_rnd_level(dest, src, range)      /* dest = src + rn1(range) */
1408 d_level *dest, *src;
1409 int range;
1410 {
1411         dest->dnum = src->dnum;
1412         dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range)) ;
1413
1414         if(dest->dlevel > dunlevs_in_dungeon(dest))
1415                 dest->dlevel = dunlevs_in_dungeon(dest);
1416         else if(dest->dlevel < 1)
1417                 dest->dlevel = 1;
1418 }
1419
1420 #endif /* OVL1 */
1421 #ifdef OVL0
1422
1423 int
1424 induced_align(pct)
1425 int     pct;
1426 {
1427         s_level *lev = Is_special(&u.uz);
1428         aligntyp al;
1429
1430         if (lev && lev->flags.align)
1431                 if(rn2(100) < pct) return(lev->flags.align);
1432
1433         if(dungeons[u.uz.dnum].flags.align)
1434                 if(rn2(100) < pct) return(dungeons[u.uz.dnum].flags.align);
1435
1436         al = rn2(3) - 1;
1437         return(Align2amask(al));
1438 }
1439
1440 #endif /* OVL0 */
1441 #ifdef OVL1
1442
1443 boolean
1444 Invocation_lev(lev)
1445 d_level *lev;
1446 {
1447         return((boolean)(In_hell(lev) &&
1448                 lev->dlevel == (dungeons[lev->dnum].num_dunlevs - 1)));
1449 }
1450
1451 /* use instead of depth() wherever a degree of difficulty is made
1452  * dependent on the location in the dungeon (eg. monster creation).
1453  */
1454 xchar
1455 level_difficulty()
1456 {
1457         if (In_endgame(&u.uz))
1458                 return((xchar)(depth(&sanctum_level) + u.ulevel/2));
1459         else
1460                 if (u.uhave.amulet)
1461                         return(deepest_lev_reached(FALSE));
1462                 else
1463                         return((xchar) depth(&u.uz));
1464 }
1465
1466 /* Take one word and try to match it to a level.
1467  * Recognized levels are as shown by print_dungeon().
1468  */
1469 schar
1470 lev_by_name(nam)
1471 const char *nam;
1472 {
1473     schar lev = 0;
1474     s_level *slev;
1475     d_level dlev;
1476     const char *p;
1477     int idx, idxtoo;
1478     char buf[BUFSZ];
1479
1480     /* allow strings like "the oracle level" to find "oracle" */
1481     if (!strncmpi(nam, "the ", 4)) nam += 4;
1482     if ((p = strstri(nam, " level")) != 0 && p == eos((char*)nam) - 6) {
1483         nam = strcpy(buf, nam);
1484         *(eos(buf) - 6) = '\0';
1485     }
1486     /* hell is the old name, and wouldn't match; gehennom would match its
1487        branch, yielding the castle level instead of the valley of the dead */
1488     if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
1489         if (In_V_tower(&u.uz)) nam = " to Vlad's tower";  /* branch to... */
1490         else nam = "valley";
1491     }
1492
1493     if ((slev = find_level(nam)) != 0) {
1494         dlev = slev->dlevel;
1495         idx = ledger_no(&dlev);
1496         if ((dlev.dnum == u.uz.dnum ||
1497                 /* within same branch, or else main dungeon <-> gehennom */
1498                 (u.uz.dnum == valley_level.dnum &&
1499                         dlev.dnum == medusa_level.dnum) ||
1500                 (u.uz.dnum == medusa_level.dnum &&
1501                         dlev.dnum == valley_level.dnum)) &&
1502             (   /* either wizard mode or else seen and not forgotten */
1503 #ifdef WIZARD
1504              wizard ||
1505 #endif
1506                 (level_info[idx].flags & (FORGOTTEN|VISITED)) == VISITED)) {
1507             lev = depth(&slev->dlevel);
1508         }
1509     } else {    /* not a specific level; try branch names */
1510         idx = find_branch(nam, (struct proto_dungeon *)0);
1511         /* "<branch> to Xyzzy" */
1512         if (idx < 0 && (p = strstri(nam, " to ")) != 0)
1513             idx = find_branch(p + 4, (struct proto_dungeon *)0);
1514
1515         if (idx >= 0) {
1516             idxtoo = (idx >> 8) & 0x00FF;
1517             idx &= 0x00FF;
1518             if (  /* either wizard mode, or else _both_ sides of branch seen */
1519 #ifdef WIZARD
1520                 wizard ||
1521 #endif
1522                 ((level_info[idx].flags & (FORGOTTEN|VISITED)) == VISITED &&
1523                  (level_info[idxtoo].flags & (FORGOTTEN|VISITED)) == VISITED)) {
1524                 if (ledger_to_dnum(idxtoo) == u.uz.dnum) idx = idxtoo;
1525                 dlev.dnum = ledger_to_dnum(idx);
1526                 dlev.dlevel = ledger_to_dlev(idx);
1527                 lev = depth(&dlev);
1528             }
1529         }
1530     }
1531     return lev;
1532 }
1533
1534 #ifdef WIZARD
1535
1536 /* Convert a branch type to a string usable by print_dungeon(). */
1537 STATIC_OVL const char *
1538 br_string(type)
1539     int type;
1540 {
1541     switch (type) {
1542         case BR_PORTAL:  return "Portal";
1543         case BR_NO_END1: return "Connection";
1544         case BR_NO_END2: return "One way stair";
1545         case BR_STAIR:   return "Stair";
1546     }
1547     return " (unknown)";
1548 }
1549
1550 /* Print all child branches between the lower and upper bounds. */
1551 STATIC_OVL void
1552 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices)
1553     winid win;
1554     int   dnum;
1555     int   lower_bound;
1556     int   upper_bound;
1557     boolean bymenu;
1558     struct lchoice *lchoices;
1559 {
1560     branch *br;
1561     char buf[BUFSZ];
1562     anything any;
1563
1564     /* This assumes that end1 is the "parent". */
1565     for (br = branches; br; br = br->next) {
1566         if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel &&
1567                                         br->end1.dlevel <= upper_bound) {
1568             Sprintf(buf,"   %s to %s: %d",
1569                     br_string(br->type),
1570                     dungeons[br->end2.dnum].dname,
1571                     depth(&br->end1));
1572             if (bymenu) {
1573                 lchoices->lev[lchoices->idx] = br->end1.dlevel;
1574                 lchoices->dgn[lchoices->idx] = br->end1.dnum;
1575                 lchoices->playerlev[lchoices->idx] = depth(&br->end1);
1576                 any.a_void = 0;
1577                 any.a_int = lchoices->idx + 1;
1578                 add_menu(win, NO_GLYPH, &any, lchoices->menuletter,
1579                                 0, ATR_NONE, buf, MENU_UNSELECTED);
1580                 if (lchoices->menuletter == 'z') lchoices->menuletter = 'A';
1581                 else lchoices->menuletter++;
1582                 lchoices->idx++;
1583             } else
1584                 putstr(win, 0, buf);
1585         }
1586     }
1587 }
1588
1589 /* Print available dungeon information. */
1590 schar
1591 print_dungeon(bymenu, rlev, rdgn)
1592 boolean bymenu;
1593 schar *rlev;
1594 xchar *rdgn;
1595 {
1596     int     i, last_level, nlev;
1597     char    buf[BUFSZ];
1598     boolean first;
1599     s_level *slev;
1600     dungeon *dptr;
1601     branch  *br;
1602     anything any;
1603     struct lchoice lchoices;
1604
1605     winid   win = create_nhwindow(NHW_MENU);
1606     if (bymenu) {
1607         start_menu(win);
1608         lchoices.idx = 0;
1609         lchoices.menuletter = 'a';
1610     }
1611
1612     for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
1613         nlev = dptr->num_dunlevs;
1614         if (nlev > 1)
1615             Sprintf(buf, "%s: levels %d to %d", dptr->dname, dptr->depth_start,
1616                                                 dptr->depth_start + nlev - 1);
1617         else
1618             Sprintf(buf, "%s: level %d", dptr->dname, dptr->depth_start);
1619
1620         /* Most entrances are uninteresting. */
1621         if (dptr->entry_lev != 1) {
1622             if (dptr->entry_lev == nlev)
1623                 Strcat(buf, ", entrance from below");
1624             else
1625                 Sprintf(eos(buf), ", entrance on %d",
1626                         dptr->depth_start + dptr->entry_lev - 1);
1627         }
1628         if (bymenu) {
1629             any.a_void = 0;
1630             add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf, MENU_UNSELECTED);
1631         } else
1632             putstr(win, 0, buf);
1633
1634         /*
1635          * Circle through the special levels to find levels that are in
1636          * this dungeon.
1637          */
1638         for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
1639             if (slev->dlevel.dnum != i) continue;
1640
1641             /* print any branches before this level */
1642             print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu, &lchoices);
1643
1644             Sprintf(buf, "   %s: %d", slev->proto, depth(&slev->dlevel));
1645             if (Is_stronghold(&slev->dlevel))
1646                 Sprintf(eos(buf), " (tune %s)", tune);
1647             if (bymenu) {
1648                 /* If other floating branches are added, this will need to change */
1649                 if (i != knox_level.dnum) {
1650                         lchoices.lev[lchoices.idx] = slev->dlevel.dlevel;
1651                         lchoices.dgn[lchoices.idx] = i;
1652                 } else {
1653                         lchoices.lev[lchoices.idx] = depth(&slev->dlevel);
1654                         lchoices.dgn[lchoices.idx] = 0;
1655                 }
1656                 lchoices.playerlev[lchoices.idx] = depth(&slev->dlevel);
1657                 any.a_void = 0;
1658                 any.a_int = lchoices.idx + 1;
1659                 add_menu(win, NO_GLYPH, &any, lchoices.menuletter,
1660                                 0, ATR_NONE, buf, MENU_UNSELECTED);
1661                 if (lchoices.menuletter == 'z') lchoices.menuletter = 'A';
1662                 else lchoices.menuletter++;
1663                 lchoices.idx++;
1664             } else
1665                 putstr(win, 0, buf);
1666
1667             last_level = slev->dlevel.dlevel;
1668         }
1669         /* print branches after the last special level */
1670         print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
1671     }
1672
1673     /* Print out floating branches (if any). */
1674     for (first = TRUE, br = branches; br; br = br->next) {
1675         if (br->end1.dnum == n_dgns) {
1676             if (first) {
1677                 if (!bymenu) {
1678                     putstr(win, 0, "");
1679                     putstr(win, 0, "Floating branches");
1680                 }
1681                 first = FALSE;
1682             }
1683             Sprintf(buf, "   %s to %s",
1684                         br_string(br->type), dungeons[br->end2.dnum].dname);
1685             if (!bymenu)
1686                 putstr(win, 0, buf);
1687         }
1688     }
1689     if (bymenu) {
1690         int n;
1691         menu_item *selected;
1692         int idx;
1693
1694         end_menu(win, "Level teleport to where:");
1695         n = select_menu(win, PICK_ONE, &selected);
1696         destroy_nhwindow(win);
1697         if (n > 0) {
1698                 idx = selected[0].item.a_int - 1;
1699                 free((genericptr_t)selected);
1700                 if (rlev && rdgn) {
1701                         *rlev = lchoices.lev[idx];
1702                         *rdgn = lchoices.dgn[idx];
1703                         return lchoices.playerlev[idx];
1704                 }
1705         }
1706         return 0;
1707     }
1708
1709     /* I hate searching for the invocation pos while debugging. -dean */
1710     if (Invocation_lev(&u.uz)) {
1711         putstr(win, 0, "");
1712         Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1713                 inv_pos.x, inv_pos.y, u.ux, u.uy);
1714         putstr(win, 0, buf);
1715     }
1716     /*
1717      * The following is based on the assumption that the inter-level portals
1718      * created by the level compiler (not the dungeon compiler) only exist
1719      * one per level (currently true, of course).
1720      */
1721     else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
1722                                 || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
1723         struct trap *trap;
1724         for (trap = ftrap; trap; trap = trap->ntrap)
1725             if (trap->ttyp == MAGIC_PORTAL) break;
1726
1727         putstr(win, 0, "");
1728         if (trap)
1729             Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)",
1730                 trap->tx, trap->ty, u.ux, u.uy);
1731         else
1732             Sprintf(buf, "No portal found.");
1733         putstr(win, 0, buf);
1734     }
1735
1736     display_nhwindow(win, TRUE);
1737     destroy_nhwindow(win);
1738     return 0;
1739 }
1740 #endif /* WIZARD */
1741
1742 #endif /* OVL1 */
1743
1744 /*dungeon.c*/