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
void FDECL(print_mapseen
, (winid
, mapseen
*, int, int, BOOLEAN_P
));
66 STATIC_DCL boolean
FDECL(interest_mapseen
, (mapseen
*));
67 STATIC_DCL
void FDECL(traverse_mapseenchn
, (BOOLEAN_P
, winid
,
69 STATIC_DCL
const char *FDECL(seen_string
, (XCHAR_P
, const char *));
70 STATIC_DCL
const char *FDECL(br_string2
, (branch
*));
71 STATIC_DCL
const char *FDECL(endgamelevelname
, (char *, int));
72 STATIC_DCL
const char *FDECL(shop_string
, (int));
73 STATIC_DCL
char *FDECL(tunesuffix
, (mapseen
*, char *));
76 #define DD dungeons[i]
77 STATIC_DCL
void NDECL(dumpit
);
86 if (!explicitdebug(__FILE__
))
89 for (i
= 0; i
< n_dgns
; i
++) {
90 fprintf(stderr
, "\n#%d \"%s\" (%s):\n", i
, DD
.dname
, DD
.proto
);
91 fprintf(stderr
, " num_dunlevs %d, dunlev_ureached %d\n",
92 DD
.num_dunlevs
, DD
.dunlev_ureached
);
93 fprintf(stderr
, " depth_start %d, ledger_start %d\n",
94 DD
.depth_start
, DD
.ledger_start
);
95 fprintf(stderr
, " flags:%s%s%s\n",
96 DD
.flags
.rogue_like
? " rogue_like" : "",
97 DD
.flags
.maze_like
? " maze_like" : "",
98 DD
.flags
.hellish
? " hellish" : "");
101 fprintf(stderr
, "\nSpecial levels:\n");
102 for (x
= sp_levchn
; x
; x
= x
->next
) {
103 fprintf(stderr
, "%s (%d): ", x
->proto
, x
->rndlevs
);
104 fprintf(stderr
, "on %d, %d; ", x
->dlevel
.dnum
, x
->dlevel
.dlevel
);
105 fprintf(stderr
, "flags:%s%s%s%s\n",
106 x
->flags
.rogue_like
? " rogue_like" : "",
107 x
->flags
.maze_like
? " maze_like" : "",
108 x
->flags
.hellish
? " hellish" : "",
109 x
->flags
.town
? " town" : "");
112 fprintf(stderr
, "\nBranches:\n");
113 for (br
= branches
; br
; br
= br
->next
) {
114 fprintf(stderr
, "%d: %s, end1 %d %d, end2 %d %d, %s\n", br
->id
,
117 : br
->type
== BR_NO_END1
119 : br
->type
== BR_NO_END2
121 : br
->type
== BR_PORTAL
124 br
->end1
.dnum
, br
->end1
.dlevel
, br
->end2
.dnum
,
125 br
->end2
.dlevel
, br
->end1_up
? "end1 up" : "end1 down");
128 fprintf(stderr
, "\nDone\n");
133 /* Save the dungeon structures. */
135 save_dungeon(fd
, perform_write
, free_data
)
137 boolean perform_write
, free_data
;
140 mapseen
*curr_ms
, *next_ms
;
144 bwrite(fd
, (genericptr_t
) &n_dgns
, sizeof n_dgns
);
145 bwrite(fd
, (genericptr_t
) dungeons
,
146 sizeof(dungeon
) * (unsigned) n_dgns
);
147 bwrite(fd
, (genericptr_t
) &dungeon_topology
, sizeof dungeon_topology
);
148 bwrite(fd
, (genericptr_t
) tune
, sizeof tune
);
150 for (count
= 0, curr
= branches
; curr
; curr
= curr
->next
)
152 bwrite(fd
, (genericptr_t
) &count
, sizeof(count
));
154 for (curr
= branches
; curr
; curr
= curr
->next
)
155 bwrite(fd
, (genericptr_t
) curr
, sizeof(branch
));
157 count
= maxledgerno();
158 bwrite(fd
, (genericptr_t
) &count
, sizeof count
);
159 bwrite(fd
, (genericptr_t
) level_info
,
160 (unsigned) count
* sizeof(struct linfo
));
161 bwrite(fd
, (genericptr_t
) &inv_pos
, sizeof inv_pos
);
163 for (count
= 0, curr_ms
= mapseenchn
; curr_ms
;
164 curr_ms
= curr_ms
->next
)
166 bwrite(fd
, (genericptr_t
) &count
, sizeof(count
));
168 for (curr_ms
= mapseenchn
; curr_ms
; curr_ms
= curr_ms
->next
)
169 save_mapseen(fd
, curr_ms
);
173 for (curr
= branches
; curr
; curr
= next
) {
175 free((genericptr_t
) curr
);
178 for (curr_ms
= mapseenchn
; curr_ms
; curr_ms
= next_ms
) {
179 next_ms
= curr_ms
->next
;
181 free((genericptr_t
) curr_ms
->custom
);
182 free((genericptr_t
) curr_ms
);
188 /* Restore the dungeon structures. */
195 mapseen
*curr_ms
, *last_ms
;
197 mread(fd
, (genericptr_t
) &n_dgns
, sizeof(n_dgns
));
198 mread(fd
, (genericptr_t
) dungeons
, sizeof(dungeon
) * (unsigned) n_dgns
);
199 mread(fd
, (genericptr_t
) &dungeon_topology
, sizeof dungeon_topology
);
200 mread(fd
, (genericptr_t
) tune
, sizeof tune
);
202 last
= branches
= (branch
*) 0;
204 mread(fd
, (genericptr_t
) &count
, sizeof(count
));
205 for (i
= 0; i
< count
; i
++) {
206 curr
= (branch
*) alloc(sizeof(branch
));
207 mread(fd
, (genericptr_t
) curr
, sizeof(branch
));
208 curr
->next
= (branch
*) 0;
216 mread(fd
, (genericptr_t
) &count
, sizeof(count
));
217 if (count
>= MAXLINFO
)
218 panic("level information count larger (%d) than allocated size",
220 mread(fd
, (genericptr_t
) level_info
,
221 (unsigned) count
* sizeof(struct linfo
));
222 mread(fd
, (genericptr_t
) &inv_pos
, sizeof inv_pos
);
224 mread(fd
, (genericptr_t
) &count
, sizeof(count
));
225 last_ms
= (mapseen
*) 0;
226 for (i
= 0; i
< count
; i
++) {
227 curr_ms
= load_mapseen(fd
);
228 curr_ms
->next
= (mapseen
*) 0;
230 last_ms
->next
= curr_ms
;
232 mapseenchn
= curr_ms
;
238 Fread(ptr
, size
, nitems
, stream
)
245 if ((cnt
= dlb_fread(ptr
, size
, nitems
, stream
)) != nitems
) {
247 "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
248 (size
* nitems
), (size
* cnt
));
249 terminate(EXIT_FAILURE
);
259 for (i
= 0; i
< n_dgns
; i
++)
260 if (!strcmp(dungeons
[i
].dname
, s
))
263 panic("Couldn't resolve dungeon number for name \"%s\".", s
);
273 for (curr
= sp_levchn
; curr
; curr
= curr
->next
)
274 if (!strcmpi(s
, curr
->proto
))
279 /* Find the branch that links the named dungeon. */
282 const char *s
; /* dungeon name */
283 struct proto_dungeon
*pd
;
288 for (i
= 0; i
< pd
->n_brs
; i
++)
289 if (!strcmp(pd
->tmpbranch
[i
].name
, s
))
292 panic("find_branch: can't find %s", s
);
294 /* support for level tport by name */
298 for (br
= branches
; br
; br
= br
->next
) {
299 dnam
= dungeons
[br
->end2
.dnum
].dname
;
300 if (!strcmpi(dnam
, s
)
301 || (!strncmpi(dnam
, "The ", 4) && !strcmpi(dnam
+ 4, s
)))
304 i
= br
? ((ledger_no(&br
->end1
) << 8) | ledger_no(&br
->end2
)) : -1;
310 * Find the "parent" by searching the prototype branch list for the branch
311 * listing, then figuring out to which dungeon it belongs.
315 const char *s
; /* dungeon name */
316 struct proto_dungeon
*pd
;
321 i
= find_branch(s
, pd
);
323 * Got branch, now find parent dungeon. Stop if we have reached
324 * "this" dungeon (if we haven't found it by now it is an error).
326 for (pdnum
= 0; strcmp(pd
->tmpdungeon
[pdnum
].name
, s
); pdnum
++)
327 if ((i
-= pd
->tmpdungeon
[pdnum
].branches
) < 0)
330 panic("parent_dnum: couldn't resolve branch.");
336 * Return a starting point and number of successive positions a level
337 * or dungeon entrance can occupy.
339 * Note: This follows the acouple (instead of the rcouple) rules for a
340 * negative random component (randc < 0). These rules are found
341 * in dgn_comp.y. The acouple [absolute couple] section says that
342 * a negative random component means from the (adjusted) base to the
343 * end of the dungeon.
346 level_range(dgn
, base
, randc
, chain
, pd
, adjusted_base
)
348 int base
, randc
, chain
;
349 struct proto_dungeon
*pd
;
352 int lmax
= dungeons
[dgn
].num_dunlevs
;
354 if (chain
>= 0) { /* relative to a special level */
355 s_level
*levtmp
= pd
->final_lev
[chain
];
357 panic("level_range: empty chain level!");
359 base
+= levtmp
->dlevel
.dlevel
;
360 } else { /* absolute in the dungeon */
361 /* from end of dungeon */
363 base
= (lmax
+ base
+ 1);
366 if (base
< 1 || base
> lmax
)
367 panic("level_range: base value out of range");
369 *adjusted_base
= base
;
371 if (randc
== -1) { /* from base to end of dungeon */
372 return (lmax
- base
+ 1);
374 /* make sure we don't run off the end of the dungeon */
375 return (((base
+ randc
- 1) > lmax
) ? lmax
- base
+ 1 : randc
);
376 } /* else only one choice */
383 struct proto_dungeon
*pd
;
385 int i
, j
, num
, base
, dnum
= parent_dnum(s
, pd
);
388 i
= find_branch(s
, pd
);
389 num
= level_range(dnum
, pd
->tmpbranch
[i
].lev
.base
,
390 pd
->tmpbranch
[i
].lev
.rand
, pd
->tmpbranch
[i
].chain
, pd
,
393 /* KMH -- Try our best to find a level without an existing branch */
398 for (curr
= branches
; curr
; curr
= curr
->next
)
399 if ((curr
->end1
.dnum
== dnum
&& curr
->end1
.dlevel
== base
+ i
)
400 || (curr
->end2
.dnum
== dnum
&& curr
->end2
.dlevel
== base
+ i
))
402 } while (curr
&& i
!= j
);
406 /* Convert from the temporary branch type to the dungeon branch type. */
408 correct_branch_type(tbr
)
409 struct tmpbranch
*tbr
;
415 return tbr
->up
? BR_NO_END1
: BR_NO_END2
;
417 return tbr
->up
? BR_NO_END2
: BR_NO_END1
;
421 impossible("correct_branch_type: unknown branch type");
426 * Add the given branch to the branch list. The branch list is ordered
427 * by end1 dungeon and level followed by end2 dungeon and level. If
428 * extract_first is true, then the branch is already part of the list
429 * but needs to be repositioned.
432 insert_branch(new_branch
, extract_first
)
434 boolean extract_first
;
437 long new_val
, curr_val
, prev_val
;
440 for (prev
= 0, curr
= branches
; curr
; prev
= curr
, curr
= curr
->next
)
441 if (curr
== new_branch
)
445 panic("insert_branch: not found");
447 prev
->next
= curr
->next
;
449 branches
= curr
->next
;
451 new_branch
->next
= (branch
*) 0;
453 /* Convert the branch into a unique number so we can sort them. */
454 #define branch_val(bp) \
455 ((((long) (bp)->end1.dnum * (MAXLEVEL + 1) + (long) (bp)->end1.dlevel) \
456 * (MAXDUNGEON + 1) * (MAXLEVEL + 1)) \
457 + ((long) (bp)->end2.dnum * (MAXLEVEL + 1) + (long) (bp)->end2.dlevel))
460 * Insert the new branch into the correct place in the branch list.
464 new_val
= branch_val(new_branch
);
465 for (curr
= branches
; curr
;
466 prev_val
= curr_val
, prev
= curr
, curr
= curr
->next
) {
467 curr_val
= branch_val(curr
);
468 if (prev_val
< new_val
&& new_val
<= curr_val
)
472 new_branch
->next
= curr
;
473 prev
->next
= new_branch
;
475 new_branch
->next
= branches
;
476 branches
= new_branch
;
480 /* Add a dungeon branch to the branch list. */
482 add_branch(dgn
, child_entry_level
, pd
)
484 int child_entry_level
;
485 struct proto_dungeon
*pd
;
487 static int branch_id
= 0;
491 branch_num
= find_branch(dungeons
[dgn
].dname
, pd
);
492 new_branch
= (branch
*) alloc(sizeof(branch
));
493 (void) memset((genericptr_t
)new_branch
, 0, sizeof(branch
));
494 new_branch
->next
= (branch
*) 0;
495 new_branch
->id
= branch_id
++;
496 new_branch
->type
= correct_branch_type(&pd
->tmpbranch
[branch_num
]);
497 new_branch
->end1
.dnum
= parent_dnum(dungeons
[dgn
].dname
, pd
);
498 new_branch
->end1
.dlevel
= parent_dlevel(dungeons
[dgn
].dname
, pd
);
499 new_branch
->end2
.dnum
= dgn
;
500 new_branch
->end2
.dlevel
= child_entry_level
;
501 new_branch
->end1_up
= pd
->tmpbranch
[branch_num
].up
? TRUE
: FALSE
;
503 insert_branch(new_branch
, FALSE
);
508 * Add new level to special level chain. Insert it in level order with the
509 * other levels in this dungeon. This assumes that we are never given a
510 * level that has a dungeon number less than the dungeon number of the
517 s_level
*prev
, *curr
;
519 prev
= (s_level
*) 0;
520 for (curr
= sp_levchn
; curr
; curr
= curr
->next
) {
521 if (curr
->dlevel
.dnum
== new_lev
->dlevel
.dnum
522 && curr
->dlevel
.dlevel
> new_lev
->dlevel
.dlevel
)
527 new_lev
->next
= sp_levchn
;
530 new_lev
->next
= curr
;
531 prev
->next
= new_lev
;
536 init_level(dgn
, proto_index
, pd
)
537 int dgn
, proto_index
;
538 struct proto_dungeon
*pd
;
541 struct tmplevel
*tlevel
= &pd
->tmplevel
[proto_index
];
543 pd
->final_lev
[proto_index
] = (s_level
*) 0; /* no "real" level */
544 if (!wizard
&& tlevel
->chance
<= rn2(100))
547 pd
->final_lev
[proto_index
] = new_level
=
548 (s_level
*) alloc(sizeof(s_level
));
549 (void) memset((genericptr_t
)new_level
, 0, sizeof(s_level
));
550 /* load new level with data */
551 Strcpy(new_level
->proto
, tlevel
->name
);
552 new_level
->boneid
= tlevel
->boneschar
;
553 new_level
->dlevel
.dnum
= dgn
;
554 new_level
->dlevel
.dlevel
= 0; /* for now */
556 new_level
->flags
.town
= !!(tlevel
->flags
& TOWN
);
557 new_level
->flags
.hellish
= !!(tlevel
->flags
& HELLISH
);
558 new_level
->flags
.maze_like
= !!(tlevel
->flags
& MAZELIKE
);
559 new_level
->flags
.rogue_like
= !!(tlevel
->flags
& ROGUELIKE
);
560 new_level
->flags
.align
= ((tlevel
->flags
& D_ALIGN_MASK
) >> 4);
561 if (!new_level
->flags
.align
)
562 new_level
->flags
.align
=
563 ((pd
->tmpdungeon
[dgn
].flags
& D_ALIGN_MASK
) >> 4);
565 new_level
->rndlevs
= tlevel
->rndlevs
;
566 new_level
->next
= (s_level
*) 0;
570 possible_places(idx
, map
, pd
)
571 int idx
; /* prototype index */
572 boolean
*map
; /* array MAXLEVEL+1 in length */
573 struct proto_dungeon
*pd
;
576 s_level
*lev
= pd
->final_lev
[idx
];
578 /* init level possibilities */
579 for (i
= 0; i
<= MAXLEVEL
; i
++)
582 /* get base and range and set those entries to true */
583 count
= level_range(lev
->dlevel
.dnum
, pd
->tmplevel
[idx
].lev
.base
,
584 pd
->tmplevel
[idx
].lev
.rand
, pd
->tmplevel
[idx
].chain
,
586 for (i
= start
; i
< start
+ count
; i
++)
589 /* mark off already placed levels */
590 for (i
= pd
->start
; i
< idx
; i
++) {
591 if (pd
->final_lev
[i
] && map
[pd
->final_lev
[i
]->dlevel
.dlevel
]) {
592 map
[pd
->final_lev
[i
]->dlevel
.dlevel
] = FALSE
;
600 /* Pick the nth TRUE entry in the given boolean array. */
603 boolean
*map
; /* an array MAXLEVEL+1 in size */
607 for (i
= 1; i
<= MAXLEVEL
; i
++)
608 if (map
[i
] && !nth
--)
610 panic("pick_level: ran out of valid levels");
615 static void FDECL(indent
, (int));
627 * Place a level. First, find the possible places on a dungeon map
628 * template. Next pick one. Then try to place the next level. If
629 * successful, we're done. Otherwise, try another (and another) until
630 * all possible places have been tried. If all possible places have
631 * been exhausted, return false.
634 place_level(proto_index
, pd
)
636 struct proto_dungeon
*pd
;
638 boolean map
[MAXLEVEL
+ 1]; /* valid levels are 1..MAXLEVEL inclusive */
645 if (proto_index
== pd
->n_levs
)
646 return TRUE
; /* at end of proto levels */
648 lev
= pd
->final_lev
[proto_index
];
650 /* No level created for this prototype, goto next. */
652 return place_level(proto_index
+ 1, pd
);
654 npossible
= possible_places(proto_index
, map
, pd
);
656 for (; npossible
; --npossible
) {
657 lev
->dlevel
.dlevel
= pick_level(map
, rn2(npossible
));
659 indent(proto_index
- pd
->start
);
660 fprintf(stderr
, "%s: trying %d [ ", lev
->proto
, lev
->dlevel
.dlevel
);
661 for (i
= 1; i
<= MAXLEVEL
; i
++)
663 fprintf(stderr
, "%d ", i
);
664 fprintf(stderr
, "]\n");
666 if (place_level(proto_index
+ 1, pd
))
668 map
[lev
->dlevel
.dlevel
] = FALSE
; /* this choice didn't work */
671 indent(proto_index
- pd
->start
);
672 fprintf(stderr
, "%s: failed\n", lev
->proto
);
678 const char *lev_name
;
680 } level_map
[] = { { "air", &air_level
},
681 { "asmodeus", &asmodeus_level
},
682 { "astral", &astral_level
},
683 { "baalz", &baalzebub_level
},
684 { "bigrm", &bigroom_level
},
685 { "castle", &stronghold_level
},
686 { "earth", &earth_level
},
687 { "fakewiz1", &portal_level
},
688 { "fire", &fire_level
},
689 { "juiblex", &juiblex_level
},
690 { "knox", &knox_level
},
691 { "medusa", &medusa_level
},
692 { "oracle", &oracle_level
},
693 { "orcus", &orcus_level
},
694 { "rogue", &rogue_level
},
695 { "sanctum", &sanctum_level
},
696 { "valley", &valley_level
},
697 { "water", &water_level
},
698 { "wizard1", &wiz1_level
},
699 { "wizard2", &wiz2_level
},
700 { "wizard3", &wiz3_level
},
701 { "minend", &mineend_level
},
702 { "soko1", &sokoend_level
},
703 { X_START
, &qstart_level
},
704 { X_LOCATE
, &qlocate_level
},
705 { X_GOAL
, &nemesis_level
},
706 { "", (d_level
*) 0 } };
708 /* initialize the "dungeon" structs */
713 register int i
, cl
= 0, cb
= 0;
715 struct proto_dungeon pd
;
716 struct level_map
*lev_map
;
717 struct version_info vers_info
;
719 pd
.n_levs
= pd
.n_brs
= 0;
721 dgn_file
= dlb_fopen(DUNGEON_FILE
, RDBMODE
);
724 Sprintf(tbuf
, "Cannot open dungeon description - \"%s", DUNGEON_FILE
);
725 #ifdef DLBRSRC /* using a resource from the executable */
726 Strcat(tbuf
, "\" resource!");
727 #else /* using a file or DLB file */
729 Strcat(tbuf
, "\" from ");
730 #ifdef PREFIXES_IN_USE
731 Strcat(tbuf
, "\n\"");
732 if (fqn_prefix
[DATAPREFIX
])
733 Strcat(tbuf
, fqn_prefix
[DATAPREFIX
]);
737 Strcat(tbuf
, DLBFILE
);
739 Strcat(tbuf
, "\" file!");
742 interject_assistance(1, INTERJECT_PANIC
, (genericptr_t
) tbuf
,
743 (genericptr_t
) fqn_prefix
[DATAPREFIX
]);
748 /* validate the data's version against the program's version */
749 Fread((genericptr_t
) &vers_info
, sizeof vers_info
, 1, dgn_file
);
750 /* we'd better clear the screen now, since when error messages come from
751 * check_version() they will be printed using pline(), which doesn't
752 * mix with the raw messages that might be already on the screen
754 if (iflags
.window_inited
)
755 clear_nhwindow(WIN_MAP
);
756 if (!check_version(&vers_info
, DUNGEON_FILE
, TRUE
))
757 panic("Dungeon description not valid.");
760 * Read in each dungeon and transfer the results to the internal
763 sp_levchn
= (s_level
*) 0;
764 Fread((genericptr_t
) &n_dgns
, sizeof(int), 1, dgn_file
);
765 if (n_dgns
>= MAXDUNGEON
)
766 panic("init_dungeons: too many dungeons");
768 for (i
= 0; i
< n_dgns
; i
++) {
769 Fread((genericptr_t
) &pd
.tmpdungeon
[i
], sizeof(struct tmpdungeon
), 1,
771 if (!wizard
&& pd
.tmpdungeon
[i
].chance
772 && (pd
.tmpdungeon
[i
].chance
<= rn2(100))) {
775 /* skip over any levels or branches */
776 for (j
= 0; j
< pd
.tmpdungeon
[i
].levels
; j
++)
777 Fread((genericptr_t
) &pd
.tmplevel
[cl
],
778 sizeof(struct tmplevel
), 1, dgn_file
);
780 for (j
= 0; j
< pd
.tmpdungeon
[i
].branches
; j
++)
781 Fread((genericptr_t
) &pd
.tmpbranch
[cb
],
782 sizeof(struct tmpbranch
), 1, dgn_file
);
788 Strcpy(dungeons
[i
].dname
, pd
.tmpdungeon
[i
].name
);
789 Strcpy(dungeons
[i
].proto
, pd
.tmpdungeon
[i
].protoname
);
790 dungeons
[i
].boneid
= pd
.tmpdungeon
[i
].boneschar
;
792 if (pd
.tmpdungeon
[i
].lev
.rand
)
793 dungeons
[i
].num_dunlevs
= (xchar
) rn1(pd
.tmpdungeon
[i
].lev
.rand
,
794 pd
.tmpdungeon
[i
].lev
.base
);
796 dungeons
[i
].num_dunlevs
= (xchar
) pd
.tmpdungeon
[i
].lev
.base
;
799 dungeons
[i
].ledger_start
= 0;
800 dungeons
[i
].depth_start
= 1;
801 dungeons
[i
].dunlev_ureached
= 1;
803 dungeons
[i
].ledger_start
=
804 dungeons
[i
- 1].ledger_start
+ dungeons
[i
- 1].num_dunlevs
;
805 dungeons
[i
].dunlev_ureached
= 0;
808 dungeons
[i
].flags
.hellish
= !!(pd
.tmpdungeon
[i
].flags
& HELLISH
);
809 dungeons
[i
].flags
.maze_like
= !!(pd
.tmpdungeon
[i
].flags
& MAZELIKE
);
810 dungeons
[i
].flags
.rogue_like
= !!(pd
.tmpdungeon
[i
].flags
& ROGUELIKE
);
811 dungeons
[i
].flags
.align
=
812 ((pd
.tmpdungeon
[i
].flags
& D_ALIGN_MASK
) >> 4);
814 * Set the entry level for this dungeon. The pd.tmpdungeon entry
816 * < 0 from bottom (-1 == bottom level)
818 * > 0 actual level (1 = top)
820 * Note that the entry_lev field in the dungeon structure is
821 * redundant. It is used only here and in print_dungeon().
823 if (pd
.tmpdungeon
[i
].entry_lev
< 0) {
824 dungeons
[i
].entry_lev
=
825 dungeons
[i
].num_dunlevs
+ pd
.tmpdungeon
[i
].entry_lev
+ 1;
826 if (dungeons
[i
].entry_lev
<= 0)
827 dungeons
[i
].entry_lev
= 1;
828 } else if (pd
.tmpdungeon
[i
].entry_lev
> 0) {
829 dungeons
[i
].entry_lev
= pd
.tmpdungeon
[i
].entry_lev
;
830 if (dungeons
[i
].entry_lev
> dungeons
[i
].num_dunlevs
)
831 dungeons
[i
].entry_lev
= dungeons
[i
].num_dunlevs
;
832 } else { /* default */
833 dungeons
[i
].entry_lev
= 1; /* defaults to top level */
836 if (i
) { /* set depth */
841 br
= add_branch(i
, dungeons
[i
].entry_lev
, &pd
);
843 /* Get the depth of the connecting end. */
844 if (br
->end1
.dnum
== i
) {
845 from_depth
= depth(&br
->end2
);
846 from_up
= !br
->end1_up
;
848 from_depth
= depth(&br
->end1
);
849 from_up
= br
->end1_up
;
853 * Calculate the depth of the top of the dungeon via
854 * its branch. First, the depth of the entry point:
856 * depth of branch from "parent" dungeon
857 * + -1 or 1 depending on an up or down stair or
860 * Followed by the depth of the top of the dungeon:
862 * - (entry depth - 1)
864 * We'll say that portals stay on the same depth.
866 dungeons
[i
].depth_start
=
867 from_depth
+ (br
->type
== BR_PORTAL
? 0 : (from_up
? -1 : 1))
868 - (dungeons
[i
].entry_lev
- 1);
871 /* this is redundant - it should have been flagged by dgn_comp */
872 if (dungeons
[i
].num_dunlevs
> MAXLEVEL
)
873 dungeons
[i
].num_dunlevs
= MAXLEVEL
;
875 pd
.start
= pd
.n_levs
; /* save starting point */
876 pd
.n_levs
+= pd
.tmpdungeon
[i
].levels
;
877 if (pd
.n_levs
> LEV_LIMIT
)
878 panic("init_dungeon: too many special levels");
880 * Read in the prototype special levels. Don't add generated
881 * special levels until they are all placed.
883 for (; cl
< pd
.n_levs
; cl
++) {
884 Fread((genericptr_t
) &pd
.tmplevel
[cl
], sizeof(struct tmplevel
), 1,
886 init_level(i
, cl
, &pd
);
889 * Recursively place the generated levels for this dungeon. This
890 * routine will attempt all possible combinations before giving
893 if (!place_level(pd
.start
, &pd
))
894 panic("init_dungeon: couldn't place levels");
896 fprintf(stderr
, "--- end of dungeon %d ---\n", i
);
900 for (; pd
.start
< pd
.n_levs
; pd
.start
++)
901 if (pd
.final_lev
[pd
.start
])
902 add_level(pd
.final_lev
[pd
.start
]);
904 pd
.n_brs
+= pd
.tmpdungeon
[i
].branches
;
905 if (pd
.n_brs
> BRANCH_LIMIT
)
906 panic("init_dungeon: too many branches");
907 for (; cb
< pd
.n_brs
; cb
++)
908 Fread((genericptr_t
) &pd
.tmpbranch
[cb
], sizeof(struct tmpbranch
),
911 (void) dlb_fclose(dgn_file
);
913 for (i
= 0; i
< 5; i
++)
914 tune
[i
] = 'A' + rn2(7);
918 * Find most of the special levels and dungeons so we can access their
921 for (lev_map
= level_map
; lev_map
->lev_name
[0]; lev_map
++) {
922 x
= find_level(lev_map
->lev_name
);
924 assign_level(lev_map
->lev_spec
, &x
->dlevel
);
925 if (!strncmp(lev_map
->lev_name
, "x-", 2)) {
926 /* This is where the name substitution on the
927 * levels of the quest dungeon occur.
929 Sprintf(x
->proto
, "%s%s", urole
.filecode
,
930 &lev_map
->lev_name
[1]);
931 } else if (lev_map
->lev_spec
== &knox_level
) {
934 * Kludge to allow floating Knox entrance. We
935 * specify a floating entrance by the fact that
936 * its entrance (end1) has a bogus dnum, namely
939 for (br
= branches
; br
; br
= br
->next
)
940 if (on_level(&br
->end2
, &knox_level
))
944 br
->end1
.dnum
= n_dgns
;
945 /* adjust the branch's position on the list */
946 insert_branch(br
, TRUE
);
951 * I hate hardwiring these names. :-(
953 quest_dnum
= dname_to_dnum("The Quest");
954 sokoban_dnum
= dname_to_dnum("Sokoban");
955 mines_dnum
= dname_to_dnum("The Gnomish Mines");
956 tower_dnum
= dname_to_dnum("Vlad's Tower");
958 /* one special fixup for dummy surface level */
959 if ((x
= find_level("dummy")) != 0) {
961 /* the code above puts earth one level above dungeon level #1,
962 making the dummy level overlay level 1; but the whole reason
963 for having the dummy level is to make earth have depth -1
964 instead of 0, so adjust the start point to shift endgame up */
965 if (dunlevs_in_dungeon(&x
->dlevel
) > 1 - dungeons
[i
].depth_start
)
966 dungeons
[i
].depth_start
-= 1;
967 /* TO DO: strip "dummy" out all the way here,
968 so that it's hidden from <ctrl/O> feedback. */
976 /* return the level number for lev in *this* dungeon */
984 /* return the lowest level number for *this* dungeon */
986 dunlevs_in_dungeon(lev
)
989 return dungeons
[lev
->dnum
].num_dunlevs
;
992 /* return the lowest level explored in the game*/
994 deepest_lev_reached(noquest
)
997 /* this function is used for three purposes: to provide a factor
998 * of difficulty in monster generation; to provide a factor of
999 * difficulty in experience calculations (botl.c and end.c); and
1000 * to insert the deepest level reached in the game in the topten
1001 * display. the 'noquest' arg switch is required for the latter.
1003 * from the player's point of view, going into the Quest is _not_
1004 * going deeper into the dungeon -- it is going back "home", where
1005 * the dungeon starts at level 1. given the setup in dungeon.def,
1006 * the depth of the Quest (thought of as starting at level 1) is
1007 * never lower than the level of entry into the Quest, so we exclude
1008 * the Quest from the topten "deepest level reached" display
1009 * calculation. _However_ the Quest is a difficult dungeon, so we
1010 * include it in the factor of difficulty calculations.
1014 register schar ret
= 0;
1016 for (i
= 0; i
< n_dgns
; i
++) {
1017 if (noquest
&& i
== quest_dnum
)
1019 tmp
.dlevel
= dungeons
[i
].dunlev_ureached
;
1020 if (tmp
.dlevel
== 0)
1023 if (depth(&tmp
) > ret
)
1029 /* return a bookkeeping level number for purpose of comparisons and
1035 return (xchar
) (lev
->dlevel
+ dungeons
[lev
->dnum
].ledger_start
);
1039 * The last level in the bookkeeping list of level is the bottom of the last
1040 * dungeon in the dungeons[] array.
1042 * Maxledgerno() -- which is the max number of levels in the bookkeeping
1043 * list, should not be confused with dunlevs_in_dungeon(lev) -- which
1044 * returns the max number of levels in lev's dungeon, and both should
1045 * not be confused with deepest_lev_reached() -- which returns the lowest
1046 * depth visited by the player.
1051 return (xchar
) (dungeons
[n_dgns
- 1].ledger_start
1052 + dungeons
[n_dgns
- 1].num_dunlevs
);
1055 /* return the dungeon that this ledgerno exists in */
1057 ledger_to_dnum(ledgerno
)
1062 /* find i such that (i->base + 1) <= ledgerno <= (i->base + i->count) */
1063 for (i
= 0; i
< n_dgns
; i
++)
1064 if (dungeons
[i
].ledger_start
< ledgerno
1065 && ledgerno
<= dungeons
[i
].ledger_start
+ dungeons
[i
].num_dunlevs
)
1068 panic("level number out of range [ledger_to_dnum(%d)]", (int) ledgerno
);
1073 /* return the level of the dungeon this ledgerno exists in */
1075 ledger_to_dlev(ledgerno
)
1078 return (xchar
) (ledgerno
1079 - dungeons
[ledger_to_dnum(ledgerno
)].ledger_start
);
1082 /* returns the depth of a level, in floors below the surface
1083 (note levels in different dungeons can have the same depth) */
1088 return (schar
) (dungeons
[lev
->dnum
].depth_start
+ lev
->dlevel
- 1);
1091 /* are "lev1" and "lev2" actually the same? */
1093 on_level(lev1
, lev2
)
1094 d_level
*lev1
, *lev2
;
1096 return (boolean
) (lev1
->dnum
== lev2
->dnum
1097 && lev1
->dlevel
== lev2
->dlevel
);
1100 /* is this level referenced in the special level chain? */
1107 for (levtmp
= sp_levchn
; levtmp
; levtmp
= levtmp
->next
)
1108 if (on_level(lev
, &levtmp
->dlevel
))
1111 return (s_level
*) 0;
1115 * Is this a multi-dungeon branch level? If so, return a pointer to the
1116 * branch. Otherwise, return null.
1124 for (curr
= branches
; curr
; curr
= curr
->next
) {
1125 if (on_level(lev
, &curr
->end1
) || on_level(lev
, &curr
->end2
))
1128 return (branch
*) 0;
1131 /* returns True iff the branch 'lev' is in a branch which builds up */
1136 dungeon
*dptr
= &dungeons
[lev
->dnum
];
1138 * FIXME: this misclassifies a single level branch reached via stairs
1139 * from below. Saving grace is that no such branches currently exist.
1141 return (boolean
) (dptr
->num_dunlevs
> 1
1142 && dptr
->entry_lev
== dptr
->num_dunlevs
);
1145 /* goto the next level (or appropriate dungeon) */
1147 next_level(at_stairs
)
1150 if (at_stairs
&& u
.ux
== sstairs
.sx
&& u
.uy
== sstairs
.sy
) {
1151 /* Taking a down dungeon branch. */
1152 goto_level(&sstairs
.tolev
, at_stairs
, FALSE
, FALSE
);
1154 /* Going down a stairs or jump in a trap door. */
1157 newlevel
.dnum
= u
.uz
.dnum
;
1158 newlevel
.dlevel
= u
.uz
.dlevel
+ 1;
1159 goto_level(&newlevel
, at_stairs
, !at_stairs
, FALSE
);
1163 /* goto the previous level (or appropriate dungeon) */
1165 prev_level(at_stairs
)
1168 if (at_stairs
&& u
.ux
== sstairs
.sx
&& u
.uy
== sstairs
.sy
) {
1169 /* Taking an up dungeon branch. */
1170 /* KMH -- Upwards branches are okay if not level 1 */
1171 /* (Just make sure it doesn't go above depth 1) */
1172 if (!u
.uz
.dnum
&& u
.uz
.dlevel
== 1 && !u
.uhave
.amulet
)
1175 goto_level(&sstairs
.tolev
, at_stairs
, FALSE
, FALSE
);
1177 /* Going up a stairs or rising through the ceiling. */
1179 newlevel
.dnum
= u
.uz
.dnum
;
1180 newlevel
.dlevel
= u
.uz
.dlevel
- 1;
1181 goto_level(&newlevel
, at_stairs
, FALSE
, FALSE
);
1192 cliparound(u
.ux
, u
.uy
);
1194 /* ridden steed always shares hero's location */
1196 u
.usteed
->mx
= u
.ux
, u
.usteed
->my
= u
.uy
;
1197 /* when changing levels, don't leave old position set with
1198 stale values from previous level */
1199 if (!on_level(&u
.uz
, &u
.uz0
))
1200 u
.ux0
= u
.ux
, u
.uy0
= u
.uy
;
1203 /* place you on a random location */
1205 u_on_rndspot(upflag
)
1208 int up
= (upflag
& 1), was_in_W_tower
= (upflag
& 2);
1211 * Place the hero at a random location within the relevant region.
1212 * place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
1213 * Unspecified region (.lx == 0) defaults to entire level.
1215 if (was_in_W_tower
&& On_W_tower_level(&u
.uz
))
1216 /* Stay inside the Wizard's tower when feasible.
1217 We use the W Tower's exclusion region for the
1218 destination instead of its enclosing region.
1219 Note: up vs down doesn't matter in this case
1220 because both specify the same exclusion area. */
1221 place_lregion(dndest
.nlx
, dndest
.nly
, dndest
.nhx
, dndest
.nhy
, 0, 0, 0,
1222 0, LR_DOWNTELE
, (d_level
*) 0);
1224 place_lregion(updest
.lx
, updest
.ly
, updest
.hx
, updest
.hy
, updest
.nlx
,
1225 updest
.nly
, updest
.nhx
, updest
.nhy
, LR_UPTELE
,
1228 place_lregion(dndest
.lx
, dndest
.ly
, dndest
.hx
, dndest
.hy
, dndest
.nlx
,
1229 dndest
.nly
, dndest
.nhx
, dndest
.nhy
, LR_DOWNTELE
,
1233 /* place you on the special staircase */
1235 u_on_sstairs(upflag
)
1239 u_on_newpos(sstairs
.sx
, sstairs
.sy
);
1241 u_on_rndspot(upflag
);
1244 /* place you on upstairs (or special equivalent) */
1249 u_on_newpos(xupstair
, yupstair
);
1251 u_on_sstairs(0); /* destination upstairs implies moving down */
1254 /* place you on dnstairs (or special equivalent) */
1259 u_on_newpos(xdnstair
, ydnstair
);
1261 u_on_sstairs(1); /* destination dnstairs implies moving up */
1268 return (boolean
) ((x
== xupstair
&& y
== yupstair
)
1269 || (x
== xdnstair
&& y
== ydnstair
)
1270 || (x
== xdnladder
&& y
== ydnladder
)
1271 || (x
== xupladder
&& y
== yupladder
)
1272 || (x
== sstairs
.sx
&& y
== sstairs
.sy
));
1279 return (boolean
) (lev
->dlevel
== dungeons
[lev
->dnum
].num_dunlevs
);
1286 return (boolean
) (!level
.flags
.hardfloor
1287 && !Is_botlevel(lev
)
1288 && !Invocation_lev(lev
));
1292 * Like Can_dig_down (above), but also allows falling through on the
1293 * stronghold level. Normally, the bottom level of a dungeon resists
1294 * both digging and falling.
1300 return (boolean
) (Can_dig_down(lev
) || Is_stronghold(lev
));
1304 * True if one can rise up a level (e.g. cursed gain level).
1305 * This happens on intermediate dungeon levels or on any top dungeon
1306 * level that has a stairwell style branch to the next higher dungeon.
1307 * Checks for amulets and such must be done elsewhere.
1310 Can_rise_up(x
, y
, lev
)
1314 /* can't rise up from inside the top of the Wizard's tower */
1315 /* KMH -- or in sokoban */
1316 if (In_endgame(lev
) || In_sokoban(lev
)
1317 || (Is_wiz1_level(lev
) && In_W_tower(x
, y
, lev
)))
1319 return (boolean
) (lev
->dlevel
> 1
1320 || (dungeons
[lev
->dnum
].entry_lev
== 1
1321 && ledger_no(lev
) != 1
1322 && sstairs
.sx
&& sstairs
.up
));
1329 /* [what about level 1 of the quest?] */
1330 return (boolean
) (!Is_airlevel(lev
) && !Is_waterlevel(lev
));
1334 * It is expected that the second argument of get_level is a depth value,
1335 * either supplied by the user (teleport control) or randomly generated.
1336 * But more than one level can be at the same depth. If the target level
1337 * is "above" the present depth location, get_level must trace "up" from
1338 * the player's location (through the ancestors dungeons) the dungeon
1339 * within which the target level is located. With only one exception
1340 * which does not pass through this routine (see level_tele), teleporting
1341 * "down" is confined to the current dungeon. At present, level teleport
1342 * in dungeons that build up is confined within them.
1345 get_level(newlevel
, levnum
)
1350 xchar dgn
= u
.uz
.dnum
;
1353 /* can only currently happen in endgame */
1354 levnum
= u
.uz
.dlevel
;
1356 > dungeons
[dgn
].depth_start
+ dungeons
[dgn
].num_dunlevs
- 1) {
1357 /* beyond end of dungeon, jump to last level */
1358 levnum
= dungeons
[dgn
].num_dunlevs
;
1360 /* The desired level is in this dungeon or a "higher" one. */
1363 * Branch up the tree until we reach a dungeon that contains the
1366 if (levnum
< dungeons
[dgn
].depth_start
) {
1369 * Find the parent dungeon of this dungeon.
1371 * This assumes that end2 is always the "child" and it is
1374 for (br
= branches
; br
; br
= br
->next
)
1375 if (br
->end2
.dnum
== dgn
)
1378 panic("get_level: can't find parent dungeon");
1380 dgn
= br
->end1
.dnum
;
1381 } while (levnum
< dungeons
[dgn
].depth_start
);
1384 /* We're within the same dungeon; calculate the level. */
1385 levnum
= levnum
- dungeons
[dgn
].depth_start
+ 1;
1388 newlevel
->dnum
= dgn
;
1389 newlevel
->dlevel
= levnum
;
1392 /* are you in the quest dungeon? */
1397 return (boolean
) (lev
->dnum
== quest_dnum
);
1400 /* are you in the mines dungeon? */
1405 return (boolean
) (lev
->dnum
== mines_dnum
);
1409 * Return the branch for the given dungeon.
1411 * This function assumes:
1412 * + This is not called with "Dungeons of Doom".
1413 * + There is only _one_ branch to a given dungeon.
1414 * + Field end2 is the "child" dungeon.
1423 dnum
= dname_to_dnum(s
);
1425 /* Find the branch that connects to dungeon i's branch. */
1426 for (br
= branches
; br
; br
= br
->next
)
1427 if (br
->end2
.dnum
== dnum
)
1431 panic("dgn_entrance: can't find entrance to %s", s
);
1437 * This returns true if the hero is on the same level as the entrance to
1438 * the named dungeon.
1440 * Called from do.c and mklev.c.
1442 * Assumes that end1 is always the "parent".
1450 br
= dungeon_branch(s
);
1451 return on_level(&u
.uz
, &br
->end1
) ? TRUE
: FALSE
;
1454 /* is `lev' part of Vlad's tower? */
1459 return (boolean
) (lev
->dnum
== tower_dnum
);
1462 /* is `lev' a level containing the Wizard's tower? */
1464 On_W_tower_level(lev
)
1467 return (boolean
) (Is_wiz1_level(lev
)
1468 || Is_wiz2_level(lev
)
1469 || Is_wiz3_level(lev
));
1472 /* is <x,y> of `lev' inside the Wizard's tower? */
1474 In_W_tower(x
, y
, lev
)
1478 if (!On_W_tower_level(lev
))
1481 * Both of the exclusion regions for arriving via level teleport
1482 * (from above or below) define the tower's boundary.
1483 * assert( updest.nIJ == dndest.nIJ for I={l|h},J={x|y} );
1486 return (boolean
) within_bounded_area(x
, y
, dndest
.nlx
, dndest
.nly
,
1487 dndest
.nhx
, dndest
.nhy
);
1489 impossible("No boundary for Wizard's Tower?");
1493 /* are you in one of the Hell levels? */
1498 return (boolean
) (dungeons
[lev
->dnum
].flags
.hellish
);
1501 /* sets *lev to be the gateway to Gehennom... */
1506 lev
->dnum
= valley_level
.dnum
;
1510 /* go directly to hell... */
1512 goto_hell(at_stairs
, falling
)
1513 boolean at_stairs
, falling
;
1518 goto_level(&lev
, at_stairs
, falling
, FALSE
);
1521 /* equivalent to dest = source */
1523 assign_level(dest
, src
)
1524 d_level
*dest
, *src
;
1526 dest
->dnum
= src
->dnum
;
1527 dest
->dlevel
= src
->dlevel
;
1530 /* dest = src + rn1(range) */
1532 assign_rnd_level(dest
, src
, range
)
1533 d_level
*dest
, *src
;
1536 dest
->dnum
= src
->dnum
;
1537 dest
->dlevel
= src
->dlevel
+ ((range
> 0) ? rnd(range
) : -rnd(-range
));
1539 if (dest
->dlevel
> dunlevs_in_dungeon(dest
))
1540 dest
->dlevel
= dunlevs_in_dungeon(dest
);
1541 else if (dest
->dlevel
< 1)
1549 s_level
*lev
= Is_special(&u
.uz
);
1552 if (lev
&& lev
->flags
.align
)
1554 return lev
->flags
.align
;
1556 if (dungeons
[u
.uz
.dnum
].flags
.align
)
1558 return dungeons
[u
.uz
.dnum
].flags
.align
;
1561 return Align2amask(al
);
1568 return (boolean
) (In_hell(lev
)
1569 && lev
->dlevel
== dungeons
[lev
->dnum
].num_dunlevs
- 1);
1572 /* use instead of depth() wherever a degree of difficulty is made
1573 * dependent on the location in the dungeon (eg. monster creation).
1580 if (In_endgame(&u
.uz
)) {
1581 res
= depth(&sanctum_level
) + u
.ulevel
/ 2;
1582 } else if (u
.uhave
.amulet
) {
1583 res
= deepest_lev_reached(FALSE
);
1586 /* depth() is the number of elevation units (levels) below
1587 the theoretical surface; in a builds-up branch, that value
1588 ends up making the harder to reach levels be treated as if
1589 they were easier; adjust for the extra effort involved in
1590 going down to the entrance and then up to the location */
1591 if (builds_up(&u
.uz
))
1592 res
+= 2 * (dungeons
[u
.uz
.dnum
].entry_lev
- u
.uz
.dlevel
+ 1);
1594 * 'Proof' by example: suppose the entrance to sokoban is
1595 * on dungeon level 9, leading up to bottom sokoban level
1596 * of 8 [entry_lev]. When the hero is on sokoban level 8
1597 * [uz.dlevel], depth() yields eight but he has ventured
1598 * one level beyond 9, so difficulty depth should be 10:
1599 * 8 + 2 * (8 - 8 + 1) => 10.
1600 * Going up to 7, depth is 7 but hero will be two beyond 9:
1601 * 7 + 2 * (8 - 7 + 1) => 11.
1602 * When he goes up to level 6, three levels beyond 9:
1603 * 6 + 2 * (8 - 6 + 1) => 12.
1604 * And the top level of sokoban at 5, four levels beyond 9:
1605 * 5 + 2 * (8 - 5 + 1) => 13.
1606 * The same applies to Vlad's Tower, although the increment
1607 * there is inconsequential compared to overall depth.
1611 * The inside of the Wizard's Tower is also effectively a
1612 * builds-up area, reached from a portal an arbitrary distance
1613 * below rather than stairs 1 level beneath the entry level.
1615 else if (On_W_tower_level(&u
.uz
) && In_W_tower(some_X
, some_Y
, &u
.uz
))
1616 res
+= (fakewiz1
.dlev
- u
.uz
.dlev
);
1618 * Handling this properly would need more information here:
1619 * an inside/outside flag, or coordinates to calculate it.
1620 * Unfortunately level difficulty may be wanted before
1621 * coordinates have been chosen so simply extending this
1622 * routine to take extra arguments is not sufficient to cope.
1623 * The difference beyond naive depth-from-surface is small
1624 * relative to the overall depth, so just ignore complications
1632 /* Take one word and try to match it to a level.
1633 * Recognized levels are as shown by print_dungeon().
1646 /* allow strings like "the oracle level" to find "oracle" */
1647 if (!strncmpi(nam
, "the ", 4))
1649 if ((p
= strstri(nam
, " level")) != 0 && p
== eos((char *) nam
) - 6) {
1650 nam
= strcpy(buf
, nam
);
1651 *(eos(buf
) - 6) = '\0';
1653 /* hell is the old name, and wouldn't match; gehennom would match its
1654 branch, yielding the castle level instead of the valley of the dead */
1655 if (!strcmpi(nam
, "gehennom") || !strcmpi(nam
, "hell")) {
1656 if (In_V_tower(&u
.uz
))
1657 nam
= " to Vlad's tower"; /* branch to... */
1662 if ((slev
= find_level(nam
)) != 0) {
1663 dlev
= slev
->dlevel
;
1664 idx
= ledger_no(&dlev
);
1665 if ((dlev
.dnum
== u
.uz
.dnum
1666 /* within same branch, or else main dungeon <-> gehennom */
1667 || (u
.uz
.dnum
== valley_level
.dnum
1668 && dlev
.dnum
== medusa_level
.dnum
)
1669 || (u
.uz
.dnum
== medusa_level
.dnum
1670 && dlev
.dnum
== valley_level
.dnum
))
1671 && (/* either wizard mode or else seen and not forgotten */
1673 || (level_info
[idx
].flags
& (FORGOTTEN
| VISITED
))
1675 lev
= depth(&slev
->dlevel
);
1677 } else { /* not a specific level; try branch names */
1678 idx
= find_branch(nam
, (struct proto_dungeon
*) 0);
1679 /* "<branch> to Xyzzy" */
1680 if (idx
< 0 && (p
= strstri(nam
, " to ")) != 0)
1681 idx
= find_branch(p
+ 4, (struct proto_dungeon
*) 0);
1684 idxtoo
= (idx
>> 8) & 0x00FF;
1686 if (/* either wizard mode, or else _both_ sides of branch seen */
1688 || ((level_info
[idx
].flags
& (FORGOTTEN
| VISITED
)) == VISITED
1689 && (level_info
[idxtoo
].flags
& (FORGOTTEN
| VISITED
))
1691 if (ledger_to_dnum(idxtoo
) == u
.uz
.dnum
)
1693 dlev
.dnum
= ledger_to_dnum(idx
);
1694 dlev
.dlevel
= ledger_to_dlev(idx
);
1703 unplaced_floater(dptr
)
1704 struct dungeon
*dptr
;
1707 int idx
= (int) (dptr
- dungeons
);
1709 /* if other floating branches are added, this will need to change */
1710 if (idx
!= knox_level
.dnum
)
1712 for (br
= branches
; br
; br
= br
->next
)
1713 if (br
->end1
.dnum
== n_dgns
&& br
->end2
.dnum
== idx
)
1719 unreachable_level(lvl_p
, unplaced
)
1727 if (In_endgame(&u
.uz
) && !In_endgame(lvl_p
))
1729 if ((dummy
= find_level("dummy")) != 0 && on_level(lvl_p
, &dummy
->dlevel
))
1735 tport_menu(win
, entry
, lchoices
, lvl_p
, unreachable
)
1738 struct lchoice
*lchoices
;
1740 boolean unreachable
;
1745 lchoices
->lev
[lchoices
->idx
] = lvl_p
->dlevel
;
1746 lchoices
->dgn
[lchoices
->idx
] = lvl_p
->dnum
;
1747 lchoices
->playerlev
[lchoices
->idx
] = depth(lvl_p
);
1750 /* not selectable, but still consumes next menuletter;
1751 prepend padding in place of missing menu selector */
1752 Sprintf(tmpbuf
, " %s", entry
);
1755 any
.a_int
= lchoices
->idx
+ 1;
1757 add_menu(win
, NO_GLYPH
, &any
, lchoices
->menuletter
, 0, ATR_NONE
, entry
,
1759 /* this assumes there are at most 52 interesting levels */
1760 if (lchoices
->menuletter
== 'z')
1761 lchoices
->menuletter
= 'A';
1763 lchoices
->menuletter
++;
1768 /* Convert a branch type to a string usable by print_dungeon(). */
1769 STATIC_OVL
const char *
1777 return "Connection";
1779 return "One way stair";
1783 return " (unknown)";
1786 /* Print all child branches between the lower and upper bounds. */
1788 print_branch(win
, dnum
, lower_bound
, upper_bound
, bymenu
, lchoices_p
)
1794 struct lchoice
*lchoices_p
;
1799 /* This assumes that end1 is the "parent". */
1800 for (br
= branches
; br
; br
= br
->next
) {
1801 if (br
->end1
.dnum
== dnum
&& lower_bound
< br
->end1
.dlevel
1802 && br
->end1
.dlevel
<= upper_bound
) {
1803 Sprintf(buf
, " %s to %s: %d", br_string(br
->type
),
1804 dungeons
[br
->end2
.dnum
].dname
, depth(&br
->end1
));
1806 tport_menu(win
, buf
, lchoices_p
, &br
->end1
,
1807 unreachable_level(&br
->end1
, FALSE
));
1809 putstr(win
, 0, buf
);
1814 /* Print available dungeon information. */
1816 print_dungeon(bymenu
, rlev
, rdgn
)
1821 int i
, last_level
, nlev
;
1824 boolean first
, unplaced
;
1829 struct lchoice lchoices
;
1831 winid win
= create_nhwindow(NHW_MENU
);
1835 lchoices
.menuletter
= 'a';
1838 for (i
= 0, dptr
= dungeons
; i
< n_dgns
; i
++, dptr
++) {
1839 if (bymenu
&& In_endgame(&u
.uz
) && i
!= astral_level
.dnum
)
1841 unplaced
= unplaced_floater(dptr
);
1842 descr
= unplaced
? "depth" : "level";
1843 nlev
= dptr
->num_dunlevs
;
1845 Sprintf(buf
, "%s: %s %d to %d", dptr
->dname
, makeplural(descr
),
1846 dptr
->depth_start
, dptr
->depth_start
+ nlev
- 1);
1848 Sprintf(buf
, "%s: %s %d", dptr
->dname
, descr
, dptr
->depth_start
);
1850 /* Most entrances are uninteresting. */
1851 if (dptr
->entry_lev
!= 1) {
1852 if (dptr
->entry_lev
== nlev
)
1853 Strcat(buf
, ", entrance from below");
1855 Sprintf(eos(buf
), ", entrance on %d",
1856 dptr
->depth_start
+ dptr
->entry_lev
- 1);
1860 add_menu(win
, NO_GLYPH
, &any
, 0, 0, iflags
.menu_headings
, buf
,
1863 putstr(win
, 0, buf
);
1866 * Circle through the special levels to find levels that are in
1869 for (slev
= sp_levchn
, last_level
= 0; slev
; slev
= slev
->next
) {
1870 if (slev
->dlevel
.dnum
!= i
)
1873 /* print any branches before this level */
1874 print_branch(win
, i
, last_level
, slev
->dlevel
.dlevel
, bymenu
,
1877 Sprintf(buf
, " %s: %d", slev
->proto
, depth(&slev
->dlevel
));
1878 if (Is_stronghold(&slev
->dlevel
))
1879 Sprintf(eos(buf
), " (tune %s)", tune
);
1881 tport_menu(win
, buf
, &lchoices
, &slev
->dlevel
,
1882 unreachable_level(&slev
->dlevel
, unplaced
));
1884 putstr(win
, 0, buf
);
1886 last_level
= slev
->dlevel
.dlevel
;
1888 /* print branches after the last special level */
1889 print_branch(win
, i
, last_level
, MAXLEVEL
, bymenu
, &lchoices
);
1894 menu_item
*selected
;
1897 end_menu(win
, "Level teleport to where:");
1898 n
= select_menu(win
, PICK_ONE
, &selected
);
1899 destroy_nhwindow(win
);
1901 idx
= selected
[0].item
.a_int
- 1;
1902 free((genericptr_t
) selected
);
1904 *rlev
= lchoices
.lev
[idx
];
1905 *rdgn
= lchoices
.dgn
[idx
];
1906 return lchoices
.playerlev
[idx
];
1912 /* Print out floating branches (if any). */
1913 for (first
= TRUE
, br
= branches
; br
; br
= br
->next
) {
1914 if (br
->end1
.dnum
== n_dgns
) {
1917 putstr(win
, 0, "Floating branches");
1920 Sprintf(buf
, " %s to %s", br_string(br
->type
),
1921 dungeons
[br
->end2
.dnum
].dname
);
1922 putstr(win
, 0, buf
);
1926 /* I hate searching for the invocation pos while debugging. -dean */
1927 if (Invocation_lev(&u
.uz
)) {
1929 Sprintf(buf
, "Invocation position @ (%d,%d), hero @ (%d,%d)",
1930 inv_pos
.x
, inv_pos
.y
, u
.ux
, u
.uy
);
1931 putstr(win
, 0, buf
);
1934 * The following is based on the assumption that the inter-level portals
1935 * created by the level compiler (not the dungeon compiler) only exist
1936 * one per level (currently true, of course).
1938 else if (Is_earthlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)
1939 || Is_firelevel(&u
.uz
) || Is_airlevel(&u
.uz
)) {
1941 for (trap
= ftrap
; trap
; trap
= trap
->ntrap
)
1942 if (trap
->ttyp
== MAGIC_PORTAL
)
1947 Sprintf(buf
, "Portal @ (%d,%d), hero @ (%d,%d)", trap
->tx
,
1948 trap
->ty
, u
.ux
, u
.uy
);
1950 Sprintf(buf
, "No portal found.");
1951 putstr(win
, 0, buf
);
1954 display_nhwindow(win
, TRUE
);
1955 destroy_nhwindow(win
);
1959 /* Record that the player knows about a branch from a level. This function
1960 * will determine whether or not it was a "real" branch that was taken.
1961 * This function should not be called for a transition done via level
1962 * teleport or via the Eye.
1965 recbranch_mapseen(source
, dest
)
1973 if (source
->dnum
== dest
->dnum
)
1976 /* we only care about forward branches */
1977 for (br
= branches
; br
; br
= br
->next
) {
1978 if (on_level(source
, &br
->end1
) && on_level(dest
, &br
->end2
))
1980 if (on_level(source
, &br
->end2
) && on_level(dest
, &br
->end1
))
1984 /* branch not found, so not a real branch. */
1988 if ((mptr
= find_mapseen(source
)) != 0) {
1989 if (mptr
->br
&& br
!= mptr
->br
)
1990 impossible("Two branches on the same level?");
1993 impossible("Can't note branch for unseen level (%d, %d)",
1994 source
->dnum
, source
->dlevel
);
2004 if ((mptr
= find_mapseen(lev
)))
2005 return mptr
->custom
;
2009 /* #annotate command - add a custom name to the current level */
2014 char nbuf
[BUFSZ
]; /* Buffer for response */
2016 if (!(mptr
= find_mapseen(&u
.uz
)))
2021 Sprintf(tmpbuf
, "Replace annotation \"%.30s%s\" with?", mptr
->custom
,
2022 strlen(mptr
->custom
) > 30 ? "..." : "");
2023 getlin(tmpbuf
, nbuf
);
2025 getlin("What do you want to call this dungeon level?", nbuf
);
2026 if (index(nbuf
, '\033'))
2028 (void) mungspaces(nbuf
);
2030 /* discard old annotation, if any */
2032 free((genericptr_t
) mptr
->custom
);
2033 mptr
->custom
= (char *) 0;
2034 mptr
->custom_lth
= 0;
2036 /* add new annotation, unless it's empty or a single space */
2037 if (*nbuf
&& strcmp(nbuf
, " ")) {
2038 mptr
->custom
= dupstr(nbuf
);
2039 mptr
->custom_lth
= strlen(mptr
->custom
);
2044 /* find the particular mapseen object in the chain; may return null */
2045 STATIC_OVL mapseen
*
2051 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
)
2052 if (on_level(&(mptr
->lev
), lev
))
2059 forget_mapseen(ledger_num
)
2063 struct cemetery
*bp
;
2065 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
)
2066 if (dungeons
[mptr
->lev
.dnum
].ledger_start
+ mptr
->lev
.dlevel
2070 /* if not found, then nothing to forget */
2072 mptr
->flags
.forgot
= 1;
2073 mptr
->br
= (branch
*) 0;
2075 /* custom names are erased, not just forgotten until revisited */
2077 mptr
->custom_lth
= 0;
2078 free((genericptr_t
) mptr
->custom
);
2079 mptr
->custom
= (char *) 0;
2081 (void) memset((genericptr_t
) mptr
->msrooms
, 0, sizeof mptr
->msrooms
);
2082 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
)
2083 bp
->bonesknown
= FALSE
;
2088 save_mapseen(fd
, mptr
)
2095 for (brindx
= 0, curr
= branches
; curr
; curr
= curr
->next
, ++brindx
)
2096 if (curr
== mptr
->br
)
2098 bwrite(fd
, (genericptr_t
) &brindx
, sizeof brindx
);
2100 bwrite(fd
, (genericptr_t
) &mptr
->lev
, sizeof mptr
->lev
);
2101 bwrite(fd
, (genericptr_t
) &mptr
->feat
, sizeof mptr
->feat
);
2102 bwrite(fd
, (genericptr_t
) &mptr
->flags
, sizeof mptr
->flags
);
2103 bwrite(fd
, (genericptr_t
) &mptr
->custom_lth
, sizeof mptr
->custom_lth
);
2104 if (mptr
->custom_lth
)
2105 bwrite(fd
, (genericptr_t
) mptr
->custom
, mptr
->custom_lth
);
2106 bwrite(fd
, (genericptr_t
) &mptr
->msrooms
, sizeof mptr
->msrooms
);
2107 savecemetery(fd
, WRITE_SAVE
, &mptr
->final_resting_place
);
2110 STATIC_OVL mapseen
*
2114 int branchnum
, brindx
;
2118 load
= (mapseen
*) alloc(sizeof *load
);
2120 mread(fd
, (genericptr_t
) &branchnum
, sizeof branchnum
);
2121 for (brindx
= 0, curr
= branches
; curr
; curr
= curr
->next
, ++brindx
)
2122 if (brindx
== branchnum
)
2126 mread(fd
, (genericptr_t
) &load
->lev
, sizeof load
->lev
);
2127 mread(fd
, (genericptr_t
) &load
->feat
, sizeof load
->feat
);
2128 mread(fd
, (genericptr_t
) &load
->flags
, sizeof load
->flags
);
2129 mread(fd
, (genericptr_t
) &load
->custom_lth
, sizeof load
->custom_lth
);
2130 if (load
->custom_lth
) {
2131 /* length doesn't include terminator (which isn't saved & restored) */
2132 load
->custom
= (char *) alloc(load
->custom_lth
+ 1);
2133 mread(fd
, (genericptr_t
) load
->custom
, load
->custom_lth
);
2134 load
->custom
[load
->custom_lth
] = '\0';
2137 mread(fd
, (genericptr_t
) &load
->msrooms
, sizeof load
->msrooms
);
2138 restcemetery(fd
, &load
->final_resting_place
);
2143 /* to support '#stats' wizard-mode command */
2145 overview_stats(win
, statsfmt
, total_count
, total_size
)
2147 const char *statsfmt
;
2148 long *total_count
, *total_size
;
2150 char buf
[BUFSZ
], hdrbuf
[QBUFSZ
];
2151 long ocount
, osize
, bcount
, bsize
, acount
, asize
;
2152 struct cemetery
*ce
;
2153 mapseen
*mptr
= find_mapseen(&u
.uz
);
2155 ocount
= bcount
= acount
= osize
= bsize
= asize
= 0L;
2156 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
) {
2158 osize
+= (long) sizeof *mptr
;
2159 for (ce
= mptr
->final_resting_place
; ce
; ce
= ce
->next
) {
2161 bsize
+= (long) sizeof *ce
;
2163 if (mptr
->custom_lth
) {
2165 asize
+= (long) (mptr
->custom_lth
+ 1);
2169 Sprintf(hdrbuf
, "general, size %ld", (long) sizeof (mapseen
));
2170 Sprintf(buf
, statsfmt
, hdrbuf
, ocount
, osize
);
2171 putstr(win
, 0, buf
);
2173 Sprintf(hdrbuf
, "cemetery, size %ld",
2174 (long) sizeof (struct cemetery
));
2175 Sprintf(buf
, statsfmt
, hdrbuf
, bcount
, bsize
);
2176 putstr(win
, 0, buf
);
2179 Sprintf(hdrbuf
, "annotations, text");
2180 Sprintf(buf
, statsfmt
, hdrbuf
, acount
, asize
);
2181 putstr(win
, 0, buf
);
2183 *total_count
+= ocount
+ bcount
+ acount
;
2184 *total_size
+= osize
+ bsize
+ asize
;
2187 /* Remove all mapseen objects for a particular dnum.
2188 * Useful during quest expulsion to remove quest levels.
2189 * [No longer deleted, just marked as unreachable. #overview will
2190 * ignore such levels, end of game disclosure will include them.]
2193 remdun_mapseen(dnum
)
2196 mapseen
*mptr
, **mptraddr
;
2198 mptraddr
= &mapseenchn
;
2199 while ((mptr
= *mptraddr
) != 0) {
2200 if (mptr
->lev
.dnum
== dnum
) {
2201 #if 1 /* use this... */
2202 mptr
->flags
.unreachable
= 1;
2204 #else /* old deletion code */
2205 *mptraddr
= mptr
->next
;
2207 free((genericptr_t
) mptr
->custom
);
2208 if (mptr
->final_resting_place
)
2209 savecemetery(-1, FREE_SAVE
, &mptr
->final_resting_place
);
2210 free((genericptr_t
) mptr
);
2213 mptraddr
= &mptr
->next
;
2221 /* Create a level and insert in "sorted" order. This is an insertion
2222 * sort first by dungeon (in order of discovery) and then by level number.
2224 mapseen
*mptr
, *init
, *prev
;
2226 init
= (mapseen
*) alloc(sizeof *init
);
2227 (void) memset((genericptr_t
) init
, 0, sizeof *init
);
2228 /* memset is fine for feature bits, flags, and rooms array;
2229 explicitly initialize pointers to null */
2230 init
->next
= 0, init
->br
= 0, init
->custom
= 0;
2231 init
->final_resting_place
= 0;
2232 /* lastseentyp[][] is reused for each level, so get rid of
2233 previous level's data */
2234 (void) memset((genericptr_t
) lastseentyp
, 0, sizeof lastseentyp
);
2236 init
->lev
.dnum
= lev
->dnum
;
2237 init
->lev
.dlevel
= lev
->dlevel
;
2239 /* walk until we get to the place where we should insert init */
2240 for (mptr
= mapseenchn
, prev
= 0; mptr
; prev
= mptr
, mptr
= mptr
->next
)
2241 if (mptr
->lev
.dnum
> init
->lev
.dnum
2242 || (mptr
->lev
.dnum
== init
->lev
.dnum
2243 && mptr
->lev
.dlevel
> init
->lev
.dlevel
))
2246 init
->next
= mapseenchn
;
2255 #define INTEREST(feat) \
2256 ((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
2257 || (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple)
2258 /* || (feat).water || (feat).ice || (feat).lava */
2260 /* returns true if this level has something interesting to print out */
2262 interest_mapseen(mptr
)
2265 if (on_level(&u
.uz
, &mptr
->lev
))
2267 if (mptr
->flags
.unreachable
|| mptr
->flags
.forgot
)
2269 /* level is of interest if it has an auto-generated annotation */
2270 if (mptr
->flags
.oracle
|| mptr
->flags
.bigroom
|| mptr
->flags
.roguelevel
2271 || mptr
->flags
.castle
|| mptr
->flags
.valley
|| mptr
->flags
.msanctum
2272 || mptr
->flags
.quest_summons
|| mptr
->flags
.questing
)
2274 /* when in Sokoban, list all sokoban levels visited; when not in it,
2275 list any visited Sokoban level which remains unsolved (will usually
2276 only be furthest one reached, but it's possible to enter pits and
2277 climb out on the far side on the first Sokoban level; also, wizard
2278 mode overrides teleport restrictions) */
2279 if (In_sokoban(&mptr
->lev
)
2280 && (In_sokoban(&u
.uz
) || !mptr
->flags
.sokosolved
))
2282 /* when in the endgame, list all endgame levels visited, whether they
2283 have annotations or not, so that #overview doesn't become extremely
2284 sparse once the rest of the dungeon has been flagged as unreachable */
2285 if (In_endgame(&u
.uz
))
2286 return (boolean
) In_endgame(&mptr
->lev
);
2287 /* level is of interest if it has non-zero feature count or known bones
2288 or user annotation or known connection to another dungeon branch
2289 or is the furthest level reached in its branch */
2290 return (boolean
) (INTEREST(mptr
->feat
)
2291 || (mptr
->final_resting_place
2292 && (mptr
->flags
.knownbones
|| wizard
))
2293 || mptr
->custom
|| mptr
->br
2294 || (mptr
->lev
.dlevel
2295 == dungeons
[mptr
->lev
.dnum
].dunlev_ureached
));
2298 /* recalculate mapseen for the current level */
2304 struct cemetery
*bp
, **bonesaddr
;
2306 int x
, y
, ltyp
, count
, atmp
;
2308 /* Should not happen in general, but possible if in the process
2309 * of being booted from the quest. The mapseen object gets
2310 * removed during the expulsion but prior to leaving the level
2311 * [Since quest expulsion no longer deletes quest mapseen data,
2312 * null return from find_mapseen() should now be impossible.]
2314 if (!(mptr
= find_mapseen(&u
.uz
)))
2317 /* reset all features; mptr->feat.* = 0; */
2318 (void) memset((genericptr_t
) &mptr
->feat
, 0, sizeof mptr
->feat
);
2319 /* reset most flags; some level-specific ones are left as-is */
2320 if (mptr
->flags
.unreachable
) {
2321 mptr
->flags
.unreachable
= 0; /* reached it; Eye of the Aethiopica? */
2322 if (In_quest(&u
.uz
)) {
2323 mapseen
*mptrtmp
= mapseenchn
;
2325 /* when quest was unreachable due to ejection and portal removal,
2326 getting back to it via arti-invoke should revive annotation
2327 data for all quest levels, not just the one we're on now */
2329 if (mptrtmp
->lev
.dnum
== mptr
->lev
.dnum
)
2330 mptrtmp
->flags
.unreachable
= 0;
2331 mptrtmp
= mptrtmp
->next
;
2335 mptr
->flags
.knownbones
= 0;
2336 mptr
->flags
.sokosolved
= In_sokoban(&u
.uz
) && !Sokoban
;
2337 /* mptr->flags.bigroom retains previous value when hero can't see */
2339 mptr
->flags
.bigroom
= Is_bigroom(&u
.uz
);
2340 else if (mptr
->flags
.forgot
)
2341 mptr
->flags
.bigroom
= 0;
2342 mptr
->flags
.roguelevel
= Is_rogue_level(&u
.uz
);
2343 mptr
->flags
.oracle
= 0; /* recalculated during room traversal below */
2344 mptr
->flags
.castletune
= 0;
2345 /* flags.castle, flags.valley, flags.msanctum retain previous value */
2346 mptr
->flags
.forgot
= 0;
2347 /* flags.quest_summons disabled once quest finished */
2348 mptr
->flags
.quest_summons
= (at_dgn_entrance("The Quest")
2350 && !(u
.uevent
.qcompleted
2351 || u
.uevent
.qexpelled
2352 || quest_status
.leader_is_dead
));
2353 mptr
->flags
.questing
= (on_level(&u
.uz
, &qstart_level
)
2354 && quest_status
.got_quest
);
2356 /* track rooms the hero is in */
2357 for (i
= 0; i
< SIZE(u
.urooms
); ++i
) {
2361 ridx
= u
.urooms
[i
] - ROOMOFFSET
;
2362 mptr
->msrooms
[ridx
].seen
= 1;
2363 mptr
->msrooms
[ridx
].untended
=
2364 (rooms
[ridx
].rtype
>= SHOPBASE
)
2365 ? (!(mtmp
= shop_keeper(u
.urooms
[i
])) || !inhishop(mtmp
))
2366 : (rooms
[ridx
].rtype
== TEMPLE
)
2367 ? (!(mtmp
= findpriest(u
.urooms
[i
]))
2368 || !inhistemple(mtmp
))
2372 /* recalculate room knowledge: for now, just shops and temples
2373 * this could be extended to an array of 0..SHOPBASE
2375 for (i
= 0; i
< SIZE(mptr
->msrooms
); ++i
) {
2376 if (mptr
->msrooms
[i
].seen
) {
2377 if (rooms
[i
].rtype
>= SHOPBASE
) {
2378 if (mptr
->msrooms
[i
].untended
)
2379 mptr
->feat
.shoptype
= SHOPBASE
- 1;
2380 else if (!mptr
->feat
.nshop
)
2381 mptr
->feat
.shoptype
= rooms
[i
].rtype
;
2382 else if (mptr
->feat
.shoptype
!= (unsigned) rooms
[i
].rtype
)
2383 mptr
->feat
.shoptype
= 0;
2384 count
= mptr
->feat
.nshop
+ 1;
2386 mptr
->feat
.nshop
= count
;
2387 } else if (rooms
[i
].rtype
== TEMPLE
) {
2388 /* altar and temple alignment handled below */
2389 count
= mptr
->feat
.ntemple
+ 1;
2391 mptr
->feat
.ntemple
= count
;
2392 } else if (rooms
[i
].orig_rtype
== DELPHI
) {
2393 mptr
->flags
.oracle
= 1;
2398 /* Update lastseentyp with typ if and only if it is in sight or the
2399 * hero can feel it on their current location (i.e. not levitating).
2400 * This *should* give the "last known typ" for each dungeon location.
2401 * (At the very least, it's a better assumption than determining what
2402 * the player knows from the glyph and the typ (which is isn't quite
2403 * enough information in some cases)).
2405 * It was reluctantly added to struct rm to track. Alternatively
2406 * we could track "features" and then update them all here, and keep
2407 * track of when new features are created or destroyed, but this
2408 * seemed the most elegant, despite adding more data to struct rm.
2409 * [3.6.0: we're using lastseentyp[][] rather than level.locations
2410 * to track the features seen.]
2412 * Although no current windowing systems (can) do this, this would add
2413 * the ability to have non-dungeon glyphs float above the last known
2414 * dungeon glyph (i.e. items on fountains).
2416 for (x
= 1; x
< COLNO
; x
++) {
2417 for (y
= 0; y
< ROWNO
; y
++) {
2418 if (cansee(x
, y
) || (x
== u
.ux
&& y
== u
.uy
&& !Levitation
)) {
2419 ltyp
= levl
[x
][y
].typ
;
2420 if (ltyp
== DRAWBRIDGE_UP
)
2421 ltyp
= db_under_typ(levl
[x
][y
].drawbridgemask
);
2422 if ((mtmp
= m_at(x
, y
)) != 0
2423 && mtmp
->m_ap_type
== M_AP_FURNITURE
&& canseemon(mtmp
))
2424 ltyp
= cmap_to_type(mtmp
->mappearance
);
2425 lastseentyp
[x
][y
] = ltyp
;
2428 switch (lastseentyp
[x
][y
]) {
2431 count
= mptr
->feat
.ice
+ 1;
2433 mptr
->feat
.ice
= count
;
2438 count
= mptr
->feat
.water
+ 1;
2440 mptr
->feat
.water
= count
;
2443 count
= mptr
->feat
.lava
+ 1;
2445 mptr
->feat
.lava
= count
;
2449 count
= mptr
->feat
.ntree
+ 1;
2451 mptr
->feat
.ntree
= count
;
2454 count
= mptr
->feat
.nfount
+ 1;
2456 mptr
->feat
.nfount
= count
;
2459 count
= mptr
->feat
.nthrone
+ 1;
2461 mptr
->feat
.nthrone
= count
;
2464 count
= mptr
->feat
.nsink
+ 1;
2466 mptr
->feat
.nsink
= count
;
2469 count
= mptr
->feat
.ngrave
+ 1;
2471 mptr
->feat
.ngrave
= count
;
2474 atmp
= (Is_astralevel(&u
.uz
)
2475 && (levl
[x
][y
].seenv
& SVALL
) != SVALL
)
2477 : Amask2msa(levl
[x
][y
].altarmask
);
2478 if (!mptr
->feat
.naltar
)
2479 mptr
->feat
.msalign
= atmp
;
2480 else if (mptr
->feat
.msalign
!= atmp
)
2481 mptr
->feat
.msalign
= MSA_NONE
;
2482 count
= mptr
->feat
.naltar
+ 1;
2484 mptr
->feat
.naltar
= count
;
2486 /* An automatic annotation is added to the Castle and
2487 * to Fort Ludios once their structure's main entrance
2488 * has been seen (in person or via magic mapping).
2489 * For the Fort, that entrance is just a secret door
2490 * which will be converted into a regular one when
2491 * located (or destroyed).
2492 * DOOR: possibly a lowered drawbridge's open portcullis;
2493 * DBWALL: a raised drawbridge's "closed door";
2494 * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
2495 * with moat or other terrain hidden underneath;
2496 * DRAWBRIDGE_UP: moat in front of a raised drawbridge,
2497 * not recognizable as a bridge location unless/until
2498 * the adjacent DBWALL has been seen.
2501 if (Is_knox(&u
.uz
)) {
2504 /* Throne is four columns left, either directly in
2505 * line or one row higher or lower, and doesn't have
2506 * to have been seen yet.
2511 * For 3.6.0 and earlier, it was always in direct line:
2512 * both throne and door on the lower of the two rows.
2514 for (ty
= y
- 1; ty
<= y
+ 1; ++ty
)
2515 if (isok(tx
, ty
) && IS_THRONE(levl
[tx
][ty
].typ
)) {
2516 mptr
->flags
.ludios
= 1;
2521 if (is_drawbridge_wall(x
, y
) < 0)
2525 case DRAWBRIDGE_DOWN
:
2526 if (Is_stronghold(&u
.uz
))
2527 mptr
->flags
.castle
= 1, mptr
->flags
.castletune
= 1;
2535 if (level
.bonesinfo
&& !mptr
->final_resting_place
) {
2536 /* clone the bonesinfo so we aren't dependent upon this
2537 level being in memory */
2538 bonesaddr
= &mptr
->final_resting_place
;
2539 bp
= level
.bonesinfo
;
2541 *bonesaddr
= (struct cemetery
*) alloc(sizeof **bonesaddr
);
2544 bonesaddr
= &(*bonesaddr
)->next
;
2548 /* decide which past hero deaths have become known; there's no
2549 guarantee of either a grave or a ghost, so we go by whether the
2550 current hero has seen the map location where each old one died */
2551 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
)
2552 if (lastseentyp
[bp
->frpx
][bp
->frpy
]) {
2553 bp
->bonesknown
= TRUE
;
2554 mptr
->flags
.knownbones
= 1;
2559 /* valley and sanctum levels get automatic annotation once temple is entered
2562 mapseen_temple(priest
)
2563 struct monst
*priest UNUSED
; /* currently unused; might be useful someday */
2565 mapseen
*mptr
= find_mapseen(&u
.uz
);
2567 if (Is_valley(&u
.uz
))
2568 mptr
->flags
.valley
= 1;
2569 else if (Is_sanctum(&u
.uz
))
2570 mptr
->flags
.msanctum
= 1;
2573 /* room entry message has just been delivered so learn room even if blind */
2575 room_discovered(roomno
)
2578 mapseen
*mptr
= find_mapseen(&u
.uz
);
2580 mptr
->msrooms
[roomno
].seen
= 1;
2583 /* #overview command */
2587 show_overview(0, 0);
2591 /* called for #overview or for end of game disclosure */
2593 show_overview(why
, reason
)
2594 int why
; /* 0 => #overview command,
2595 1 or 2 => final disclosure (1: hero lived, 2: hero died) */
2596 int reason
; /* how hero died; used when disclosing end-of-game level */
2601 /* lazy initialization */
2602 (void) recalc_mapseen();
2604 win
= create_nhwindow(NHW_MENU
);
2605 /* show the endgame levels before the rest of the dungeon,
2606 so that the Planes (dnum 5-ish) come out above main dungeon (dnum 0) */
2607 if (In_endgame(&u
.uz
))
2608 traverse_mapseenchn(TRUE
, win
, why
, reason
, &lastdun
);
2609 /* if game is over or we're not in the endgame yet, show the dungeon */
2610 if (why
> 0 || !In_endgame(&u
.uz
))
2611 traverse_mapseenchn(FALSE
, win
, why
, reason
, &lastdun
);
2612 display_nhwindow(win
, TRUE
);
2613 destroy_nhwindow(win
);
2616 /* display endgame levels or non-endgame levels, not both */
2618 traverse_mapseenchn(viewendgame
, win
, why
, reason
, lastdun_p
)
2619 boolean viewendgame
;
2621 int why
, reason
, *lastdun_p
;
2626 for (mptr
= mapseenchn
; mptr
; mptr
= mptr
->next
) {
2627 if (viewendgame
^ In_endgame(&mptr
->lev
))
2630 /* only print out info for a level or a dungeon if interest */
2631 if (why
> 0 || interest_mapseen(mptr
)) {
2632 showheader
= (boolean
) (mptr
->lev
.dnum
!= *lastdun_p
);
2633 print_mapseen(win
, mptr
, why
, reason
, showheader
);
2634 *lastdun_p
= mptr
->lev
.dnum
;
2639 STATIC_OVL
const char *
2644 /* players are computer scientists: 0, 1, 2, n */
2648 /* an() returns too much. index is ok in this case */
2650 return index(vowels
, *obj
) ? "an" : "a";
2660 /* better br_string */
2661 STATIC_OVL
const char *
2665 /* Special case: quest portal says closed if kicked from quest */
2666 boolean closed_portal
= (br
->end2
.dnum
== quest_dnum
2667 && u
.uevent
.qexpelled
);
2671 return closed_portal
? "Sealed portal" : "Portal";
2673 return "Connection";
2675 return br
->end1_up
? "One way stairs up" : "One way stairs down";
2677 return br
->end1_up
? "Stairs up" : "Stairs down";
2683 /* get the name of an endgame level; topten.c does something similar */
2684 STATIC_OVL
const char *
2685 endgamelevelname(outbuf
, indx
)
2689 const char *planename
= 0;
2694 Strcpy(outbuf
, "Astral Plane");
2697 planename
= "Water";
2706 planename
= "Earth";
2710 Sprintf(outbuf
, "Plane of %s", planename
);
2712 Sprintf(outbuf
, "unknown plane #%d", indx
);
2716 STATIC_OVL
const char *
2720 const char *str
= "shop"; /* catchall */
2722 /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
2725 str
= "untended shop";
2726 break; /* see recalc_mapseen */
2728 str
= "general store";
2734 str
= "scroll shop";
2737 str
= "potion shop";
2740 str
= "weapon shop";
2743 str
= "delicatessen";
2755 str
= "health food store";
2758 str
= "lighting shop";
2766 /* if player knows about the mastermind tune, append it to Castle annotation;
2767 if drawbridge has been destroyed, flags.castletune will be zero */
2769 tunesuffix(mptr
, outbuf
)
2774 if (mptr
->flags
.castletune
&& u
.uevent
.uheard_tune
) {
2777 if (u
.uevent
.uheard_tune
== 2)
2778 Sprintf(tmp
, "notes \"%s\"", tune
);
2780 Strcpy(tmp
, "5-note tune");
2781 Sprintf(outbuf
, " (play %s to open or close drawbridge)", tmp
);
2786 /* some utility macros for print_mapseen */
2787 #define TAB " " /* three spaces */
2789 #define BULLET "" /* empty; otherwise output becomes cluttered */
2790 #define PREFIX TAB TAB BULLET
2792 /* K&R: don't require support for concatenation of adjacent string literals */
2793 #define PREFIX " " /* two TABs + empty BULLET: six spaces */
2795 #define COMMA (i++ > 0 ? ", " : PREFIX)
2796 /* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
2797 #define ADDNTOBUF(nam, var) \
2800 Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
2801 (nam), plur(var)); \
2803 #define ADDTOBUF(nam, var) \
2806 Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
2810 print_mapseen(win
, mptr
, final
, how
, printdun
)
2813 int final
; /* 0: not final; 1: game over, alive; 2: game over, dead */
2814 int how
; /* cause of death; only used if final==2 and mptr->lev==u.uz */
2817 char buf
[BUFSZ
], tmpbuf
[BUFSZ
];
2818 int i
, depthstart
, dnum
;
2819 boolean died_here
= (final
== 2 && on_level(&u
.uz
, &mptr
->lev
));
2821 /* Damnable special cases */
2822 /* The quest and knox should appear to be level 1 to match
2825 dnum
= mptr
->lev
.dnum
;
2826 if (dnum
== quest_dnum
|| dnum
== knox_level
.dnum
)
2829 depthstart
= dungeons
[dnum
].depth_start
;
2832 if (dungeons
[dnum
].dunlev_ureached
== dungeons
[dnum
].entry_lev
2833 /* suppress the negative numbers in the endgame */
2834 || In_endgame(&mptr
->lev
))
2835 Sprintf(buf
, "%s:", dungeons
[dnum
].dname
);
2836 else if (builds_up(&mptr
->lev
))
2837 Sprintf(buf
, "%s: levels %d up to %d",
2838 dungeons
[dnum
].dname
,
2839 depthstart
+ dungeons
[dnum
].entry_lev
- 1,
2840 depthstart
+ dungeons
[dnum
].dunlev_ureached
- 1);
2842 Sprintf(buf
, "%s: levels %d to %d",
2843 dungeons
[dnum
].dname
, depthstart
,
2844 depthstart
+ dungeons
[dnum
].dunlev_ureached
- 1);
2845 putstr(win
, !final
? ATR_INVERSE
: 0, buf
);
2848 /* calculate level number */
2849 i
= depthstart
+ mptr
->lev
.dlevel
- 1;
2850 if (In_endgame(&mptr
->lev
))
2851 Sprintf(buf
, "%s%s:", TAB
, endgamelevelname(tmpbuf
, i
));
2853 Sprintf(buf
, "%sLevel %d:", TAB
, i
);
2855 /* wizmode prints out proto dungeon names for clarity */
2859 if ((slev
= Is_special(&mptr
->lev
)) != 0)
2860 Sprintf(eos(buf
), " [%s]", slev
->proto
);
2862 /* [perhaps print custom annotation on its own line when it's long] */
2864 Sprintf(eos(buf
), " \"%s\"", mptr
->custom
);
2865 if (on_level(&u
.uz
, &mptr
->lev
))
2866 Sprintf(eos(buf
), " <- You %s here.",
2867 (!final
|| (final
== 1 && how
== ASCENDED
)) ? "are"
2868 : (final
== 1 && how
== ESCAPED
) ? "left from"
2870 putstr(win
, !final
? ATR_BOLD
: 0, buf
);
2872 if (mptr
->flags
.forgot
)
2875 if (INTEREST(mptr
->feat
)) {
2878 i
= 0; /* interest counter */
2879 /* List interests in an order vaguely corresponding to
2880 * how important they are.
2882 if (mptr
->feat
.nshop
> 0) {
2883 if (mptr
->feat
.nshop
> 1)
2884 ADDNTOBUF("shop", mptr
->feat
.nshop
);
2886 Sprintf(eos(buf
), "%s%s", COMMA
,
2887 an(shop_string(mptr
->feat
.shoptype
)));
2889 if (mptr
->feat
.naltar
> 0) {
2890 /* Temples + non-temple altars get munged into just "altars" */
2891 if (mptr
->feat
.ntemple
!= mptr
->feat
.naltar
)
2892 ADDNTOBUF("altar", mptr
->feat
.naltar
);
2894 ADDNTOBUF("temple", mptr
->feat
.ntemple
);
2896 /* only print out altar's god if they are all to your god */
2897 if (Amask2align(Msa2amask(mptr
->feat
.msalign
)) == u
.ualign
.type
)
2898 Sprintf(eos(buf
), " to %s", align_gname(u
.ualign
.type
));
2900 ADDNTOBUF("throne", mptr
->feat
.nthrone
);
2901 ADDNTOBUF("fountain", mptr
->feat
.nfount
);
2902 ADDNTOBUF("sink", mptr
->feat
.nsink
);
2903 ADDNTOBUF("grave", mptr
->feat
.ngrave
);
2904 ADDNTOBUF("tree", mptr
->feat
.ntree
);
2906 ADDTOBUF("water", mptr
->feat
.water
);
2907 ADDTOBUF("lava", mptr
->feat
.lava
);
2908 ADDTOBUF("ice", mptr
->feat
.ice
);
2910 /* capitalize afterwards */
2912 buf
[i
] = highc(buf
[i
]);
2913 /* capitalizing it makes it a sentence; terminate with '.' */
2915 putstr(win
, 0, buf
);
2918 /* we assume that these are mutually exclusive */
2920 if (mptr
->flags
.oracle
) {
2921 Sprintf(buf
, "%sOracle of Delphi.", PREFIX
);
2922 } else if (In_sokoban(&mptr
->lev
)) {
2923 Sprintf(buf
, "%s%s.", PREFIX
,
2924 mptr
->flags
.sokosolved
? "Solved" : "Unsolved");
2925 } else if (mptr
->flags
.bigroom
) {
2926 Sprintf(buf
, "%sA very big room.", PREFIX
);
2927 } else if (mptr
->flags
.roguelevel
) {
2928 Sprintf(buf
, "%sA primitive area.", PREFIX
);
2929 } else if (mptr
->flags
.quest_summons
) {
2930 Sprintf(buf
, "%sSummoned by %s.", PREFIX
, ldrname());
2931 } else if (on_level(&mptr
->lev
, &qstart_level
)) {
2932 Sprintf(buf
, "%sHome%s.", PREFIX
,
2933 mptr
->flags
.unreachable
? " (no way back...)" : "");
2934 if (u
.uevent
.qcompleted
)
2935 Sprintf(buf
, "%sCompleted quest for %s.", PREFIX
, ldrname());
2936 else if (mptr
->flags
.questing
)
2937 Sprintf(buf
, "%sGiven quest by %s.", PREFIX
, ldrname());
2938 } else if (mptr
->flags
.ludios
) {
2939 /* presence of the ludios branch in #overview output indicates that
2940 the player has made it onto the level; presence of this annotation
2941 indicates that the fort's entrance has been seen (or mapped) */
2942 Sprintf(buf
, "%sFort Ludios.", PREFIX
);
2943 } else if (mptr
->flags
.castle
) {
2944 Sprintf(buf
, "%sThe castle%s.", PREFIX
, tunesuffix(mptr
, tmpbuf
));
2945 } else if (mptr
->flags
.valley
) {
2946 Sprintf(buf
, "%sValley of the Dead.", PREFIX
);
2947 } else if (mptr
->flags
.msanctum
) {
2948 Sprintf(buf
, "%sMoloch's Sanctum.", PREFIX
);
2951 putstr(win
, 0, buf
);
2953 /* print out branches */
2955 Sprintf(buf
, "%s%s to %s", PREFIX
, br_string2(mptr
->br
),
2956 dungeons
[mptr
->br
->end2
.dnum
].dname
);
2958 /* Since mapseen objects are printed out in increasing order
2959 * of dlevel, clarify which level this branch is going to
2960 * if the branch goes upwards. Unless it's the end game.
2962 if (mptr
->br
->end1_up
&& !In_endgame(&(mptr
->br
->end2
)))
2963 Sprintf(eos(buf
), ", level %d", depth(&(mptr
->br
->end2
)));
2965 putstr(win
, 0, buf
);
2968 /* maybe print out bones details */
2969 if (mptr
->final_resting_place
|| final
) {
2970 struct cemetery
*bp
;
2971 int kncnt
= !died_here
? 0 : 1;
2973 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
)
2974 if (bp
->bonesknown
|| wizard
|| final
)
2977 Sprintf(buf
, "%s%s", PREFIX
, "Final resting place for");
2978 putstr(win
, 0, buf
);
2980 /* disclosure occurs before bones creation, so listing dead
2981 hero here doesn't give away whether bones are produced */
2982 formatkiller(tmpbuf
, sizeof tmpbuf
, how
, TRUE
);
2983 /* rephrase a few death reasons to work with "you" */
2984 (void) strsubst(tmpbuf
, " himself", " yourself");
2985 (void) strsubst(tmpbuf
, " herself", " yourself");
2986 (void) strsubst(tmpbuf
, " his ", " your ");
2987 (void) strsubst(tmpbuf
, " her ", " your ");
2988 Sprintf(buf
, "%s%syou, %s%c", PREFIX
, TAB
, tmpbuf
,
2989 --kncnt
? ',' : '.');
2990 putstr(win
, 0, buf
);
2992 for (bp
= mptr
->final_resting_place
; bp
; bp
= bp
->next
) {
2993 if (bp
->bonesknown
|| wizard
|| final
) {
2994 Sprintf(buf
, "%s%s%s, %s%c", PREFIX
, TAB
, bp
->who
,
2995 bp
->how
, --kncnt
? ',' : '.');
2996 putstr(win
, 0, buf
);