Fix: a number of unblock_points shouldn't unblock unconditionally

Initially diagnosed in an xnethack fuzzer crash - unblock_point
shouldn't be called when a closed door becomes non-closed, because it's
possible that there's a gas cloud on the space which means it still
blocks vision. These always need to be recalc_block_point. A number of
them were fixed, but when I went through all the xnethack ones, I found
some that were unchanged from upstream NetHack. I reproduced the sanity
check impossibles usually by breathing gas at a door as an iron golem
and then opening or destroying the door to trigger the unblock_point
call.

The use of recalc_block_point in wizterrainwish was not triggering this
bug, but the previous code there basically duplicated
recalc_block_point.
This commit is contained in:
copperwater
2025-03-08 07:53:57 -05:00
parent a6a1e1b365
commit 49b43f760f
6 changed files with 6 additions and 13 deletions
+1 -1
View File
@@ -1435,7 +1435,7 @@ mdig_tunnel(struct monst *mtmp)
sawit = canseemon(mtmp); /* before door state change and unblock_pt */ sawit = canseemon(mtmp); /* before door state change and unblock_pt */
trapped = (here->doormask & D_TRAPPED) ? TRUE : FALSE; trapped = (here->doormask & D_TRAPPED) ? TRUE : FALSE;
here->doormask = trapped ? D_NODOOR : D_BROKEN; here->doormask = trapped ? D_NODOOR : D_BROKEN;
unblock_point(mtmp->mx, mtmp->my); /* vision */ recalc_block_point(mtmp->mx, mtmp->my); /* vision */
newsym(mtmp->mx, mtmp->my); newsym(mtmp->mx, mtmp->my);
if (trapped) { if (trapped) {
seeit = canseemon(mtmp); seeit = canseemon(mtmp);
+1 -1
View File
@@ -949,7 +949,7 @@ kick_door(coordxy x, coordxy y, int avrg_attrib)
gm.maploc->doormask = D_BROKEN; gm.maploc->doormask = D_BROKEN;
} }
feel_newsym(x, y); /* we know we broke it */ feel_newsym(x, y); /* we know we broke it */
unblock_point(x, y); /* vision */ recalc_block_point(x, y); /* vision */
if (shopdoor) { if (shopdoor) {
add_damage(x, y, SHOP_DOOR_COST); add_damage(x, y, SHOP_DOOR_COST);
pay_for_damage("break", FALSE); pay_for_damage("break", FALSE);
+1 -1
View File
@@ -787,7 +787,7 @@ still_chewing(coordxy x, coordxy y)
lev->typ = CORR; lev->typ = CORR;
} }
unblock_point(x, y); /* vision */ recalc_block_point(x, y); /* vision */
newsym(x, y); newsym(x, y);
if (digtxt) if (digtxt)
You1(digtxt); /* after newsym */ You1(digtxt); /* after newsym */
+1 -1
View File
@@ -463,7 +463,7 @@ do_earthquake(int force)
} }
/* wasn't doorless, now it will be */ /* wasn't doorless, now it will be */
levl[x][y].doormask = D_NODOOR; levl[x][y].doormask = D_NODOOR;
unblock_point(x, y); recalc_block_point(x, y);
newsym(x, y); /* before pline */ newsym(x, y); /* before pline */
if (cansee(x, y)) if (cansee(x, y))
pline_The("door collapses."); pline_The("door collapses.");
+1 -8
View File
@@ -3862,14 +3862,7 @@ wizterrainwish(struct _readobjnam_data *d)
} else { } else {
if (u.utrap && u.utraptype == TT_LAVA && !is_lava(u.ux, u.uy)) if (u.utrap && u.utraptype == TT_LAVA && !is_lava(u.ux, u.uy))
reset_utrap(FALSE); reset_utrap(FALSE);
recalc_block_point(x, y);
if (does_block(x, y, lev)) {
if (!didblock)
block_point(x, y);
} else {
if (didblock)
unblock_point(x, y);
}
} }
/* fixups for replaced terrain that aren't handled above */ /* fixups for replaced terrain that aren't handled above */
+1 -1
View File
@@ -3443,7 +3443,7 @@ launch_obj(
} }
levl[x][y].doormask = D_BROKEN; levl[x][y].doormask = D_BROKEN;
if (dist) if (dist)
unblock_point(x, y); recalc_block_point(x, y);
} }
/* if about to hit something, do so now */ /* if about to hit something, do so now */