1 /* NetHack 3.6 dungeon.c $NHDT-Date: 1470275509 2016/08/04 01:51:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.76 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
10 #define DUNGEON_FILE "dungeon"
12 #define X_START "x-strt"
13 #define X_LOCATE "x-loca"
14 #define X_GOAL "x-goal"
16 struct proto_dungeon
{
17 struct tmpdungeon tmpdungeon
[MAXDUNGEON
];
18 struct tmplevel tmplevel
[LEV_LIMIT
];
19 s_level
*final_lev
[LEV_LIMIT
]; /* corresponding level pointers */
20 struct tmpbranch tmpbranch
[BRANCH_LIMIT
];
22 int start
; /* starting index of current dungeon sp levels */
23 int n_levs
; /* number of tmplevel entries */
24 int n_brs
; /* number of tmpbranch entries */
27 int n_dgns
; /* number of dungeons (also used in mklev.c and do.c) */
28 static branch
*branches
= (branch
*) 0; /* dungeon branch list */
30 mapseen
*mapseenchn
= (struct mapseen
*) 0; /*DUNGEON_OVERVIEW*/
35 schar playerlev
[MAXLINFO
];
40 static void FDECL(Fread
, (genericptr_t
, int, int, dlb
*));
41 STATIC_DCL xchar
FDECL(dname_to_dnum
, (const char *));
42 STATIC_DCL
int FDECL(find_branch
, (const char *, struct proto_dungeon
*));
43 STATIC_DCL xchar
FDECL(parent_dnum
, (const char *, struct proto_dungeon
*));
44 STATIC_DCL
int FDECL(level_range
, (XCHAR_P
, int, int, int,
45 struct proto_dungeon
*, int *));
46 STATIC_DCL xchar
FDECL(parent_dlevel
, (const char *, struct proto_dungeon
*));
47 STATIC_DCL
int FDECL(correct_branch_type
, (struct tmpbranch
*));
48 STATIC_DCL branch
*FDECL(add_branch
, (int, int, struct proto_dungeon
*));
49 STATIC_DCL
void FDECL(add_level
, (s_level
*));
50 STATIC_DCL
void FDECL(init_level
, (int, int, struct proto_dungeon
*));
51 STATIC_DCL
int FDECL(possible_places
, (int, boolean
*,
52 struct proto_dungeon
*));
53 STATIC_DCL xchar
FDECL(pick_level
, (boolean
*, int));
54 STATIC_DCL boolean
FDECL(place_level
, (int, struct proto_dungeon
*));
55 STATIC_DCL boolean
FDECL(unplaced_floater
, (struct dungeon
*));
56 STATIC_DCL boolean
FDECL(unreachable_level
, (d_level
*, BOOLEAN_P
));
57 STATIC_DCL
void FDECL(tport_menu
, (winid
, char *, struct lchoice
*, d_level
*,
59 STATIC_DCL
const char *FDECL(br_string
, (int));
60 STATIC_DCL
void FDECL(print_branch
, (winid
, int, int, int, BOOLEAN_P
,
62 STATIC_DCL mapseen
*FDECL(load_mapseen
, (int));
63 STATIC_DCL
void FDECL(save_mapseen
, (int, mapseen
*));
64 STATIC_DCL mapseen
*FDECL(find_mapseen
, (d_level
*));
65 STATIC_DCL mapseen
*FDECL(find_mapseen_by_str
, (const char *));
66 STATIC_DCL
void FDECL(print_mapseen
, (winid
, mapseen
*, int, int, BOOLEAN_P
));
67 STATIC_DCL boolean
FDECL(interest_mapseen
, (mapseen
*));
68 STATIC_DCL
void FDECL(traverse_mapseenchn
, (BOOLEAN_P
, winid
,
70 STATIC_DCL
const char *FDECL(seen_string
, (XCHAR_P
, const char *));
71 STATIC_DCL
const char *FDECL(br_string2
, (branch
*));
72 STATIC_DCL
const char *FDECL(endgamelevelname
, (char *, int));
73 STATIC_DCL
const char *FDECL(shop_string
, (int));
74 STATIC_DCL
char *FDECL(tunesuffix
, (mapseen
*, char *));
77 #define DD dungeons[i]
78 STATIC_DCL
void NDECL(dumpit
);
87 if (!explicitdebug(__FILE__
))
90 for (i
= 0; i
< n_dgns
; i
++) {
91 fprintf(stderr
, "\n#%d \"%s\" (%s):\n", i
, DD
.dname
, DD
.proto
);
92 fprintf(stderr
, " num_dunlevs %d, dunlev_ureached %d\n",
93 DD
.num_dunlevs
, DD
.dunlev_ureached
);
94 fprintf(stderr
, " depth_start %d, ledger_start %d\n",
95 DD
.depth_start
, DD
.ledger_start
);
96 fprintf(stderr
, " flags:%s%s%s\n",
97 DD
.flags
.rogue_like
? " rogue_like" : "",
98 DD
.flags
.maze_like
? " maze_like" : "",
99 DD
.flags
.hellish
? " hellish" : "");
102 fprintf(stderr
, "\nSpecial levels:\n");
103 for (x
= sp_levchn
; x
; x
= x
->next
) {
104 fprintf(stderr
, "%s (%d): ", x
->proto
, x
->rndlevs
);
105 fprintf(stderr
, "on %d, %d; ", x
->dlevel
.dnum
, x
->dlevel
.dlevel
);
106 fprintf(stderr
, "flags:%s%s%s%s\n",
107 x
->flags
.rogue_like
? " rogue_like" : "",
108 x
->flags
.maze_like
? " maze_like" : "",
109 x
->flags
.hellish
? " hellish" : "",
110 x
->flags
.town
? " town" : "");
113 fprintf(stderr
, "\nBranches:\n");
114 for (br
= branches
; br
; br
= br
->next
) {
115 fprintf(stderr
, "%d: %s, end1 %d %d, end2 %d %d, %s\n", br
->id
,
118 : br
->type
== BR_NO_END1
120 : br
->type
== BR_NO_END2
122 : br
->type
== BR_PORTAL
125 br
->end1
.dnum
, br
->end1
.dlevel
, br
->end2
.dnum
,
126 br
->end2
.dlevel
, br
->end1_up
? "end1 up" : "end1 down");
129 fprintf(stderr
, "\nDone\n");
134 /* Save the dungeon structures. */
136 save_dungeon(fd
, perform_write
, free_data
)
138 boolean perform_write
, free_data
;
141 mapseen
*curr_ms
, *next_ms
;
145 bwrite(fd
, (genericptr_t
) &n_dgns
, sizeof n_dgns
);
146 bwrite(fd
, (genericptr_t
) dungeons
,
147 sizeof(dungeon
) * (unsigned) n_dgns
);
148 bwrite(fd
, (genericptr_t
) &dungeon_topology
, sizeof dungeon_topology
);
149 bwrite(fd
, (genericptr_t
) tune
, sizeof tune
);
151 for (count
= 0, curr
= branches
; curr
; curr
= curr
->next
)
153 bwrite(fd
, (genericptr_t
) &count
, sizeof(count
));
155 for (curr
= branches
; curr
; curr
= curr
->next
)
156 bwrite(fd
, (genericptr_t
) curr
, sizeof(branch
));
158 count
= maxledgerno();
159 bwrite(fd
, (genericptr_t
) &count
, sizeof count
);
160 bwrite(fd
, (genericptr_t
) level_info
,
161 (unsigned) count
* sizeof(struct linfo
));
162 bwrite(fd
, (genericptr_t
) &inv_pos
, sizeof inv_pos
);
164 for (count
= 0, curr_ms
= mapseenchn
; curr_ms
;
165 curr_ms
= curr_ms
->next
)
167 bwrite(fd
, (genericptr_t
) &count
, sizeof(count
));
169 for (curr_ms
= mapseenchn
; curr_ms
; curr_ms
= curr_ms
->next
)
170 save_mapseen(fd
, curr_ms
);
174 for (curr
= branches
; curr
; curr
= next
) {
176 free((genericptr_t
) curr
);
179 for (curr_ms
= mapseenchn
; curr_ms
; curr_ms
= next_ms
) {
180 next_ms
= curr_ms
->next
;
182 free((genericptr_t
) curr_ms
->custom
);
183 free((genericptr_t
) curr_ms
);
189 /* Restore the dungeon structures. */
196 mapseen
*curr_ms
, *last_ms
;
198 mread(fd
, (genericptr_t
) &n_dgns
, sizeof(n_dgns
));
199 mread(fd
, (genericptr_t
) dungeons
, sizeof(dungeon
) * (unsigned) n_dgns
);
200 mread(fd
, (genericptr_t
) &dungeon_topology
, sizeof dungeon_topology
);
201 mread(fd
, (genericptr_t
) tune
, sizeof tune
);
203 last
= branches
= (branch
*) 0;
205 mread(fd
, (genericptr_t
) &count
, sizeof(count
));
206 for (i
= 0; i
< count
; i
++) {
207 curr
= (branch
*) alloc(sizeof(branch
));
208 mread(fd
, (genericptr_t
) curr
, sizeof(branch
));
209 curr
->next
= (branch
*) 0;
217 mread(fd
, (genericptr_t
) &count
, sizeof(count
));
218 if (count
>= MAXLINFO
)
219 panic("level information count larger (%d) than allocated size",
221 mread(fd
, (genericptr_t
) level_info
,
222 (unsigned) count
* sizeof(struct linfo
));
223 mread(fd
, (genericptr_t
) &inv_pos
, sizeof inv_pos
);
225 mread(fd
, (genericptr_t
) &count
, sizeof(count
));
226 last_ms
= (mapseen
*) 0;
227 for (i
= 0; i
< count
; i
++) {
228 curr_ms
= load_mapseen(fd
);
229 curr_ms
->next
= (mapseen
*) 0;
231 last_ms
->next
= curr_ms
;
233 mapseenchn
= curr_ms
;
239 Fread(ptr
, size
, nitems
, stream
)
246 if ((cnt
= dlb_fread(ptr
, size
, nitems
, stream
)) != nitems
) {
248 "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
249 (size
* nitems
), (size
* cnt
));
250 terminate(EXIT_FAILURE
);
260 for (i
= 0; i
< n_dgns
; i
++)
261 if (!strcmp(dungeons
[i
].dname
, s
))
264 panic("Couldn't resolve dungeon number for name \"%s\".", s
);
274 for (curr
= sp_levchn
; curr
; curr
= curr
->next
)
275 if (!strcmpi(s
, curr
->proto
))
280 /* Find the branch that links the named dungeon. */
283 const char *s
; /* dungeon name */
284 struct proto_dungeon
*pd
;
289 for (i
= 0; i
< pd
->n_brs
; i
++)
290 if (!strcmp(pd
->tmpbranch
[i
].name
, s
))
293 panic("find_branch: can't find %s", s
);
295 /* support for level tport by name */
299 for (br
= branches
; br
; br
= br
->next
) {
300 dnam
= dungeons
[br
->end2
.dnum
].dname
;
301 if (!strcmpi(dnam
, s
)
302 || (!strncmpi(dnam
, "The ", 4) && !strcmpi(dnam
+ 4, s
)))
305 i
= br
? ((ledger_no(&br
->end1
) << 8) | ledger_no(&br
->end2
)) : -1;
311 * Find the "parent" by searching the prototype branch list for the branch
312 * listing, then figuring out to which dungeon it belongs.
316 const char *s
; /* dungeon name */
317 struct proto_dungeon
*pd
;
322 i
= find_branch(s
, pd
);
324 * Got branch, now find parent dungeon. Stop if we have reached
325 * "this" dungeon (if we haven't found it by now it is an error).
327 for (pdnum
= 0; strcmp(pd
->tmpdungeon
[pdnum
].name
, s
); pdnum
++)
328 if ((i
-= pd
->tmpdungeon
[pdnum
].branches
) < 0)
331 panic("parent_dnum: couldn't resolve branch.");
337 * Return a starting point and number of successive positions a level
338 * or dungeon entrance can occupy.
340 * Note: This follows the acouple (instead of the rcouple) rules for a
341 * negative random component (randc < 0). These rules are found
342 * in dgn_comp.y. The acouple [absolute couple] section says that
343 * a negative random component means from the (adjusted) base to the
344 * end of the dungeon.
347 level_range(dgn
, base
, randc
, chain
, pd
, adjusted_base
)
349 int base
, randc
, chain
;
350 struct proto_dungeon
*pd
;
353 int lmax
= dungeons
[dgn
].num_dunlevs
;
355 if (chain
>= 0) { /* relative to a special level */
356 s_level
*levtmp
= pd
->final_lev
[chain
];
358 panic("level_range: empty chain level!");
360 base
+= levtmp
->dlevel
.dlevel
;
361 } else { /* absolute in the dungeon */
362 /* from end of dungeon */
364 base
= (lmax
+ base
+ 1);
367 if (base
< 1 || base
> lmax
)
368 panic("level_range: base value out of range");
370 *adjusted_base
= base
;
372 if (randc
== -1) { /* from base to end of dungeon */
373 return (lmax
- base
+ 1);
375 /* make sure we don't run off the end of the dungeon */
376 return (((base
+ randc
- 1) > lmax
) ? lmax
- base
+ 1 : randc
);
377 } /* else only one choice */
384 struct proto_dungeon
*pd
;
386 int i
, j
, num
, base
, dnum
= parent_dnum(s
, pd
);
389 i
= find_branch(s
, pd
);
390 num
= level_range(dnum
, pd
->tmpbranch
[i
].lev
.base
,
391 pd
->tmpbranch
[i
].lev
.rand
, pd
->tmpbranch
[i
].chain
, pd
,
394 /* KMH -- Try our best to find a level without an existing branch */
399 for (curr
= branches
; curr
; curr
= curr
->next
)
400 if ((curr
->end1
.dnum
== dnum
&& curr
->end1
.dlevel
== base
+ i
)
401 || (curr
->end2
.dnum
== dnum
&& curr
->end2
.dlevel
== base
+ i
))
403 } while (curr
&& i
!= j
);
407 /* Convert from the temporary branch type to the dungeon branch type. */
409 correct_branch_type(tbr
)
410 struct tmpbranch
*tbr
;
416 return tbr
->up
? BR_NO_END1
: BR_NO_END2
;
418 return tbr
->up
? BR_NO_END2
: BR_NO_END1
;
422 impossible("correct_branch_type: unknown branch type");
427 * Add the given branch to the branch list. The branch list is ordered
428 * by end1 dungeon and level followed by end2 dungeon and level. If
429 * extract_first is true, then the branch is already part of the list
430 * but needs to be repositioned.
433 insert_branch(new_branch
, extract_first
)
435 boolean extract_first
;
438 long new_val
, curr_val
, prev_val
;
441 for (prev
= 0, curr
= branches
; curr
; prev
= curr
, curr
= curr
->next
)
442 if (curr
== new_branch
)
446 panic("insert_branch: not found");
448 prev
->next
= curr
->next
;
450 branches
= curr
->next
;
452 new_branch
->next
= (branch
*) 0;
454 /* Convert the branch into a unique number so we can sort them. */
455 #define branch_val(bp) \
456 ((((long) (bp)->end1.dnum * (MAXLEVEL + 1) + (long) (bp)->end1.dlevel) \
457 * (MAXDUNGEON + 1) * (MAXLEVEL + 1)) \
458 + ((long) (bp)->end2.dnum * (MAXLEVEL + 1) + (long) (bp)->end2.dlevel))
461 * Insert the new branch into the correct place in the branch list.
465 new_val
= branch_val(new_branch
);
466 for (curr
= branches
; curr
;
467 prev_val
= curr_val
, prev
= curr
, curr
= curr
->next
) {
468 curr_val
= branch_val(curr
);
469 if (prev_val
< new_val
&& new_val
<= curr_val
)
473 new_branch
->next
= curr
;
474 prev
->next
= new_branch
;
476 new_branch
->next
= branches
;
477 branches
= new_branch
;
481 /* Add a dungeon branch to the branch list. */
483 add_branch(dgn
, child_entry_level
, pd
)
485 int child_entry_level
;
486 struct proto_dungeon
*pd
;
488 static int branch_id
= 0;
492 branch_num
= find_branch(dungeons
[dgn
].dname
, pd
);
493 new_branch
= (branch
*) alloc(sizeof(branch
));
494 (void) memset((genericptr_t
)new_branch
, 0, sizeof(branch
));
495 new_branch
->next
= (branch
*) 0;
496 new_branch
->id
= branch_id
++;
497 new_branch
->type
= correct_branch_type(&pd
->tmpbranch
[branch_num
]);
498 new_branch
->end1
.dnum
= parent_dnum(dungeons
[dgn
].dname
, pd
);
499 new_branch
->end1
.dlevel
= parent_dlevel(dungeons
[dgn
].dname
, pd
);
500 new_branch
->end2
.dnum
= dgn
;
501 new_branch
->end2
.dlevel
= child_entry_level
;
502 new_branch
->end1_up
= pd
->tmpbranch
[branch_num
].up
? TRUE
: FALSE
;
504 insert_branch(new_branch
, FALSE
);
509 * Add new level to special level chain. Insert it in level order with the
510 * other levels in this dungeon. This assumes that we are never given a
511 * level that has a dungeon number less than the dungeon number of the
518 s_level
*prev
, *curr
;
520 prev
= (s_level
*) 0;
521 for (curr
= sp_levchn
; curr
; curr
= curr
->next
) {
522 if (curr
->dlevel
.dnum
== new_lev
->dlevel
.dnum
523 && curr
->dlevel
.dlevel
> new_lev
->dlevel
.dlevel
)
528 new_lev
->next
= sp_levchn
;
531 new_lev
->next
= curr
;
532 prev
->next
= new_lev
;
537 init_level(dgn
, proto_index
, pd
)
538 int dgn
, proto_index
;
539 struct proto_dungeon
*pd
;
542 struct tmplevel
*tlevel
= &pd
->tmplevel
[proto_index
];
544 pd
->final_lev
[proto_index
] = (s_level
*) 0; /* no "real" level */
545 if (!wizard
&& tlevel
->chance
<= rn2(100))
548 pd
->final_lev
[proto_index
] = new_level
=
549 (s_level
*) alloc(sizeof(s_level
));
550 (void) memset((genericptr_t
)new_level
, 0, sizeof(s_level
));
551 /* load new level with data */
552 Strcpy(new_level
->proto
, tlevel
->name
);
553 new_level
->boneid
= tlevel
->boneschar
;
554 new_level
->dlevel
.dnum
= dgn
;
555 new_level
->dlevel
.dlevel
= 0; /* for now */
557 new_level
->flags
.town
= !!(tlevel
->flags
& TOWN
);
558 new_level
->flags
.hellish
= !!(tlevel
->flags
& HELLISH
);
559 new_level
->flags
.maze_like
= !!(tlevel
->flags
& MAZELIKE
);
560 new_level
->flags
.rogue_like
= !!(tlevel
->flags
& ROGUELIKE
);
561 new_level
->flags
.align
= ((tlevel
->flags
& D_ALIGN_MASK
) >> 4);
562 if (!new_level
->flags
.align
)
563 new_level
->flags
.align
=
564 ((pd
->tmpdungeon
[dgn
].flags
& D_ALIGN_MASK
) >> 4);
566 new_level
->rndlevs
= tlevel
->rndlevs
;
567 new_level
->next
= (s_level
*) 0;
571 possible_places(idx
, map
, pd
)
572 int idx
; /* prototype index */
573 boolean
*map
; /* array MAXLEVEL+1 in length */
574 struct proto_dungeon
*pd
;
577 s_level
*lev
= pd
->final_lev
[idx
];
579 /* init level possibilities */
580 for (i
= 0; i
<= MAXLEVEL
; i
++)
583 /* get base and range and set those entries to true */
584 count
= level_range(lev
->dlevel
.dnum
, pd
->tmplevel
[idx
].lev
.base
,
585 pd
->tmplevel
[idx
].lev
.rand
, pd
->tmplevel
[idx
].chain
,
587 for (i
= start
; i
< start
+ count
; i
++)
590 /* mark off already placed levels */
591 for (i
= pd
->start
; i
< idx
; i
++) {
592 if (pd
->final_lev
[i
] && map
[pd
->final_lev
[i
]->dlevel
.dlevel
]) {
593 map
[pd
->final_lev
[i
]->dlevel
.dlevel
] = FALSE
;
601 /* Pick the nth TRUE entry in the given boolean array. */
604 boolean
*map
; /* an array MAXLEVEL+1 in size */
608 for (i
= 1; i
<= MAXLEVEL
; i
++)
609 if (map
[i
] && !nth
--)
611 panic("pick_level: ran out of valid levels");
616 static void FDECL(indent
, (int));
628 * Place a level. First, find the possible places on a dungeon map
629 * template. Next pick one. Then try to place the next level. If
630 * successful, we're done. Otherwise, try another (and another) until
631 * all possible places have been tried. If all possible places have
632 * been exhausted, return false.
635 place_level(proto_index
, pd
)
637 struct proto_dungeon
*pd
;
639 boolean map
[MAXLEVEL
+ 1]; /* valid levels are 1..MAXLEVEL inclusive */
646 if (proto_index
== pd
->n_levs
)
647 return TRUE
; /* at end of proto levels */
649 lev
= pd
->final_lev
[proto_index
];
651 /* No level created for this prototype, goto next. */
653 return place_level(proto_index
+ 1, pd
);
655 npossible
= possible_places(proto_index
, map
, pd
);
657 for (; npossible
; --npossible
) {
658 lev
->dlevel
.dlevel
= pick_level(map
, rn2(npossible
));
660 indent(proto_index
- pd
->start
);
661 fprintf(stderr
, "%s: trying %d [ ", lev
->proto
, lev
->dlevel
.dlevel
);
662 for (i
= 1; i
<= MAXLEVEL
; i
++)
664 fprintf(stderr
, "%d ", i
);
665 fprintf(stderr
, "]\n");
667 if (place_level(proto_index
+ 1, pd
))
669 map
[lev
->dlevel
.dlevel
] = FALSE
; /* this choice didn't work */
672 indent(proto_index
- pd
->start
);
673 fprintf(stderr
, "%s: failed\n", lev
->proto
);
679 const char *lev_name
;
681 } level_map
[] = { { "air", &air_level
},
682 { "asmodeus", &asmodeus_level
},
683 { "astral", &astral_level
},
684 { "baalz", &baalzebub_level
},
685 { "bigrm", &bigroom_level
},
686 { "castle", &stronghold_level
},
687 { "earth", &earth_level
},
688 { "fakewiz1", &portal_level
},
689 { "fire", &fire_level
},
690 { "juiblex", &juiblex_level
},
691 { "knox", &knox_level
},
692 { "medusa", &medusa_level
},
693 { "oracle", &oracle_level
},
694 { "orcus", &orcus_level
},
695 { "rogue", &rogue_level
},
696 { "sanctum", &sanctum_level
},
697 { "valley", &valley_level
},
698 { "water", &water_level
},
699 { "wizard1", &wiz1_level
},
700 { "wizard2", &wiz2_level
},
701 { "wizard3", &wiz3_level
},
702 { "minend", &mineend_level
},
703 { "soko1", &sokoend_level
},
704 { X_START
, &qstart_level
},
705 { X_LOCATE
, &qlocate_level
},
706 { X_GOAL
, &nemesis_level
},
707 { "", (d_level
*) 0 } };
709 /* initialize the "dungeon" structs */
714 register int i
, cl
= 0, cb
= 0;
716 struct proto_dungeon pd
;
717 struct level_map
*lev_map
;
718 struct version_info vers_info
;
720 pd
.n_levs
= pd
.n_brs
= 0;
722 dgn_file
= dlb_fopen(DUNGEON_FILE
, RDBMODE
);
725 Sprintf(tbuf
, "Cannot open dungeon description - \"%s", DUNGEON_FILE
);
726 #ifdef DLBRSRC /* using a resource from the executable */
727 Strcat(tbuf
, "\" resource!");
728 #else /* using a file or DLB file */
730 Strcat(tbuf
, "\" from ");
731 #ifdef PREFIXES_IN_USE
732 Strcat(tbuf
, "\n\"");
733 if (fqn_prefix
[DATAPREFIX
])
734 Strcat(tbuf
, fqn_prefix
[DATAPREFIX
]);
738 Strcat(tbuf
, DLBFILE
);
740 Strcat(tbuf
, "\" file!");
743 interject_assistance(1, INTERJECT_PANIC
, (genericptr_t
) tbuf
,
744 (genericptr_t
) fqn_prefix
[DATAPREFIX
]);
749 /* validate the data's version against the program's version */
750 Fread((genericptr_t
) &vers_info
, sizeof vers_info
, 1, dgn_file
);
751 /* we'd better clear the screen now, since when error messages come from
752 * check_version() they will be printed using pline(), which doesn't
753 * mix with the raw messages that might be already on the screen
755 if (iflags
.window_inited
)
756 clear_nhwindow(WIN_MAP
);
757 if (!check_version(&vers_info
, DUNGEON_FILE
, TRUE
))
758 panic("Dungeon description not valid.");
761 * Read in each dungeon and transfer the results to the internal
764 sp_levchn
= (s_level
*) 0;
765 Fread((genericptr_t
) &n_dgns
, sizeof(int), 1, dgn_file
);
766 if (n_dgns
>= MAXDUNGEON
)
767 panic("init_dungeons: too many dungeons");
769 for (i
= 0; i
< n_dgns
; i
++) {
770 Fread((genericptr_t
) &pd
.tmpdungeon
[i
], sizeof(struct tmpdungeon
), 1,
772 if (!wizard
&& pd
.tmpdungeon
[i
].chance
773 && (pd
.tmpdungeon
[i
].chance
<= rn2(100))) {
776 /* skip over any levels or branches */
777 for (j
= 0; j
< pd
.tmpdungeon
[i
].levels
; j
++)
778 Fread((genericptr_t
) &pd
.tmplevel
[cl
],
779 sizeof(struct tmplevel
), 1, dgn_file
);
781 for (j
= 0; j
< pd
.tmpdungeon
[i
].branches
; j
++)
782 Fread((genericptr_t
) &pd
.tmpbranch
[cb
],
783 sizeof(struct tmpbranch
), 1, dgn_file
);
789 Strcpy(dungeons
[i
].dname
, pd
.tmpdungeon
[i
].name
);
790 Strcpy(dungeons
[i
].proto
, pd
.tmpdungeon
[i
].protoname
);
791 dungeons
[i
].boneid
= pd
.tmpdungeon
[i
].boneschar
;
793 if (pd
.tmpdungeon
[i
].lev
.rand
)
794 dungeons
[i
].num_dunlevs
= (xchar
) rn1(pd
.tmpdungeon
[i
].lev
.rand
,
795 pd
.tmpdungeon
[i
].lev
.base
);
797 dungeons
[i
].num_dunlevs
= (xchar
) pd
.tmpdungeon
[i
].lev
.base
;
800 dungeons
[i
].ledger_start
= 0;
801 dungeons
[i
].depth_start
= 1;
802 dungeons
[i
].dunlev_ureached
= 1;
804 dungeons
[i
].ledger_start
=
805 dungeons
[i
- 1].ledger_start
+ dungeons
[i
- 1].num_dunlevs
;
806 dungeons
[i
].dunlev_ureached
= 0;
809 dungeons
[i
].flags
.hellish
= !!(pd
.tmpdungeon
[i
].flags
& HELLISH
);
810 dungeons
[i
].flags
.maze_like
= !!(pd
.tmpdungeon
[i
].flags
& MAZELIKE
);
811 dungeons
[i
].flags
.rogue_like
= !!(pd
.tmpdungeon
[i
].flags
& ROGUELIKE
);
812 dungeons
[i
].flags
.align
=
813 ((pd
.tmpdungeon
[i
].flags
& D_ALIGN_MASK
) >> 4);
815 * Set the entry level for this dungeon. The pd.tmpdungeon entry
817 * < 0 from bottom (-1 == bottom level)
819 * > 0 actual level (1 = top)
821 * Note that the entry_lev field in the dungeon structure is
822 * redundant. It is used only here and in print_dungeon().
824 if (pd
.tmpdungeon
[i
].entry_lev
< 0) {
825 dungeons
[i
].entry_lev
=
826 dungeons
[i
].num_dunlevs
+ pd
.tmpdungeon
[i
].entry_lev
+ 1;
827 if (dungeons
[i
].entry_lev
<= 0)
828 dungeons
[i
].entry_lev
= 1;
829 } else if (pd
.tmpdungeon
[i
].entry_lev
> 0) {
830 dungeons
[i
].entry_lev
= pd
.tmpdungeon
[i
].entry_lev
;
831 if (dungeons
[i
].entry_lev
> dungeons
[i
].num_dunlevs
)
832 dungeons
[i
].entry_lev
= dungeons
[i
].num_dunlevs
;
833 } else { /* default */
834 dungeons
[i
].entry_lev
= 1; /* defaults to top level */
837 if (i
) { /* set depth */
842 br
= add_branch(i
, dungeons
[i
].entry_lev
, &pd
);
844 /* Get the depth of the connecting end. */
845 if (br
->end1
.dnum
== i
) {
846 from_depth
= depth(&br
->end2
);
847 from_up
= !br
->end1_up
;
849 from_depth
= depth(&br
->end1
);
850 from_up
= br
->end1_up
;
854 * Calculate the depth of the top of the dungeon via
855 * its branch. First, the depth of the entry point:
857 * depth of branch from "parent" dungeon
858 * + -1 or 1 depending on an up or down stair or
861 * Followed by the depth of the top of the dungeon:
863 * - (entry depth - 1)
865 * We'll say that portals stay on the same depth.
867 dungeons
[i
].depth_start
=
868 from_depth
+ (br
->type
== BR_PORTAL
? 0 : (from_up
? -1 : 1))
869 - (dungeons
[i
].entry_lev
- 1);
872 /* this is redundant - it should have been flagged by dgn_comp */
873 if (dungeons
[i
].num_dunlevs
> MAXLEVEL
)
874 dungeons
[i
].num_dunlevs
= MAXLEVEL
;
876 pd
.start
= pd
.n_levs
; /* save starting point */
877 pd
.n_levs
+= pd
.tmpdungeon
[i
].levels
;
878 if (pd
.n_levs
> LEV_LIMIT
)
879 panic("init_dungeon: too many special levels");
881 * Read in the prototype special levels. Don't add generated
882 * special levels until they are all placed.
884 for (; cl
< pd
.n_levs
; cl
++) {
885 Fread((genericptr_t
) &pd
.tmplevel
[cl
], sizeof(struct tmplevel
), 1,
887 init_level(i
, cl
, &pd
);
890 * Recursively place the generated levels for this dungeon. This
891 * routine will attempt all possible combinations before giving
894 if (!place_level(pd
.start
, &pd
))
895 panic("init_dungeon: couldn't place levels");
897 fprintf(stderr
, "--- end of dungeon %d ---\n", i
);
901 for (; pd
.start
< pd
.n_levs
; pd
.start
++)
902 if (pd
.final_lev
[pd
.start
])
903 add_level(pd
.final_lev
[pd
.start
]);
905 pd
.n_brs
+= pd
.tmpdungeon
[i
].branches
;
906 if (pd
.n_brs
> BRANCH_LIMIT
)
907 panic("init_dungeon: too many branches");
908 for (; cb
< pd
.n_brs
; cb
++)
909 Fread((genericptr_t
) &pd
.tmpbranch
[cb
], sizeof(struct tmpbranch
),
912 (void) dlb_fclose(dgn_file
);
914 for (i
= 0; i
< 5; i
++)
915 tune
[i
] = 'A' + rn2(7);
919 * Find most of the special levels and dungeons so we can access their
922 for (lev_map
= level_map
; lev_map
->lev_name
[0]; lev_map
++) {
923 x
= find_level(lev_map
->lev_name
);
925 assign_level(lev_map
->lev_spec
, &x
->dlevel
);
926 if (!strncmp(lev_map
->lev_name
, "x-", 2)) {
927 /* This is where the name substitution on the
928 * levels of the quest dungeon occur.
930 Sprintf(x
->proto
, "%s%s", urole
.filecode
,
931 &lev_map
->lev_name
[1]);
932 } else if (lev_map
->lev_spec
== &knox_level
) {
935 * Kludge to allow floating Knox entrance. We
936 * specify a floating entrance by the fact that
937 * its entrance (end1) has a bogus dnum, namely
940 for (br
= branches
; br
; br
= br
->next
)
941 if (on_level(&br
->end2
, &knox_level
))
945 br
->end1
.dnum
= n_dgns
;
946 /* adjust the branch's position on the list */
947 insert_branch(br
, TRUE
);
952 * I hate hardwiring these names. :-(
954 quest_dnum
= dname_to_dnum("The Quest");
955 sokoban_dnum
= dname_to_dnum("Sokoban");
956 mines_dnum
= dname_to_dnum("The Gnomish Mines");
957 tower_dnum
= dname_to_dnum("Vlad's Tower");
959 /* one special fixup for dummy surface level */
960 if ((x
= find_level("dummy")) != 0) {
962 /* the code above puts earth one level above dungeon level #1,
963 making the dummy level overlay level 1; but the whole reason
964 for having the dummy level is to make earth have depth -1
965 instead of 0, so adjust the start point to shift endgame up */
966 if (dunlevs_in_dungeon(&x
->dlevel
) > 1 - dungeons
[i
].depth_start
)
967 dungeons
[i
].depth_start
-= 1;
968 /* TO DO: strip "dummy" out all the way here,
969 so that it's hidden from <ctrl/O> feedback. */
977 /* return the level number for lev in *this* dungeon */
985 /* return the lowest level number for *this* dungeon */
987 dunlevs_in_dungeon(lev
)
990 return dungeons
[lev
->dnum
].num_dunlevs
;
993 /* return the lowest level explored in the game*/
995 deepest_lev_reached(noquest
)
998 /* this function is used for three purposes: to provide a factor
999 * of difficulty in monster generation; to provide a factor of
1000 * difficulty in experience calculations (botl.c and end.c); and
1001 * to insert the deepest level reached in the game in the topten
1002 * display. the 'noquest' arg switch is required for the latter.
1004 * from the player's point of view, going into the Quest is _not_
1005 * going deeper into the dungeon -- it is going back "home", where
1006 * the dungeon starts at level 1. given the setup in dungeon.def,
1007 * the depth of the Quest (thought of as starting at level 1) is
1008 * never lower than the level of entry into the Quest, so we exclude
1009 * the Quest from the topten "deepest level reached" display
1010 * calculation. _However_ the Quest is a difficult dungeon, so we
1011 * include it in the factor of difficulty calculations.
1015 register schar ret
= 0;
1017 for (i
= 0; i
< n_dgns
; i
++) {
1018 if (noquest
&& i
== quest_dnum
)
1020 tmp
.dlevel
= dungeons
[i
].dunlev_ureached
;
1021 if (tmp
.dlevel
== 0)
1024 if (depth(&tmp
) > ret
)
1030 /* return a bookkeeping level number for purpose of comparisons and
1036 return (xchar
) (lev
->dlevel
+ dungeons
[lev
->dnum
].ledger_start
);
1040 * The last level in the bookkeeping list of level is the bottom of the last
1041 * dungeon in the dungeons[] array.
1043 * Maxledgerno() -- which is the max number of levels in the bookkeeping
1044 * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1045 * returns the max number of levels in lev's dungeon, and both should
1046 * not be confused with deepest_lev_reached() -- which returns the lowest
1047 * depth visited by the player.
1052 return (xchar
) (dungeons
[n_dgns
- 1].ledger_start
1053 + dungeons
[n_dgns
- 1].num_dunlevs
);
1056 /* return the dungeon that this ledgerno exists in */
1058 ledger_to_dnum(ledgerno
)
1063 /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1064 for (i
= 0; i
< n_dgns
; i
++)
1065 if (dungeons
[i
].ledger_start
< ledgerno
1066 && ledgerno
<= dungeons
[i
].ledger_start
+ dungeons
[i
].num_dunlevs
)
1069 panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno
);
1074 /* return the level of the dungeon this ledgerno exists in */
1076 ledger_to_dlev(ledgerno
)
1079 return (xchar
) (ledgerno
1080 - dungeons
[ledger_to_dnum(ledgerno
)].ledger_start
);
1083 /* returns the depth of a level, in floors below the surface
1084 (note levels in different dungeons can have the same depth) */
1089 return (schar
) (dungeons
[lev
->dnum
].depth_start
+ lev
->dlevel
- 1);
1092 /* are "lev1" and "lev2" actually the same? */
1094 on_level(lev1
, lev2
)
1095 d_level
*lev1
, *lev2
;
1097 return (boolean
) (lev1
->dnum
== lev2
->dnum
1098 && lev1
->dlevel
== lev2
->dlevel
);
1101 /* is this level referenced in the special level chain? */
1108 for (levtmp
= sp_levchn
; levtmp
; levtmp
= levtmp
->next
)
1109 if (on_level(lev
, &levtmp
->dlevel
))
1112 return (s_level
*) 0;
1116 * Is this a multi-dungeon branch level? If so, return a pointer to the
1117 * branch. Otherwise, return null.
1125 for (curr
= branches
; curr
; curr
= curr
->next
) {
1126 if (on_level(lev
, &curr
->end1
) || on_level(lev
, &curr
->end2
))
1129 return (branch
*) 0;
1132 /* returns True iff the branch 'lev' is in a branch which builds up */
1137 dungeon
*dptr
= &dungeons
[lev
->dnum
];
1139 * FIXME: this misclassifies a single level branch reached via stairs
1140 * from below. Saving grace is that no such branches currently exist.
1142 return (boolean
) (dptr
->num_dunlevs
> 1
1143 && dptr
->entry_lev
== dptr
->num_dunlevs
);
1146 /* goto the next level (or appropriate dungeon) */
1148 next_level(at_stairs
)
1151 if (at_stairs
&& u
.ux
== sstairs
.sx
&& u
.uy
== sstairs
.sy
) {
1152 /* Taking a down dungeon branch. */
1153 goto_level(&sstairs
.tolev
, at_stairs
, FALSE
, FALSE
);
1155 /* Going down a stairs or jump in a trap door. */
1158 newlevel
.dnum
= u
.uz
.dnum
;
1159 newlevel
.dlevel
= u
.uz
.dlevel
+ 1;
1160 goto_level(&newlevel
, at_stairs
, !at_stairs
, FALSE
);
1164 /* goto the previous level (or appropriate dungeon) */
1166 prev_level(at_stairs
)
1169 if (at_stairs
&& u
.ux
== sstairs
.sx
&& u
.uy
== sstairs
.sy
) {
1170 /* Taking an up dungeon branch. */
1171 /* KMH -- Upwards branches are okay if not level 1 */
1172 /* (Just make sure it doesn't go above depth 1) */
1173 if (!u
.uz
.dnum
&& u
.uz
.dlevel
== 1 && !u
.uhave
.amulet
)
1176 goto_level(&sstairs
.tolev
, at_stairs
, FALSE
, FALSE
);
1178 /* Going up a stairs or rising through the ceiling. */
1180 newlevel
.dnum
= u
.uz
.dnum
;
1181 newlevel
.dlevel
= u
.uz
.dlevel
- 1;
1182 goto_level(&newlevel
, at_stairs
, FALSE
, FALSE
);
1193 cliparound(u
.ux
, u
.uy
);
1195 /* ridden steed always shares hero's location */
1197 u
.usteed
->mx
= u
.ux
, u
.usteed
->my
= u
.uy
;
1198 /* when changing levels, don't leave old position set with
1199 stale values from previous level */
1200 if (!on_level(&u
.uz
, &u
.uz0
))
1201 u
.ux0
= u
.ux
, u
.uy0
= u
.uy
;
1204 /* place you on a random location */
1206 u_on_rndspot(upflag
)
1209 int up
= (upflag
& 1), was_in_W_tower
= (upflag
& 2);
1212 * Place the hero at a random location within the relevant region.
1213 * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1214 * Unspecified region (.lx == 0) defaults to entire level.
1216 if (was_in_W_tower
&& On_W_tower_level(&u
.uz
))
1217 /* Stay inside the Wizard's tower when feasible.
1218 We use the W Tower's exclusion region for the
1219 destination instead of its enclosing region.
1220 Note: up vs down doesn't matter in this case
1221 because both specify the same exclusion area. */
1222 place_lregion(dndest
.nlx
, dndest
.nly
, dndest
.nhx
, dndest
.nhy
, 0, 0, 0,
1223 0, LR_DOWNTELE
, (d_level
*) 0);
1225 place_lregion(updest
.lx
, updest
.ly
, updest
.hx
, updest
.hy
, updest
.nlx
,
1226 updest
.nly
, updest
.nhx
, updest
.nhy
, LR_UPTELE
,
1229 place_lregion(dndest
.lx
, dndest
.ly
, dndest
.hx
, dndest
.hy
, dndest
.nlx
,
1230 dndest
.nly
, dndest
.nhx
, dndest
.nhy
, LR_DOWNTELE
,
1234 /* place you on the special staircase */
1236 u_on_sstairs(upflag
)
1240 u_on_newpos(sstairs
.sx
, sstairs
.sy
);
1242 u_on_rndspot(upflag
);
1245 /* place you on upstairs (or special equivalent) */
1250 u_on_newpos(xupstair
, yupstair
);
1252 u_on_sstairs(0); /* destination upstairs implies moving down */
1255 /* place you on dnstairs (or special equivalent) */
1260 u_on_newpos(xdnstair
, ydnstair
);
1262 u_on_sstairs(1); /* destination dnstairs implies moving up */
1269 return (boolean
) ((x
== xupstair
&& y
== yupstair
)
1270 || (x
== xdnstair
&& y
== ydnstair
)
1271 || (x
== xdnladder
&& y
== ydnladder
)
1272 || (x
== xupladder
&& y
== yupladder
)
1273 || (x
== sstairs
.sx
&& y
== sstairs
.sy
));
1280 return (boolean
) (lev
->dlevel
== dungeons
[lev
->dnum
].num_dunlevs
);
1287 return (boolean
) (!level
.flags
.hardfloor
1288 && !Is_botlevel(lev
)
1289 && !Invocation_lev(lev
));
1293 * Like Can_dig_down (above), but also allows falling through on the
1294 * stronghold level. Normally, the bottom level of a dungeon resists
1295 * both digging and falling.
1301 return (boolean
) (Can_dig_down(lev
) || Is_stronghold(lev
));
1305 * True if one can rise up a level (e.g. cursed gain level).
1306 * This happens on intermediate dungeon levels or on any top dungeon
1307 * level that has a stairwell style branch to the next higher dungeon.
1308 * Checks for amulets and such must be done elsewhere.
1311 Can_rise_up(x
, y
, lev
)
1315 /* can't rise up from inside the top of the Wizard's tower */
1316 /* KMH -- or in sokoban */
1317 if (In_endgame(lev
) || In_sokoban(lev
)
1318 || (Is_wiz1_level(lev
) && In_W_tower(x
, y
, lev
)))
1320 return (boolean
) (lev
->dlevel
> 1
1321 || (dungeons
[lev
->dnum
].entry_lev
== 1
1322 && ledger_no(lev
) != 1
1323 && sstairs
.sx
&& sstairs
.up
));
1330 /* [what about level 1 of the quest?] */
1331 return (boolean
) (!Is_airlevel(lev
) && !Is_waterlevel(lev
));
1335 * It is expected that the second argument of get_level is a depth value,
1336 * either supplied by the user (teleport control) or randomly generated.
1337 * But more than one level can be at the same depth. If the target level
1338 * is "above" the present depth location, get_level must trace "up" from
1339 * the player's location (through the ancestors dungeons) the dungeon
1340 * within which the target level is located. With only one exception
1341 * which does not pass through this routine (see level_tele), teleporting
1342 * "down" is confined to the current dungeon. At present, level teleport
1343 * in dungeons that build up is confined within them.
1346 get_level(newlevel
, levnum
)
1351 xchar dgn
= u
.uz
.dnum
;
1354 /* can only currently happen in endgame */
1355 levnum
= u
.uz
.dlevel
;
1357 > dungeons
[dgn
].depth_start
+ dungeons
[dgn
].num_dunlevs
- 1) {
1358 /* beyond end of dungeon, jump to last level */
1359 levnum
= dungeons
[dgn
].num_dunlevs
;
1361 /* The desired level is in this dungeon or a "higher" one. */
1364 * Branch up the tree until we reach a dungeon that contains the
1367 if (levnum
< dungeons
[dgn
].depth_start
) {
1370 * Find the parent dungeon of this dungeon.
1372 * This assumes that end2 is always the "child" and it is
1375 for (br
= branches
; br
; br
= br
->next
)
1376 if (br
->end2
.dnum
== dgn
)
1379 panic("get_level: can't find parent dungeon");
1381 dgn
= br
->end1
.dnum
;
1382 } while (levnum
< dungeons
[dgn
].depth_start
);
1385 /* We're within the same dungeon; calculate the level. */
1386 levnum
= levnum
- dungeons
[dgn
].depth_start
+ 1;
1389 newlevel
->dnum
= dgn
;
1390 newlevel
->dlevel
= levnum
;
1393 /* are you in the quest dungeon? */
1398 return (boolean
) (lev
->dnum
== quest_dnum
);
1401 /* are you in the mines dungeon? */
1406 return (boolean
) (lev
->dnum
== mines_dnum
);
1410 * Return the branch for the given dungeon.
1412 * This function assumes:
1413 * + This is not called with "Dungeons of Doom".
1414 * + There is only _one_ branch to a given dungeon.
1415 * + Field end2 is the "child" dungeon.
1424 dnum
= dname_to_dnum(s
);
1426 /* Find the branch that connects to dungeon i's branch. */
1427 for (br
= branches
; br
; br
= br
->next
)
1428 if (br
->end2
.dnum
== dnum
)
1432 panic("dgn_entrance: can't find entrance to %s", s
);
1438 * This returns true if the hero is on the same level as the entrance to
1439 * the named dungeon.
1441 * Called from do.c and mklev.c.
1443 * Assumes that end1 is always the "parent".
1451 br
= dungeon_branch(s
);
1452 return on_level(&u
.uz
, &br
->end1
) ? TRUE
: FALSE
;
1455 /* is `lev' part of Vlad's tower? */
1460 return (boolean
) (lev
->dnum
== tower_dnum
);
1463 /* is `lev' a level containing the Wizard's tower? */
1465 On_W_tower_level(lev
)
1468 return (boolean
) (Is_wiz1_level(lev
)
1469 || Is_wiz2_level(lev
)
1470 || Is_wiz3_level(lev
));
1473 /* is <x,y> of `lev' inside the Wizard's tower? */
1475 In_W_tower(x
, y
, lev
)
1479 if (!On_W_tower_level(lev
))
1482 * Both of the exclusion regions for arriving via level teleport
1483 * (from above or below) define the tower's boundary.
1484 * assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1487 return (boolean
) within_bounded_area(x
, y
, dndest
.nlx
, dndest
.nly
,
1488 dndest
.nhx
, dndest
.nhy
);
1490 impossible("No boundary for Wizard's Tower?");
1494 /* are you in one of the Hell levels? */
1499 return (boolean
) (dungeons
[lev
->dnum
].flags
.hellish
);
1502 /* sets *lev to be the gateway to Gehennom... */
1507 lev
->dnum
= valley_level
.dnum
;
1511 /* go directly to hell... */
1513 goto_hell(at_stairs
, falling
)
1514 boolean at_stairs
, falling
;
1519 goto_level(&lev
, at_stairs
, falling
, FALSE
);
1522 /* equivalent to dest = source */
1524 assign_level(dest
, src
)
1525 d_level
*dest
, *src
;
1527 dest
->dnum
= src
->dnum
;
1528 dest
->dlevel
= src
->dlevel
;
1531 /* dest = src + rn1(range) */
1533 assign_rnd_level(dest
, src
, range
)
1534 d_level
*dest
, *src
;
1537 dest
->dnum
= src
->dnum
;
1538 dest
->dlevel
= src
->dlevel
+ ((range
> 0) ? rnd(range
) : -rnd(-range
));
1540 if (dest
->dlevel
> dunlevs_in_dungeon(dest
))
1541 dest
->dlevel
= dunlevs_in_dungeon(dest
);
1542 else if (dest
->dlevel
< 1)
1550 s_level
*lev
= Is_special(&u
.uz
);
1553 if (lev
&& lev
->flags
.align
)
1555 return lev
->flags
.align
;
1557 if (dungeons
[u
.uz
.dnum
].flags
.align
)
1559 return dungeons
[u
.uz
.dnum
].flags
.align
;
1562 return Align2amask(al
);
1569 return (boolean
) (In_hell(lev
)
1570 && lev
->dlevel
== dungeons
[lev
->dnum
].num_dunlevs
- 1);
1573 /* use instead of depth() wherever a degree of difficulty is made
1574 * dependent on the location in the dungeon (eg. monster creation).
1581 if (In_endgame(&u
.uz
)) {
1582 res
= depth(&sanctum_level
) + u
.ulevel
/ 2;
1583 } else if (u
.uhave
.amulet
) {
1584 res
= deepest_lev_reached(FALSE
);
1587 /* depth() is the number of elevation units (levels) below
1588 the theoretical surface; in a builds-up branch, that value
1589 ends up making the harder to reach levels be treated as if
1590 they were easier; adjust for the extra effort involved in
1591 going down to the entrance and then up to the location */
1592 if (builds_up(&u
.uz
))
1593 res
+= 2 * (dungeons
[u
.uz
.dnum
].entry_lev
- u
.uz
.dlevel
+ 1);
1595 * 'Proof' by example: suppose the entrance to sokoban is
1596 * on dungeon level 9, leading up to bottom sokoban level
1597 * of 8 [entry_lev]. When the hero is on sokoban level 8
1598 * [uz.dlevel], depth() yields eight but he has ventured
1599 * one level beyond 9, so difficulty depth should be 10:
1600 * 8 + 2 * (8 - 8 + 1) => 10.
1601 * Going up to 7, depth is 7 but hero will be two beyond 9:
1602 * 7 + 2 * (8 - 7 + 1) => 11.
1603 * When he goes up to level 6, three levels beyond 9:
1604 * 6 + 2 * (8 - 6 + 1) => 12.
1605 * And the top level of sokoban at 5, four levels beyond 9:
1606 * 5 + 2 * (8 - 5 + 1) => 13.
1607 * The same applies to Vlad's Tower, although the increment
1608 * there is inconsequential compared to overall depth.
1612 * The inside of the Wizard's Tower is also effectively a
1613 * builds-up area, reached from a portal an arbitrary distance
1614 * below rather than stairs 1 level beneath the entry level.
1616 else if (On_W_tower_level(&u
.uz
) && In_W_tower(some_X
, some_Y
, &u
.uz
))
1617 res
+= (fakewiz1
.dlev
- u
.uz
.dlev
);
1619 * Handling this properly would need more information here:
1620 * an inside/outside flag, or coordinates to calculate it.
1621 * Unfortunately level difficulty may be wanted before
1622 * coordinates have been chosen so simply extending this
1623 * routine to take extra arguments is not sufficient to cope.
1624 * The difference beyond naive depth-from-surface is small
1625 * relative to the overall depth, so just ignore complications
1633 /* Take one word and try to match it to a level.
1634 * Recognized levels are as shown by print_dungeon().
1641 s_level
*slev
= (s_level
*)0;
1648 /* look at the player's custom level annotations first */
1649 if ((mseen
= find_mapseen_by_str(nam
)) != 0) {
1652 /* no matching annotation, check whether they used a name we know */
1654 /* allow strings like "the oracle level" to find "oracle" */
1655 if (!strncmpi(nam
, "the ", 4))
1657 if ((p
= strstri(nam
, " level")) != 0 && p
== eos((char *) nam
) - 6) {
1658 nam
= strcpy(buf
, nam
);
1659 *(eos(buf
) - 6) = '\0';
1661 /* hell is the old name, and wouldn't match; gehennom would match its
1662 branch, yielding the castle level instead of the valley of the dead */
1663 if (!strcmpi(nam
, "gehennom") || !strcmpi(nam
, "hell")) {
1664 if (In_V_tower(&u
.uz
))
1665 nam
= " to Vlad's tower"; /* branch to... */
1670 if ((slev
= find_level(nam
)) != 0)
1671 dlev
= slev
->dlevel
;
1674 if (mseen
|| slev
) {
1675 idx
= ledger_no(&dlev
);
1676 if ((dlev
.dnum
== u
.uz
.dnum
1677 /* within same branch, or else main dungeon <-> gehennom */
1678 || (u
.uz
.dnum
== valley_level
.dnum
1679 && dlev
.dnum
== medusa_level
.dnum
)
1680 || (u
.uz
.dnum
== medusa_level
.dnum
1681 && dlev
.dnum
== valley_level
.dnum
))
1682 && (/* either wizard mode or else seen and not forgotten */
1684 || (level_info
[idx
].flags
& (FORGOTTEN
| VISITED
))
1688 } else { /* not a specific level; try branch names */
1689 idx
= find_branch(nam
, (struct proto_dungeon
*) 0);
1690 /* "<branch> to Xyzzy" */
1691 if (idx
< 0 && (p
= strstri(nam
, " to ")) != 0)
1692 idx
= find_branch(p
+ 4, (struct proto_dungeon
*) 0);
1695 idxtoo
= (idx
>> 8) & 0x00FF;
1697 if (/* either wizard mode, or else _both_ sides of branch seen */
1699 || ((level_info
[idx
].flags
& (FORGOTTEN
| VISITED
)) == VISITED
1700 && (level_info
[idxtoo
].flags
& (FORGOTTEN
| VISITED
))
1702 if (ledger_to_dnum(idxtoo
) == u
.uz
.dnum
)
1704 dlev
.dnum
= ledger_to_dnum(idx
);
1705 dlev
.dlevel
= ledger_to_dlev(idx
);
1714 unplaced_floater(dptr
)
1715 struct dungeon
*dptr
;
1718 int idx
= (int) (dptr
- dungeons
);
1720 /* if other floating branches are added, this will need to change */
1721 if (idx
!= knox_level
.dnum
)
1723 for (br
= branches
; br
; br
= br
->next
)
1724 if (br
->end1
.dnum
== n_dgns
&& br
->end2
.dnum
== idx
)
1730 unreachable_level(lvl_p
, unplaced
)
1738 if (In_endgame(&u
.uz
) && !In_endgame(lvl_p
))
1740 if ((dummy
= find_level("dummy")) != 0 && on_level(lvl_p
, &dummy
->dlevel
))
1746 tport_menu(win
, entry
, lchoices
, lvl_p
, unreachable
)
1749 struct lchoice
*lchoices
;
1751 boolean unreachable
;
1756 lchoices
->lev
[lchoices
->idx
] = lvl_p
->dlevel
;
1757 lchoices
->dgn
[lchoices
->idx
] = lvl_p
->dnum
;
1758 lchoices
->playerlev
[lchoices
->idx
] = depth(lvl_p
);
1761 /* not selectable, but still consumes next menuletter;
1762 prepend padding in place of missing menu selector */
1763 Sprintf(tmpbuf
, " %s", entry
);
1766 any
.a_int
= lchoices
->idx
+ 1;
1768 add_menu(win
, NO_GLYPH
, &any
, lchoices
->menuletter
, 0, ATR_NONE
, entry
,
1770 /* this assumes there are at most 52 interesting levels */
1771 if (lchoices
->menuletter
== 'z')
1772 lchoices
->menuletter
= 'A';
1774 lchoices
->menuletter
++;
1779 /* Convert a branch type to a string usable by print_dungeon(). */
1780 STATIC_OVL
const char *
1788 return "Connection";
1790 return "One way stair";
1794 return " (unknown)";
1797 /* Print all child branches between the lower and upper bounds. */
1799 print_branch(win
, dnum
, lower_bound
, upper_bound
, bymenu
, lchoices_p
)
1805 struct lchoice
*lchoices_p
;
1810 /* This assumes that end1 is the "parent". */
1811 for (br
= branches
; br
; br
= br
->next
) {
1812 if (br
->end1
.dnum
== dnum
&& lower_bound
< br
->end1
.dlevel
1813 && br
->end1
.dlevel
<= upper_bound
) {
1814 Sprintf(buf
, " %s to %s: %d", br_string(br
->type
),
1815 dungeons
[br
->end2
.dnum
].dname
, depth(&br
->end1
));
1817 tport_menu(win
, buf
, lchoices_p
, &br
->end1
,
1818 unreachable_level(&br
->end1
, FALSE
));
1820 putstr(win
, 0, buf
);
1825 /* Print available dungeon information. */
1827 print_dungeon(bymenu
, rlev
, rdgn
)
1832 int i
, last_level
, nlev
;
1835 boolean first
, unplaced
;
1840 struct lchoice lchoices
;
1842 winid win
= create_nhwindow(NHW_MENU
);
1846 lchoices
.menuletter
= 'a';
1849 for (i
= 0, dptr
= dungeons
; i
< n_dgns
; i
++, dptr
++) {
1850 if (bymenu
&& In_endgame(&u
.uz
) && i
!= astral_level
.dnum
)
1852 unplaced
= unplaced_floater(dptr
);
1853 descr
= unplaced
? "depth" : "level";
1854 nlev
= dptr
->num_dunlevs
;
1856 Sprintf(buf
, "%s: %s %d to %d", dptr
->dname
, makeplural(descr
),
1857 dptr
->depth_start
, dptr
->depth_start
+ nlev
- 1);
1859 Sprintf(buf
, "%s: %s %d", dptr
->dname
, descr
, dptr
->depth_start
);
1861 /* Most entrances are uninteresting. */
1862 if (dptr
->entry_lev
!= 1) {
1863 if (dptr
->entry_lev
== nlev
)
1864 Strcat(buf
, ", entrance from below");
1866 Sprintf(eos(buf
), ", entrance on %d",
1867 dptr
->depth_start
+ dptr
->entry_lev
- 1);
1871 add_menu(win
, NO_GLYPH
, &any
, 0, 0, iflags
.menu_headings
, buf
,
1874 putstr(win
, 0, buf
);
1877 * Circle through the special levels to find levels that are in
1880 for (slev
= sp_levchn
, last_level
= 0; slev
; slev
= slev
->next
) {
1881 if (slev
->dlevel
.dnum
!= i
)
1884 /* print any branches before this level */
1885 print_branch(win
, i
, last_level
, slev
->dlevel
.dlevel
, bymenu
,
1888 Sprintf(buf
, " %s: %d", slev
->proto
, depth(&slev
->dlevel
));
1889 if (Is_stronghold(&slev
->dlevel
))
1890 Sprintf(eos(buf
), " (tune %s)", tune
);
1892 tport_menu(win
, buf
, &lchoices
, &slev
->dlevel
,
1893 unreachable_level(&slev
->dlevel
, unplaced
));
1895 putstr(win
, 0, buf
);
1897 last_level
= slev
->dlevel
.dlevel
;
1899 /* print branches after the last special level */
1900 print_branch(win
, i
, last_level
, MAXLEVEL
, bymenu
, &lchoices
);
1905 menu_item
*selected
;
1908 end_menu(win
, "Level teleport to where:");
1909 n
= select_menu(win
, PICK_ONE
, &selected
);
1910 destroy_nhwindow(win
);
1912 idx
= selected
[0].item
.a_int
- 1;
1913 free((genericptr_t
) selected
);
1915 *rlev
= lchoices
.lev
[idx
];
1916 *rdgn
= lchoices
.dgn
[idx
];
1917 return lchoices
.playerlev
[idx
];
1923 /* Print out floating branches (if any). */
1924 for (first
= TRUE
, br
= branches
; br
; br
= br
->next
) {
1925 if (br
->end1
.dnum
== n_dgns
) {
1928 putstr(win
, 0, "Floating branches");
1931 Sprintf(buf
, " %s to %s", br_string(br
->type
),
1932 dungeons
[br
->end2
.dnum
].dname
);
1933 putstr(win
, 0, buf
);
1937 /* I hate searching for the invocation pos while debugging. -dean */
1938 if (Invocation_lev(&u
.uz
)) {
1940 Sprintf(buf
, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1941 inv_pos
.x
, inv_pos
.y
, u
.ux
, u
.uy
);
1942 putstr(win
, 0, buf
);
1945 * The following is based on the assumption that the inter-level portals
1946 * created by the level compiler (not the dungeon compiler) only exist
1947 * one per level (currently true, of course).
1949 else if (Is_earthlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)
1950 || Is_firelevel(&u
.uz
) || Is_airlevel(&u
.uz
)) {
1952 for (trap
= ftrap
; trap
; trap
= trap
->ntrap
)
1953 if (trap
->ttyp
== MAGIC_PORTAL
)
1958 Sprintf(buf
, "Portal @ (%d,%d), hero @ (%d,%d)", trap
->tx
,
1959 trap
->ty
, u
.ux
, u
.uy
);
1961 Sprintf(buf
, "No portal found.");
1962 putstr(win
, 0, buf
);
1965 display_nhwindow(win
, TRUE
);
1966 destroy_nhwindow(win
);
1970 /* Record that the player knows about a branch from a level. This function
1971 * will determine whether or not it was a "real" branch that was taken.
1972 * This function should not be called for a transition done via level
1973 * teleport or via the Eye.
1976 recbranch_mapseen(source
, dest
)
1984 if (source
->dnum
== dest
->dnum
)
1987 /* we only care about forward branches */
1988 for (br
= branches
; br
; br
= br
->next
) {
1989 if (on_level(source
, &br
->end1
) && on_level(dest
, &br
->end2
))
1991 if (on_level(source
, &br
->end2
) && on_level(dest
, &br
->end1
))
1995 /* branch not found, so not a real branch. */
1999 if ((mptr
= find_mapseen(source
)) != 0) {
2000 if (mptr
->br
&& br
!= mptr
->br
)
2001 impossible("Two branches on the same level?");
2004 impossible("Can't note branch for unseen level (%d, %d)",
2005 source
->dnum
, source
->dlevel
);
2015 if ((mptr
= find_mapseen(lev
)))
2016 return mptr
->custom
;
2020 /* #annotate command - add a custom name to the current level */
2025 char nbuf
[BUFSZ
]; /* Buffer for response */
2027 if (!(mptr
= find_mapseen(&u
.uz
)))
2032 Sprintf(tmpbuf
, "Replace annotation \"%.30s%s\" with?", mptr
->custom
,
2033 strlen(mptr
->custom
) > 30 ? "..." : "");
2034 getlin(tmpbuf
, nbuf
);
2036 getlin("What do you want to call this dungeon level?", nbuf
);
2037 if (index(nbuf
, '\033'))
2039 (void) mungspaces(nbuf
);
2041 /* discard old annotation, if any */
2043 free((genericptr_t
) mptr
->custom
);
2044 mptr
->custom
= (char *) 0;
2045 mptr
->custom_lth
= 0;
2047 /* add new annotation, unless it's empty or a single space */
2048 if (*nbuf
&& strcmp(nbuf
, " ")) {
2049 mptr
->custom
= dupstr(nbuf
);
2050 mptr
->custom_lth
= strlen(mptr
->custom
);
2055 /* find the particular mapseen object in the chain; may return null */
2056 STATIC_OVL mapseen
*
2062 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
)
2063 if (on_level(&(mptr
->lev
), lev
))
2069 STATIC_OVL mapseen
*
2070 find_mapseen_by_str(s
)
2075 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
)
2076 if (mptr
->custom
&& !strcmpi(s
, mptr
->custom
))
2084 forget_mapseen(ledger_num
)
2088 struct cemetery
*bp
;
2090 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
)
2091 if (dungeons
[mptr
->lev
.dnum
].ledger_start
+ mptr
->lev
.dlevel
2095 /* if not found, then nothing to forget */
2097 mptr
->flags
.forgot
= 1;
2098 mptr
->br
= (branch
*) 0;
2100 /* custom names are erased, not just forgotten until revisited */
2102 mptr
->custom_lth
= 0;
2103 free((genericptr_t
) mptr
->custom
);
2104 mptr
->custom
= (char *) 0;
2106 (void) memset((genericptr_t
) mptr
->msrooms
, 0, sizeof mptr
->msrooms
);
2107 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
)
2108 bp
->bonesknown
= FALSE
;
2113 save_mapseen(fd
, mptr
)
2120 for (brindx
= 0, curr
= branches
; curr
; curr
= curr
->next
, ++brindx
)
2121 if (curr
== mptr
->br
)
2123 bwrite(fd
, (genericptr_t
) &brindx
, sizeof brindx
);
2125 bwrite(fd
, (genericptr_t
) &mptr
->lev
, sizeof mptr
->lev
);
2126 bwrite(fd
, (genericptr_t
) &mptr
->feat
, sizeof mptr
->feat
);
2127 bwrite(fd
, (genericptr_t
) &mptr
->flags
, sizeof mptr
->flags
);
2128 bwrite(fd
, (genericptr_t
) &mptr
->custom_lth
, sizeof mptr
->custom_lth
);
2129 if (mptr
->custom_lth
)
2130 bwrite(fd
, (genericptr_t
) mptr
->custom
, mptr
->custom_lth
);
2131 bwrite(fd
, (genericptr_t
) &mptr
->msrooms
, sizeof mptr
->msrooms
);
2132 savecemetery(fd
, WRITE_SAVE
, &mptr
->final_resting_place
);
2135 STATIC_OVL mapseen
*
2139 int branchnum
, brindx
;
2143 load
= (mapseen
*) alloc(sizeof *load
);
2145 mread(fd
, (genericptr_t
) &branchnum
, sizeof branchnum
);
2146 for (brindx
= 0, curr
= branches
; curr
; curr
= curr
->next
, ++brindx
)
2147 if (brindx
== branchnum
)
2151 mread(fd
, (genericptr_t
) &load
->lev
, sizeof load
->lev
);
2152 mread(fd
, (genericptr_t
) &load
->feat
, sizeof load
->feat
);
2153 mread(fd
, (genericptr_t
) &load
->flags
, sizeof load
->flags
);
2154 mread(fd
, (genericptr_t
) &load
->custom_lth
, sizeof load
->custom_lth
);
2155 if (load
->custom_lth
) {
2156 /* length doesn't include terminator (which isn't saved & restored) */
2157 load
->custom
= (char *) alloc(load
->custom_lth
+ 1);
2158 mread(fd
, (genericptr_t
) load
->custom
, load
->custom_lth
);
2159 load
->custom
[load
->custom_lth
] = '\0';
2162 mread(fd
, (genericptr_t
) &load
->msrooms
, sizeof load
->msrooms
);
2163 restcemetery(fd
, &load
->final_resting_place
);
2168 /* to support '#stats' wizard-mode command */
2170 overview_stats(win
, statsfmt
, total_count
, total_size
)
2172 const char *statsfmt
;
2173 long *total_count
, *total_size
;
2175 char buf
[BUFSZ
], hdrbuf
[QBUFSZ
];
2176 long ocount
, osize
, bcount
, bsize
, acount
, asize
;
2177 struct cemetery
*ce
;
2178 mapseen
*mptr
= find_mapseen(&u
.uz
);
2180 ocount
= bcount
= acount
= osize
= bsize
= asize
= 0L;
2181 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
) {
2183 osize
+= (long) sizeof *mptr
;
2184 for (ce
= mptr
->final_resting_place
; ce
; ce
= ce
->next
) {
2186 bsize
+= (long) sizeof *ce
;
2188 if (mptr
->custom_lth
) {
2190 asize
+= (long) (mptr
->custom_lth
+ 1);
2194 Sprintf(hdrbuf
, "general, size %ld", (long) sizeof (mapseen
));
2195 Sprintf(buf
, statsfmt
, hdrbuf
, ocount
, osize
);
2196 putstr(win
, 0, buf
);
2198 Sprintf(hdrbuf
, "cemetery, size %ld",
2199 (long) sizeof (struct cemetery
));
2200 Sprintf(buf
, statsfmt
, hdrbuf
, bcount
, bsize
);
2201 putstr(win
, 0, buf
);
2204 Sprintf(hdrbuf
, "annotations, text");
2205 Sprintf(buf
, statsfmt
, hdrbuf
, acount
, asize
);
2206 putstr(win
, 0, buf
);
2208 *total_count
+= ocount
+ bcount
+ acount
;
2209 *total_size
+= osize
+ bsize
+ asize
;
2212 /* Remove all mapseen objects for a particular dnum.
2213 * Useful during quest expulsion to remove quest levels.
2214 * [No longer deleted, just marked as unreachable. #overview will
2215 * ignore such levels, end of game disclosure will include them.]
2218 remdun_mapseen(dnum
)
2221 mapseen
*mptr
, **mptraddr
;
2223 mptraddr
= &mapseenchn
;
2224 while ((mptr
= *mptraddr
) != 0) {
2225 if (mptr
->lev
.dnum
== dnum
) {
2226 #if 1 /* use this... */
2227 mptr
->flags
.unreachable
= 1;
2229 #else /* old deletion code */
2230 *mptraddr
= mptr
->next
;
2232 free((genericptr_t
) mptr
->custom
);
2233 if (mptr
->final_resting_place
)
2234 savecemetery(-1, FREE_SAVE
, &mptr
->final_resting_place
);
2235 free((genericptr_t
) mptr
);
2238 mptraddr
= &mptr
->next
;
2246 /* Create a level and insert in "sorted" order. This is an insertion
2247 * sort first by dungeon (in order of discovery) and then by level number.
2249 mapseen
*mptr
, *init
, *prev
;
2251 init
= (mapseen
*) alloc(sizeof *init
);
2252 (void) memset((genericptr_t
) init
, 0, sizeof *init
);
2253 /* memset is fine for feature bits, flags, and rooms array;
2254 explicitly initialize pointers to null */
2255 init
->next
= 0, init
->br
= 0, init
->custom
= 0;
2256 init
->final_resting_place
= 0;
2257 /* lastseentyp[][] is reused for each level, so get rid of
2258 previous level's data */
2259 (void) memset((genericptr_t
) lastseentyp
, 0, sizeof lastseentyp
);
2261 init
->lev
.dnum
= lev
->dnum
;
2262 init
->lev
.dlevel
= lev
->dlevel
;
2264 /* walk until we get to the place where we should insert init */
2265 for (mptr
= mapseenchn
, prev
= 0; mptr
; prev
= mptr
, mptr
= mptr
->next
)
2266 if (mptr
->lev
.dnum
> init
->lev
.dnum
2267 || (mptr
->lev
.dnum
== init
->lev
.dnum
2268 && mptr
->lev
.dlevel
> init
->lev
.dlevel
))
2271 init
->next
= mapseenchn
;
2280 #define INTEREST(feat) \
2281 ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2282 || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2283 /* || (feat).water || (feat).ice || (feat).lava */
2285 /* returns true if this level has something interesting to print out */
2287 interest_mapseen(mptr
)
2290 if (on_level(&u
.uz
, &mptr
->lev
))
2292 if (mptr
->flags
.unreachable
|| mptr
->flags
.forgot
)
2294 /* level is of interest if it has an auto-generated annotation */
2295 if (mptr
->flags
.oracle
|| mptr
->flags
.bigroom
|| mptr
->flags
.roguelevel
2296 || mptr
->flags
.castle
|| mptr
->flags
.valley
|| mptr
->flags
.msanctum
2297 || mptr
->flags
.quest_summons
|| mptr
->flags
.questing
)
2299 /* when in Sokoban, list all sokoban levels visited; when not in it,
2300 list any visited Sokoban level which remains unsolved (will usually
2301 only be furthest one reached, but it's possible to enter pits and
2302 climb out on the far side on the first Sokoban level; also, wizard
2303 mode overrides teleport restrictions) */
2304 if (In_sokoban(&mptr
->lev
)
2305 && (In_sokoban(&u
.uz
) || !mptr
->flags
.sokosolved
))
2307 /* when in the endgame, list all endgame levels visited, whether they
2308 have annotations or not, so that #overview doesn't become extremely
2309 sparse once the rest of the dungeon has been flagged as unreachable */
2310 if (In_endgame(&u
.uz
))
2311 return (boolean
) In_endgame(&mptr
->lev
);
2312 /* level is of interest if it has non-zero feature count or known bones
2313 or user annotation or known connection to another dungeon branch
2314 or is the furthest level reached in its branch */
2315 return (boolean
) (INTEREST(mptr
->feat
)
2316 || (mptr
->final_resting_place
2317 && (mptr
->flags
.knownbones
|| wizard
))
2318 || mptr
->custom
|| mptr
->br
2319 || (mptr
->lev
.dlevel
2320 == dungeons
[mptr
->lev
.dnum
].dunlev_ureached
));
2323 /* recalculate mapseen for the current level */
2329 struct cemetery
*bp
, **bonesaddr
;
2331 int x
, y
, ltyp
, count
, atmp
;
2333 /* Should not happen in general, but possible if in the process
2334 * of being booted from the quest. The mapseen object gets
2335 * removed during the expulsion but prior to leaving the level
2336 * [Since quest expulsion no longer deletes quest mapseen data,
2337 * null return from find_mapseen() should now be impossible.]
2339 if (!(mptr
= find_mapseen(&u
.uz
)))
2342 /* reset all features; mptr->feat.* = 0; */
2343 (void) memset((genericptr_t
) &mptr
->feat
, 0, sizeof mptr
->feat
);
2344 /* reset most flags; some level-specific ones are left as-is */
2345 if (mptr
->flags
.unreachable
) {
2346 mptr
->flags
.unreachable
= 0; /* reached it; Eye of the Aethiopica? */
2347 if (In_quest(&u
.uz
)) {
2348 mapseen
*mptrtmp
= mapseenchn
;
2350 /* when quest was unreachable due to ejection and portal removal,
2351 getting back to it via arti-invoke should revive annotation
2352 data for all quest levels, not just the one we're on now */
2354 if (mptrtmp
->lev
.dnum
== mptr
->lev
.dnum
)
2355 mptrtmp
->flags
.unreachable
= 0;
2356 mptrtmp
= mptrtmp
->next
;
2360 mptr
->flags
.knownbones
= 0;
2361 mptr
->flags
.sokosolved
= In_sokoban(&u
.uz
) && !Sokoban
;
2362 /* mptr->flags.bigroom retains previous value when hero can't see */
2364 mptr
->flags
.bigroom
= Is_bigroom(&u
.uz
);
2365 else if (mptr
->flags
.forgot
)
2366 mptr
->flags
.bigroom
= 0;
2367 mptr
->flags
.roguelevel
= Is_rogue_level(&u
.uz
);
2368 mptr
->flags
.oracle
= 0; /* recalculated during room traversal below */
2369 mptr
->flags
.castletune
= 0;
2370 /* flags.castle, flags.valley, flags.msanctum retain previous value */
2371 mptr
->flags
.forgot
= 0;
2372 /* flags.quest_summons disabled once quest finished */
2373 mptr
->flags
.quest_summons
= (at_dgn_entrance("The Quest")
2375 && !(u
.uevent
.qcompleted
2376 || u
.uevent
.qexpelled
2377 || quest_status
.leader_is_dead
));
2378 mptr
->flags
.questing
= (on_level(&u
.uz
, &qstart_level
)
2379 && quest_status
.got_quest
);
2381 /* track rooms the hero is in */
2382 for (i
= 0; i
< SIZE(u
.urooms
); ++i
) {
2386 ridx
= u
.urooms
[i
] - ROOMOFFSET
;
2387 mptr
->msrooms
[ridx
].seen
= 1;
2388 mptr
->msrooms
[ridx
].untended
=
2389 (rooms
[ridx
].rtype
>= SHOPBASE
)
2390 ? (!(mtmp
= shop_keeper(u
.urooms
[i
])) || !inhishop(mtmp
))
2391 : (rooms
[ridx
].rtype
== TEMPLE
)
2392 ? (!(mtmp
= findpriest(u
.urooms
[i
]))
2393 || !inhistemple(mtmp
))
2397 /* recalculate room knowledge: for now, just shops and temples
2398 * this could be extended to an array of 0..SHOPBASE
2400 for (i
= 0; i
< SIZE(mptr
->msrooms
); ++i
) {
2401 if (mptr
->msrooms
[i
].seen
) {
2402 if (rooms
[i
].rtype
>= SHOPBASE
) {
2403 if (mptr
->msrooms
[i
].untended
)
2404 mptr
->feat
.shoptype
= SHOPBASE
- 1;
2405 else if (!mptr
->feat
.nshop
)
2406 mptr
->feat
.shoptype
= rooms
[i
].rtype
;
2407 else if (mptr
->feat
.shoptype
!= (unsigned) rooms
[i
].rtype
)
2408 mptr
->feat
.shoptype
= 0;
2409 count
= mptr
->feat
.nshop
+ 1;
2411 mptr
->feat
.nshop
= count
;
2412 } else if (rooms
[i
].rtype
== TEMPLE
) {
2413 /* altar and temple alignment handled below */
2414 count
= mptr
->feat
.ntemple
+ 1;
2416 mptr
->feat
.ntemple
= count
;
2417 } else if (rooms
[i
].orig_rtype
== DELPHI
) {
2418 mptr
->flags
.oracle
= 1;
2423 /* Update lastseentyp with typ if and only if it is in sight or the
2424 * hero can feel it on their current location (i.e. not levitating).
2425 * This *should* give the "last known typ" for each dungeon location.
2426 * (At the very least, it's a better assumption than determining what
2427 * the player knows from the glyph and the typ (which is isn't quite
2428 * enough information in some cases)).
2430 * It was reluctantly added to struct rm to track. Alternatively
2431 * we could track "features" and then update them all here, and keep
2432 * track of when new features are created or destroyed, but this
2433 * seemed the most elegant, despite adding more data to struct rm.
2434 * [3.6.0: we're using lastseentyp[][] rather than level.locations
2435 * to track the features seen.]
2437 * Although no current windowing systems (can) do this, this would add
2438 * the ability to have non-dungeon glyphs float above the last known
2439 * dungeon glyph (i.e. items on fountains).
2441 for (x
= 1; x
< COLNO
; x
++) {
2442 for (y
= 0; y
< ROWNO
; y
++) {
2443 if (cansee(x
, y
) || (x
== u
.ux
&& y
== u
.uy
&& !Levitation
)) {
2444 ltyp
= levl
[x
][y
].typ
;
2445 if (ltyp
== DRAWBRIDGE_UP
)
2446 ltyp
= db_under_typ(levl
[x
][y
].drawbridgemask
);
2447 if ((mtmp
= m_at(x
, y
)) != 0
2448 && mtmp
->m_ap_type
== M_AP_FURNITURE
&& canseemon(mtmp
))
2449 ltyp
= cmap_to_type(mtmp
->mappearance
);
2450 lastseentyp
[x
][y
] = ltyp
;
2453 switch (lastseentyp
[x
][y
]) {
2456 count
= mptr
->feat
.ice
+ 1;
2458 mptr
->feat
.ice
= count
;
2463 count
= mptr
->feat
.water
+ 1;
2465 mptr
->feat
.water
= count
;
2468 count
= mptr
->feat
.lava
+ 1;
2470 mptr
->feat
.lava
= count
;
2474 count
= mptr
->feat
.ntree
+ 1;
2476 mptr
->feat
.ntree
= count
;
2479 count
= mptr
->feat
.nfount
+ 1;
2481 mptr
->feat
.nfount
= count
;
2484 count
= mptr
->feat
.nthrone
+ 1;
2486 mptr
->feat
.nthrone
= count
;
2489 count
= mptr
->feat
.nsink
+ 1;
2491 mptr
->feat
.nsink
= count
;
2494 count
= mptr
->feat
.ngrave
+ 1;
2496 mptr
->feat
.ngrave
= count
;
2499 atmp
= (Is_astralevel(&u
.uz
)
2500 && (levl
[x
][y
].seenv
& SVALL
) != SVALL
)
2502 : Amask2msa(levl
[x
][y
].altarmask
);
2503 if (!mptr
->feat
.naltar
)
2504 mptr
->feat
.msalign
= atmp
;
2505 else if (mptr
->feat
.msalign
!= atmp
)
2506 mptr
->feat
.msalign
= MSA_NONE
;
2507 count
= mptr
->feat
.naltar
+ 1;
2509 mptr
->feat
.naltar
= count
;
2511 /* An automatic annotation is added to the Castle and
2512 * to Fort Ludios once their structure's main entrance
2513 * has been seen (in person or via magic mapping).
2514 * For the Fort, that entrance is just a secret door
2515 * which will be converted into a regular one when
2516 * located (or destroyed).
2517 * DOOR: possibly a lowered drawbridge's open portcullis;
2518 * DBWALL: a raised drawbridge's "closed door";
2519 * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2520 * with moat or other terrain hidden underneath;
2521 * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2522 * not recognizable as a bridge location unless/until
2523 * the adjacent DBWALL has been seen.
2526 if (Is_knox(&u
.uz
)) {
2529 /* Throne is four columns left, either directly in
2530 * line or one row higher or lower, and doesn't have
2531 * to have been seen yet.
2536 * For 3.6.0 and earlier, it was always in direct line:
2537 * both throne and door on the lower of the two rows.
2539 for (ty
= y
- 1; ty
<= y
+ 1; ++ty
)
2540 if (isok(tx
, ty
) && IS_THRONE(levl
[tx
][ty
].typ
)) {
2541 mptr
->flags
.ludios
= 1;
2546 if (is_drawbridge_wall(x
, y
) < 0)
2550 case DRAWBRIDGE_DOWN
:
2551 if (Is_stronghold(&u
.uz
))
2552 mptr
->flags
.castle
= 1, mptr
->flags
.castletune
= 1;
2560 if (level
.bonesinfo
&& !mptr
->final_resting_place
) {
2561 /* clone the bonesinfo so we aren't dependent upon this
2562 level being in memory */
2563 bonesaddr
= &mptr
->final_resting_place
;
2564 bp
= level
.bonesinfo
;
2566 *bonesaddr
= (struct cemetery
*) alloc(sizeof **bonesaddr
);
2569 bonesaddr
= &(*bonesaddr
)->next
;
2573 /* decide which past hero deaths have become known; there's no
2574 guarantee of either a grave or a ghost, so we go by whether the
2575 current hero has seen the map location where each old one died */
2576 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
)
2577 if (lastseentyp
[bp
->frpx
][bp
->frpy
]) {
2578 bp
->bonesknown
= TRUE
;
2579 mptr
->flags
.knownbones
= 1;
2584 /* valley and sanctum levels get automatic annotation once temple is entered
2587 mapseen_temple(priest
)
2588 struct monst
*priest UNUSED
; /* currently unused; might be useful someday */
2590 mapseen
*mptr
= find_mapseen(&u
.uz
);
2592 if (Is_valley(&u
.uz
))
2593 mptr
->flags
.valley
= 1;
2594 else if (Is_sanctum(&u
.uz
))
2595 mptr
->flags
.msanctum
= 1;
2598 /* room entry message has just been delivered so learn room even if blind */
2600 room_discovered(roomno
)
2603 mapseen
*mptr
= find_mapseen(&u
.uz
);
2605 mptr
->msrooms
[roomno
].seen
= 1;
2608 /* #overview command */
2612 show_overview(0, 0);
2616 /* called for #overview or for end of game disclosure */
2618 show_overview(why
, reason
)
2619 int why
; /* 0 => #overview command,
2620 1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2621 int reason
; /* how hero died; used when disclosing end-of-game level */
2626 /* lazy initialization */
2627 (void) recalc_mapseen();
2629 win
= create_nhwindow(NHW_MENU
);
2630 /* show the endgame levels before the rest of the dungeon,
2631 so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2632 if (In_endgame(&u
.uz
))
2633 traverse_mapseenchn(TRUE
, win
, why
, reason
, &lastdun
);
2634 /* if game is over or we're not in the endgame yet, show the dungeon */
2635 if (why
> 0 || !In_endgame(&u
.uz
))
2636 traverse_mapseenchn(FALSE
, win
, why
, reason
, &lastdun
);
2637 display_nhwindow(win
, TRUE
);
2638 destroy_nhwindow(win
);
2641 /* display endgame levels or non-endgame levels, not both */
2643 traverse_mapseenchn(viewendgame
, win
, why
, reason
, lastdun_p
)
2644 boolean viewendgame
;
2646 int why
, reason
, *lastdun_p
;
2651 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
) {
2652 if (viewendgame
^ In_endgame(&mptr
->lev
))
2655 /* only print out info for a level or a dungeon if interest */
2656 if (why
> 0 || interest_mapseen(mptr
)) {
2657 showheader
= (boolean
) (mptr
->lev
.dnum
!= *lastdun_p
);
2658 print_mapseen(win
, mptr
, why
, reason
, showheader
);
2659 *lastdun_p
= mptr
->lev
.dnum
;
2664 STATIC_OVL
const char *
2669 /* players are computer scientists: 0, 1, 2, n */
2673 /* an() returns too much. index is ok in this case */
2675 return index(vowels
, *obj
) ? "an" : "a";
2685 /* better br_string */
2686 STATIC_OVL
const char *
2690 /* Special case: quest portal says closed if kicked from quest */
2691 boolean closed_portal
= (br
->end2
.dnum
== quest_dnum
2692 && u
.uevent
.qexpelled
);
2696 return closed_portal
? "Sealed portal" : "Portal";
2698 return "Connection";
2700 return br
->end1_up
? "One way stairs up" : "One way stairs down";
2702 return br
->end1_up
? "Stairs up" : "Stairs down";
2708 /* get the name of an endgame level; topten.c does something similar */
2709 STATIC_OVL
const char *
2710 endgamelevelname(outbuf
, indx
)
2714 const char *planename
= 0;
2719 Strcpy(outbuf
, "Astral Plane");
2722 planename
= "Water";
2731 planename
= "Earth";
2735 Sprintf(outbuf
, "Plane of %s", planename
);
2737 Sprintf(outbuf
, "unknown plane #%d", indx
);
2741 STATIC_OVL
const char *
2745 const char *str
= "shop"; /* catchall */
2747 /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2750 str
= "untended shop";
2751 break; /* see recalc_mapseen */
2753 str
= "general store";
2759 str
= "scroll shop";
2762 str
= "potion shop";
2765 str
= "weapon shop";
2768 str
= "delicatessen";
2780 str
= "health food store";
2783 str
= "lighting shop";
2791 /* if player knows about the mastermind tune, append it to Castle annotation;
2792 if drawbridge has been destroyed, flags.castletune will be zero */
2794 tunesuffix(mptr
, outbuf
)
2799 if (mptr
->flags
.castletune
&& u
.uevent
.uheard_tune
) {
2802 if (u
.uevent
.uheard_tune
== 2)
2803 Sprintf(tmp
, "notes \"%s\"", tune
);
2805 Strcpy(tmp
, "5-note tune");
2806 Sprintf(outbuf
, " (play %s to open or close drawbridge)", tmp
);
2811 /* some utility macros for print_mapseen */
2812 #define TAB " " /* three spaces */
2814 #define BULLET "" /* empty; otherwise output becomes cluttered */
2815 #define PREFIX TAB TAB BULLET
2817 /* K&R: don't require support for concatenation of adjacent string literals */
2818 #define PREFIX " " /* two TABs + empty BULLET: six spaces */
2820 #define COMMA (i++ > 0 ? ", " : PREFIX)
2821 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2822 #define ADDNTOBUF(nam, var) \
2825 Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2826 (nam), plur(var)); \
2828 #define ADDTOBUF(nam, var) \
2831 Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
2835 print_mapseen(win
, mptr
, final
, how
, printdun
)
2838 int final
; /* 0: not final; 1: game over, alive; 2: game over, dead */
2839 int how
; /* cause of death; only used if final==2 and mptr->lev==u.uz */
2842 char buf
[BUFSZ
], tmpbuf
[BUFSZ
];
2843 int i
, depthstart
, dnum
;
2844 boolean died_here
= (final
== 2 && on_level(&u
.uz
, &mptr
->lev
));
2846 /* Damnable special cases */
2847 /* The quest and knox should appear to be level 1 to match
2850 dnum
= mptr
->lev
.dnum
;
2851 if (dnum
== quest_dnum
|| dnum
== knox_level
.dnum
)
2854 depthstart
= dungeons
[dnum
].depth_start
;
2857 if (dungeons
[dnum
].dunlev_ureached
== dungeons
[dnum
].entry_lev
2858 /* suppress the negative numbers in the endgame */
2859 || In_endgame(&mptr
->lev
))
2860 Sprintf(buf
, "%s:", dungeons
[dnum
].dname
);
2861 else if (builds_up(&mptr
->lev
))
2862 Sprintf(buf
, "%s: levels %d up to %d",
2863 dungeons
[dnum
].dname
,
2864 depthstart
+ dungeons
[dnum
].entry_lev
- 1,
2865 depthstart
+ dungeons
[dnum
].dunlev_ureached
- 1);
2867 Sprintf(buf
, "%s: levels %d to %d",
2868 dungeons
[dnum
].dname
, depthstart
,
2869 depthstart
+ dungeons
[dnum
].dunlev_ureached
- 1);
2870 putstr(win
, !final
? ATR_INVERSE
: 0, buf
);
2873 /* calculate level number */
2874 i
= depthstart
+ mptr
->lev
.dlevel
- 1;
2875 if (In_endgame(&mptr
->lev
))
2876 Sprintf(buf
, "%s%s:", TAB
, endgamelevelname(tmpbuf
, i
));
2878 Sprintf(buf
, "%sLevel %d:", TAB
, i
);
2880 /* wizmode prints out proto dungeon names for clarity */
2884 if ((slev
= Is_special(&mptr
->lev
)) != 0)
2885 Sprintf(eos(buf
), " [%s]", slev
->proto
);
2887 /* [perhaps print custom annotation on its own line when it's long] */
2889 Sprintf(eos(buf
), " \"%s\"", mptr
->custom
);
2890 if (on_level(&u
.uz
, &mptr
->lev
))
2891 Sprintf(eos(buf
), " <- You %s here.",
2892 (!final
|| (final
== 1 && how
== ASCENDED
)) ? "are"
2893 : (final
== 1 && how
== ESCAPED
) ? "left from"
2895 putstr(win
, !final
? ATR_BOLD
: 0, buf
);
2897 if (mptr
->flags
.forgot
)
2900 if (INTEREST(mptr
->feat
)) {
2903 i
= 0; /* interest counter */
2904 /* List interests in an order vaguely corresponding to
2905 * how important they are.
2907 if (mptr
->feat
.nshop
> 0) {
2908 if (mptr
->feat
.nshop
> 1)
2909 ADDNTOBUF("shop", mptr
->feat
.nshop
);
2911 Sprintf(eos(buf
), "%s%s", COMMA
,
2912 an(shop_string(mptr
->feat
.shoptype
)));
2914 if (mptr
->feat
.naltar
> 0) {
2915 /* Temples + non-temple altars get munged into just "altars" */
2916 if (mptr
->feat
.ntemple
!= mptr
->feat
.naltar
)
2917 ADDNTOBUF("altar", mptr
->feat
.naltar
);
2919 ADDNTOBUF("temple", mptr
->feat
.ntemple
);
2921 /* only print out altar's god if they are all to your god */
2922 if (Amask2align(Msa2amask(mptr
->feat
.msalign
)) == u
.ualign
.type
)
2923 Sprintf(eos(buf
), " to %s", align_gname(u
.ualign
.type
));
2925 ADDNTOBUF("throne", mptr
->feat
.nthrone
);
2926 ADDNTOBUF("fountain", mptr
->feat
.nfount
);
2927 ADDNTOBUF("sink", mptr
->feat
.nsink
);
2928 ADDNTOBUF("grave", mptr
->feat
.ngrave
);
2929 ADDNTOBUF("tree", mptr
->feat
.ntree
);
2931 ADDTOBUF("water", mptr
->feat
.water
);
2932 ADDTOBUF("lava", mptr
->feat
.lava
);
2933 ADDTOBUF("ice", mptr
->feat
.ice
);
2935 /* capitalize afterwards */
2937 buf
[i
] = highc(buf
[i
]);
2938 /* capitalizing it makes it a sentence; terminate with '.' */
2940 putstr(win
, 0, buf
);
2943 /* we assume that these are mutually exclusive */
2945 if (mptr
->flags
.oracle
) {
2946 Sprintf(buf
, "%sOracle of Delphi.", PREFIX
);
2947 } else if (In_sokoban(&mptr
->lev
)) {
2948 Sprintf(buf
, "%s%s.", PREFIX
,
2949 mptr
->flags
.sokosolved
? "Solved" : "Unsolved");
2950 } else if (mptr
->flags
.bigroom
) {
2951 Sprintf(buf
, "%sA very big room.", PREFIX
);
2952 } else if (mptr
->flags
.roguelevel
) {
2953 Sprintf(buf
, "%sA primitive area.", PREFIX
);
2954 } else if (mptr
->flags
.quest_summons
) {
2955 Sprintf(buf
, "%sSummoned by %s.", PREFIX
, ldrname());
2956 } else if (on_level(&mptr
->lev
, &qstart_level
)) {
2957 Sprintf(buf
, "%sHome%s.", PREFIX
,
2958 mptr
->flags
.unreachable
? " (no way back...)" : "");
2959 if (u
.uevent
.qcompleted
)
2960 Sprintf(buf
, "%sCompleted quest for %s.", PREFIX
, ldrname());
2961 else if (mptr
->flags
.questing
)
2962 Sprintf(buf
, "%sGiven quest by %s.", PREFIX
, ldrname());
2963 } else if (mptr
->flags
.ludios
) {
2964 /* presence of the ludios branch in #overview output indicates that
2965 the player has made it onto the level; presence of this annotation
2966 indicates that the fort's entrance has been seen (or mapped) */
2967 Sprintf(buf
, "%sFort Ludios.", PREFIX
);
2968 } else if (mptr
->flags
.castle
) {
2969 Sprintf(buf
, "%sThe castle%s.", PREFIX
, tunesuffix(mptr
, tmpbuf
));
2970 } else if (mptr
->flags
.valley
) {
2971 Sprintf(buf
, "%sValley of the Dead.", PREFIX
);
2972 } else if (mptr
->flags
.msanctum
) {
2973 Sprintf(buf
, "%sMoloch's Sanctum.", PREFIX
);
2976 putstr(win
, 0, buf
);
2978 /* print out branches */
2980 Sprintf(buf
, "%s%s to %s", PREFIX
, br_string2(mptr
->br
),
2981 dungeons
[mptr
->br
->end2
.dnum
].dname
);
2983 /* Since mapseen objects are printed out in increasing order
2984 * of dlevel, clarify which level this branch is going to
2985 * if the branch goes upwards. Unless it's the end game.
2987 if (mptr
->br
->end1_up
&& !In_endgame(&(mptr
->br
->end2
)))
2988 Sprintf(eos(buf
), ", level %d", depth(&(mptr
->br
->end2
)));
2990 putstr(win
, 0, buf
);
2993 /* maybe print out bones details */
2994 if (mptr
->final_resting_place
|| final
) {
2995 struct cemetery
*bp
;
2996 int kncnt
= !died_here
? 0 : 1;
2998 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
)
2999 if (bp
->bonesknown
|| wizard
|| final
)
3002 Sprintf(buf
, "%s%s", PREFIX
, "Final resting place for");
3003 putstr(win
, 0, buf
);
3005 /* disclosure occurs before bones creation, so listing dead
3006 hero here doesn't give away whether bones are produced */
3007 formatkiller(tmpbuf
, sizeof tmpbuf
, how
, TRUE
);
3008 /* rephrase a few death reasons to work with "you" */
3009 (void) strsubst(tmpbuf
, " himself", " yourself");
3010 (void) strsubst(tmpbuf
, " herself", " yourself");
3011 (void) strsubst(tmpbuf
, " his ", " your ");
3012 (void) strsubst(tmpbuf
, " her ", " your ");
3013 Sprintf(buf
, "%s%syou, %s%c", PREFIX
, TAB
, tmpbuf
,
3014 --kncnt
? ',' : '.');
3015 putstr(win
, 0, buf
);
3017 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
) {
3018 if (bp
->bonesknown
|| wizard
|| final
) {
3019 Sprintf(buf
, "%s%s%s, %s%c", PREFIX
, TAB
, bp
->who
,
3020 bp
->how
, --kncnt
? ',' : '.');
3021 putstr(win
, 0, buf
);