fix #H166 - trapdoors on quest levels
From a bug report, it was possible
to fall from above the quest locate level to below it even though it has
nondiggable floors (hence no trapdoors or holes to pass through). Since
the game can't verify that it is nondiggable (which could vary on a role
by role basis depending upon their quest descriptions) when it is not the
current level, restrict falling past it only when it hasn't been visited
yet. Impose the same restriction for random level teleport. This enforces
proper sequencing of the quest feedback, which was the more significant
thing that went wrong in the reported case (player finally got the full
locate level message on a return visit, when descending from above, after
having already cleared out that level on his way back up from falling).
Once the locate level has been reached or passed, it is no longer a
barrier to falling or random teleport. (When it is eventually visited,
there's no attempt to remember whether it allows holes, since that
information and the corresponding fall check would need to be extended to
every level in the dungeon. Also, controlled teleport is still allowed to
bypass it even when it hasn't yet been visited, so the "enforces proper
sequencing" claim above is an exaggeration.)
This commit is contained in:
@@ -242,6 +242,8 @@ terminal window set to 21 lines can cause a crash during player selection
|
||||
menus; have bot() check for valid youmonst.data
|
||||
free storage used to hold region messages in free_region()
|
||||
honor pushweapon when applying a tool or weapon causes it to become wielded
|
||||
in the quest, if the locate level hasn't been reached yet, don't fall or
|
||||
randomly teleport past it
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
|
||||
@@ -991,9 +991,9 @@ boolean noquest;
|
||||
register schar ret = 0;
|
||||
|
||||
for(i = 0; i < n_dgns; i++) {
|
||||
if((tmp.dlevel = dungeons[i].dunlev_ureached) == 0) continue;
|
||||
if(!strcmp(dungeons[i].dname, "The Quest") && noquest) continue;
|
||||
|
||||
if (noquest && i == quest_dnum) continue;
|
||||
tmp.dlevel = dungeons[i].dunlev_ureached;
|
||||
if (tmp.dlevel == 0) continue;
|
||||
tmp.dnum = i;
|
||||
if(depth(&tmp) > ret) ret = depth(&tmp);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)teleport.c 3.5 2006/03/18 */
|
||||
/* SCCS Id: @(#)teleport.c 3.5 2006/08/05 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1244,11 +1244,23 @@ random_teleport_level()
|
||||
* monsters sometimes level teleporting out of it into main dungeon.
|
||||
* Also prevent monsters reaching the Sanctum prior to invocation.
|
||||
*/
|
||||
min_depth = In_quest(&u.uz) ? dungeons[u.uz.dnum].depth_start : 1;
|
||||
max_depth = dunlevs_in_dungeon(&u.uz) +
|
||||
if (In_quest(&u.uz)) {
|
||||
int bottom = dunlevs_in_dungeon(&u.uz),
|
||||
qlocate_depth = qlocate_level.dlevel;
|
||||
|
||||
/* if hero hasn't reached the middle locate level yet,
|
||||
no one can randomly teleport past it */
|
||||
if (dunlev_reached(&u.uz) < qlocate_depth)
|
||||
bottom = qlocate_depth;
|
||||
min_depth = dungeons[u.uz.dnum].depth_start;
|
||||
max_depth = bottom + (dungeons[u.uz.dnum].depth_start - 1);
|
||||
} else {
|
||||
min_depth = 1;
|
||||
max_depth = dunlevs_in_dungeon(&u.uz) +
|
||||
(dungeons[u.uz.dnum].depth_start - 1);
|
||||
/* can't reach the Sanctum if the invocation hasn't been performed */
|
||||
if (Inhell && !u.uevent.invoked) max_depth -= 1;
|
||||
/* can't reach Sanctum if the invocation hasn't been performed */
|
||||
if (Inhell && !u.uevent.invoked) max_depth -= 1;
|
||||
}
|
||||
|
||||
/* Get a random value relative to the current dungeon */
|
||||
/* Range is 1 to current+3, current not counting */
|
||||
|
||||
20
src/trap.c
20
src/trap.c
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)trap.c 3.5 2006/06/16 */
|
||||
/* SCCS Id: @(#)trap.c 3.5 2006/08/05 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -316,14 +316,25 @@ boolean td; /* td == TRUE : trap door or hole */
|
||||
d_level dtmp;
|
||||
char msgbuf[BUFSZ];
|
||||
const char *dont_fall = 0;
|
||||
register int newlevel = dunlev(&u.uz);
|
||||
int newlevel, bottom;
|
||||
|
||||
/* KMH -- You can't escape the Sokoban level traps */
|
||||
if(Blind && Levitation && !In_sokoban(&u.uz)) return;
|
||||
|
||||
bottom = dunlevs_in_dungeon(&u.uz);
|
||||
/* when in the upper half of the quest, don't fall past the
|
||||
middle "quest locate" level if hero hasn't been there yet */
|
||||
if (In_quest(&u.uz)) {
|
||||
int qlocate_depth = qlocate_level.dlevel;
|
||||
|
||||
/* deepest reached < qlocate implies current < qlocate */
|
||||
if (dunlev_reached(&u.uz) < qlocate_depth)
|
||||
bottom = qlocate_depth; /* early cut-off */
|
||||
}
|
||||
newlevel = dunlev(&u.uz); /* current level */
|
||||
do {
|
||||
newlevel++;
|
||||
} while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz));
|
||||
} while (!rn2(4) && newlevel < bottom);
|
||||
|
||||
if(td) {
|
||||
struct trap *t = t_at(u.ux,u.uy);
|
||||
@@ -341,8 +352,7 @@ boolean td; /* td == TRUE : trap door or hole */
|
||||
else if(Levitation || u.ustuck
|
||||
|| (!Can_fall_thru(&u.uz) && !levl[u.ux][u.uy].candig)
|
||||
|| Flying || is_clinger(youmonst.data)
|
||||
|| (Inhell && !u.uevent.invoked &&
|
||||
newlevel == dunlevs_in_dungeon(&u.uz))
|
||||
|| (Inhell && !u.uevent.invoked && newlevel == bottom)
|
||||
) {
|
||||
dont_fall = "don't fall in.";
|
||||
} else if (youmonst.data->msize >= MZ_HUGE) {
|
||||
|
||||
Reference in New Issue
Block a user