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