fix github issue #1170 - trapped without a trap

Issue reported by mkuoppal:  drum of earthquake triggers a sanity
check warning which the fuzzer escalated to panic.

Analysis by entrez.  If a pit gets created next to a pool or moat or
lava, liquid might flow there and replace the pit.  But the drum of
earthquake code assumed that the pit was still there.  If there was a
monster there and it wasn't levitating or flying and it wasn't killed
by the liquid, it got marked as trapped even though the pit was gone.
'sanity_check' noticed.

With difficulty I was able to reproduce the impossible warning before
the fix, but the are a bunch of random factors at play.  After the
fix I can't reproduce it again, but that's not a guarantee that it's
actually fixed.  The analysis seems correct though and the fix is
based on dealing with that.

Closes #1170
This commit is contained in:
PatR
2023-12-10 03:21:52 -08:00
parent 8b821d0e00
commit 31717fe227
3 changed files with 32 additions and 11 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 dig.c $NHDT-Date: 1596498156 2020/08/03 23:42:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.142 $ */
/* NetHack 3.7 dig.c $NHDT-Date: 1702206282 2023/12/10 11:04:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.204 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -747,19 +747,32 @@ digactualhole(coordxy x, coordxy y, struct monst *madeby, int ttyp)
DISABLE_WARNING_FORMAT_NONLITERAL
/*
* Called from dighole(), but also from do_break_wand()
* in apply.c.
* Called from dighole(); also from do_break_wand() in apply.c
* and do_earthquake() in music.c.
*/
void
liquid_flow(coordxy x, coordxy y, schar typ, struct trap *ttmp,
const char *fillmsg)
liquid_flow(
coordxy x, coordxy y,
schar typ,
struct trap *ttmp,
const char *fillmsg)
{
struct obj *objchain;
struct monst *mon;
boolean u_spot = u_at(x, y);
/* caller should have changed levl[x][y].typ to POOL, MOAT, or LAVA */
if (!is_pool_or_lava(x, y)) {
if (iflags.sanity_check) {
impossible("Insane liquid_flow(%d,%d,%s,%s).", x, y,
ttmp ? trapname(ttmp->ttyp, TRUE) : "no trap",
fillmsg ? fillmsg : "no mesg");
}
return;
}
if (ttmp)
(void) delfloortrap(ttmp);
(void) delfloortrap(ttmp); /* will untrap monster is one is here */
/* if any objects were frozen here, they're released now */
unearth_objs(x, y);