Refine attempt to clamp trap door fall destination

This should prevent anyone from exploiting falling into the sanctum (by
taking advantage of a trap door in a bones file from a differently
laid-out dungeon, as described in the previous commit) to bypass the
invocation, in addition to falling past the actual end of the dungeon.
This commit is contained in:
Michael Meyer
2022-09-21 20:06:35 -04:00
committed by Pasi Kallinen
parent 1830b206c7
commit 9f5b362601

View File

@@ -8,7 +8,7 @@
extern const char *const destroy_strings[][3]; /* from zap.c */
static void mk_trap_statue(coordxy, coordxy);
static int dng_bottom(void);
static int dng_bottom(d_level *lev);
static void hole_destination(d_level *);
static boolean keep_saddle_with_steedcorpse(unsigned, struct obj *,
struct obj *);
@@ -375,19 +375,19 @@ mk_trap_statue(coordxy x, coordxy y)
mongone(mtmp);
}
/* find "bottom" level of current dungeon, stopping at quest locate */
/* find "bottom" level of specified dungeon, stopping at quest locate */
static int
dng_bottom(void)
dng_bottom(d_level *lev)
{
int bottom = dunlevs_in_dungeon(&u.uz);
int bottom = dunlevs_in_dungeon(lev);
/* 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)) {
if (In_quest(lev)) {
int qlocate_depth = qlocate_level.dlevel;
/* deepest reached < qlocate implies current < qlocate */
if (dunlev_reached(&u.uz) < qlocate_depth)
if (dunlev_reached(lev) < qlocate_depth)
bottom = qlocate_depth; /* early cut-off */
}
return bottom;
@@ -397,7 +397,7 @@ dng_bottom(void)
static void
hole_destination(d_level *dst)
{
int bottom = dng_bottom();
int bottom = dng_bottom(&u.uz);
dst->dnum = u.uz.dnum;
dst->dlevel = dunlev(&u.uz);
@@ -520,7 +520,7 @@ fall_through(
d_level dtmp;
char msgbuf[BUFSZ];
const char *dont_fall = 0;
int newlevel, bottom = dng_bottom();
int newlevel, bottom = dng_bottom(&u.uz);
struct trap *t = (struct trap *) 0;
/* we'll fall even while levitating in Sokoban; otherwise, if we
@@ -550,6 +550,8 @@ fall_through(
|| ((Flying || is_clinger(g.youmonst.data)
|| (ceiling_hider(g.youmonst.data) && u.uundetected))
&& !(ftflags & TOOKPLUNGE))
/* this is no longer a very useful test because newlevel isn't
the real destination we're aiming for, if t != 0 */
|| (Inhell && !u.uevent.invoked && newlevel == bottom)) {
dont_fall = "don't fall in.";
} else if (g.youmonst.data->msize >= MZ_HUGE) {
@@ -586,13 +588,17 @@ fall_through(
dtmp.dnum = t->dst.dnum;
/* don't fall beyond the bottom, in case this came from a bones
file with different dungeon size */
bottom = dng_bottom(&t->dst);
dtmp.dlevel = min(t->dst.dlevel, bottom);
dist = dtmp.dlevel - dunlev(&u.uz);
if (In_hell(&t->dst) && !u.uevent.invoked
&& dtmp.dlevel == bottom)
dtmp.dlevel--;
} else {
dtmp.dnum = u.uz.dnum;
dtmp.dlevel = newlevel;
dist = newlevel - dunlev(&u.uz);
}
/* XXX: dist won't be accurate if dtmp.dnum may not match u.uz.dnum */
dist = dtmp.dlevel - dunlev(&u.uz);
if (dist > 1)
You("fall down a %s%sshaft!", dist > 3 ? "very " : "",
dist > 2 ? "deep " : "");