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
17struct 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
28int n_dgns;				/* number of dungeons (used here,  */
29					/*   and mklev.c)		   */
30static branch *branches = (branch *) 0;	/* dungeon branch list		   */
31
32struct lchoice {
33	int idx;
34	schar lev[MAXLINFO];
35	schar playerlev[MAXLINFO];
36	xchar dgn[MAXLINFO];
37	char menuletter;
38};
39
40static void FDECL(Fread, (genericptr_t, int, int, dlb *));
41STATIC_DCL xchar FDECL(dname_to_dnum, (const char *));
42STATIC_DCL int FDECL(find_branch, (const char *, struct proto_dungeon *));
43STATIC_DCL xchar FDECL(parent_dnum, (const char *, struct proto_dungeon *));
44STATIC_DCL int FDECL(level_range, (XCHAR_P,int,int,int,struct proto_dungeon *,int *));
45STATIC_DCL xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *));
46STATIC_DCL int FDECL(correct_branch_type, (struct tmpbranch *));
47STATIC_DCL branch *FDECL(add_branch, (int, int, struct proto_dungeon *));
48STATIC_DCL void FDECL(add_level, (s_level *));
49STATIC_DCL void FDECL(init_level, (int,int,struct proto_dungeon *));
50STATIC_DCL int FDECL(possible_places, (int, boolean *, struct proto_dungeon *));
51STATIC_DCL xchar FDECL(pick_level, (boolean *, int));
52STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
53#ifdef WIZARD
54STATIC_DCL const char *FDECL(br_string, (int));
55STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, struct lchoice *));
56#endif
57
58#ifdef NETHACK_DEBUG
59#define DD	dungeons[i]
60STATIC_DCL void NDECL(dumpit);
61
62STATIC_OVL void
63dumpit()
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. */
113void
114save_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. */
151void
152restore_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
184static void
185Fread(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
200STATIC_OVL xchar
201dname_to_dnum(s)
202const 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
214s_level *
215find_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. */
225STATIC_OVL int
226find_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 */
257STATIC_OVL xchar
258parent_dnum(s, pd)
259const char	   *s;	/* dungeon name */
260struct 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 */
289STATIC_OVL int
290level_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
322STATIC_OVL xchar
323parent_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. */
350STATIC_OVL int
351correct_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 */
370void
371insert_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. */
417STATIC_OVL branch *
418add_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 */
448STATIC_OVL void
449add_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
470STATIC_OVL void
471init_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
505STATIC_OVL int
506possible_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. */
537STATIC_OVL xchar
538pick_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
550static void FDECL(indent,(int));
551
552static void
553indent(d)
554int 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 */
567STATIC_OVL boolean
568place_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
608struct 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
641void
642init_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 NETHACK_DEBUG
898	dumpit();
899#endif
900}
901
902xchar
903dunlev(lev)	/* return the level number for lev in *this* dungeon */
904d_level	*lev;
905{
906	return(lev->dlevel);
907}
908
909xchar
910dunlevs_in_dungeon(lev)	/* return the lowest level number for *this* dungeon*/
911d_level	*lev;
912{
913	return(dungeons[lev->dnum].num_dunlevs);
914}
915
916xchar
917deepest_lev_reached(noquest) /* return the lowest level explored in the game*/
918boolean 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 */
951xchar
952ledger_no(lev)
953d_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 */
968xchar
969maxledgerno()
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 */
976xchar
977ledger_to_dnum(ledgerno)
978xchar	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 */
994xchar
995ledger_to_dlev(ledgerno)
996xchar	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).	*/
1006schar
1007depth(lev)
1008d_level	*lev;
1009{
1010	return((schar)( dungeons[lev->dnum].depth_start + lev->dlevel - 1));
1011}
1012
1013boolean
1014on_level(lev1, lev2)	/* are "lev1" and "lev2" actually the same? */
1015d_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? */
1024s_level *
1025Is_special(lev)
1026d_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 */
1040branch *
1041Is_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) */
1054void
1055next_level(at_stairs)
1056boolean	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) */
1072void
1073prev_level(at_stairs)
1074boolean	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
1091void
1092u_on_newpos(x, y)
1093int 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
1106void
1107u_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 NETHACK_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
1132void
1133u_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
1141void
1142u_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
1150boolean
1151On_stairs(x, y)
1152xchar 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
1161boolean
1162Is_botlevel(lev)
1163d_level *lev;
1164{
1165	return((boolean)(lev->dlevel == dungeons[lev->dnum].num_dunlevs));
1166}
1167
1168boolean
1169Can_dig_down(lev)
1170d_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 */
1181boolean
1182Can_fall_thru(lev)
1183d_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 */
1194boolean
1195Can_rise_up(x, y, lev)
1196int	x, y;
1197d_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 */
1220void
1221get_level(newlevel, levnum)
1222d_level *newlevel;
1223int 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
1271boolean
1272In_quest(lev)	/* are you in the quest dungeon? */
1273d_level *lev;
1274{
1275	return((boolean)(lev->dnum == quest_dnum));
1276}
1277
1278#endif /* OVL0 */
1279#ifdef OVL1
1280
1281boolean
1282In_mines(lev)	/* are you in the mines dungeon? */
1283d_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 */
1296branch *
1297dungeon_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 */
1322boolean
1323at_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
1332boolean
1333In_V_tower(lev)	/* is `lev' part of Vlad's tower? */
1334d_level	*lev;
1335{
1336	return((boolean)(lev->dnum == tower_dnum));
1337}
1338
1339boolean
1340On_W_tower_level(lev)	/* is `lev' a level containing the Wizard's tower? */
1341d_level	*lev;
1342{
1343	return (boolean)(Is_wiz1_level(lev) ||
1344			 Is_wiz2_level(lev) ||
1345			 Is_wiz3_level(lev));
1346}
1347
1348boolean
1349In_W_tower(x, y, lev)	/* is <x,y> of `lev' inside the Wizard's tower? */
1350int	x, y;
1351d_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
1370boolean
1371In_hell(lev)	/* are you in one of the Hell levels? */
1372d_level	*lev;
1373{
1374	return((boolean)(dungeons[lev->dnum].flags.hellish));
1375}
1376
1377#endif /* OVL0 */
1378#ifdef OVL1
1379
1380void
1381find_hell(lev)	/* sets *lev to be the gateway to Gehennom... */
1382d_level *lev;
1383{
1384	lev->dnum = valley_level.dnum;
1385	lev->dlevel = 1;
1386}
1387
1388void
1389goto_hell(at_stairs, falling)	/* go directly to hell... */
1390boolean	at_stairs, falling;
1391{
1392	d_level lev;
1393
1394	find_hell(&lev);
1395	goto_level(&lev, at_stairs, falling, FALSE);
1396}
1397
1398void
1399assign_level(dest, src)		/* equivalent to dest = source */
1400d_level	*dest, *src;
1401{
1402	dest->dnum = src->dnum;
1403	dest->dlevel = src->dlevel;
1404}
1405
1406void
1407assign_rnd_level(dest, src, range)	/* dest = src + rn1(range) */
1408d_level	*dest, *src;
1409int 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
1423int
1424induced_align(pct)
1425int	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
1443boolean
1444Invocation_lev(lev)
1445d_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 */
1454xchar
1455level_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 */
1469schar
1470lev_by_name(nam)
1471const 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(). */
1537STATIC_OVL const char *
1538br_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. */
1551STATIC_OVL void
1552print_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. */
1590schar
1591print_dungeon(bymenu, rlev, rdgn)
1592boolean bymenu;
1593schar *rlev;
1594xchar *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*/
1745