sanity check: avoid "you over monster" impossible

I did this several months ago to avoid a sanity check warning (and
consequent fuzzer panic) when an engulfer expels the hero on a full
level.  I was hoping to refine it but never went back; install it
now before forgetting about it entirely.

If a chameleon changes from wall-phazer to engulfer while in a spot
the hero can't move onto and engulfs him/her, expelling the hero
after the engulfer has taken the hero's spot might be forced to put
the hero on top of the engulfer or another monster when unable to
use the engulfer's former spot.  Rather than try to figure out all
the possible ways this might happen and attempt to deal with each
of them, just prevent an engulf attack from succeeding if the hero
wouldn't be able to move to the engulfer's spot.  (Does not prevent
an air elemental over water from engulfing the hero.)
This commit is contained in:
PatR
2023-11-02 09:12:37 -07:00
parent 196fd41817
commit c1045cc18a
2 changed files with 26 additions and 16 deletions

View File

@@ -1713,6 +1713,10 @@ applying a wielded lump of royal jelly but not picking something to rub it on
"addinv: null obj after quiver merge" (like applying lit potion of oil)
ceiling hider could become hidden when there was no ceiling, triggering a
warning if sanity_check was On
hero could be forced onto a monster's location if a level was full and an
engulfer was occupying an adjacent but inaccessible spot, engulfed
hero, then expelled hero while now occupying hero's accessible spot,
triggering sanity_check warning "you over monster"
experimental #saveoptions wasn't saving the set of cond_xyz options correctly;
if player viewed the 'm O' submenu for status conditions, they would
get saved even if not changed; otherwise, ones that came in from the

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mhitm.c $NHDT-Date: 1627412283 2021/07/27 18:58:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.199 $ */
/* NetHack 3.7 mhitm.c $NHDT-Date: 1698939796 2023/11/02 15:43:16 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.244 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -797,7 +797,9 @@ boolean
engulf_target(struct monst *magr, struct monst *mdef)
{
struct rm *lev;
int dx, dy;
int ax, ay, dx, dy;
boolean uatk = (magr == &gy.youmonst),
udef = (mdef == &gy.youmonst);
/* can't swallow something that's too big */
if (mdef->data->msize >= MZ_HUGE
@@ -808,21 +810,25 @@ engulf_target(struct monst *magr, struct monst *mdef)
if (mdef->mtrapped || magr->mtrapped)
return FALSE;
/* (hypothetical) engulfers who can pass through walls aren't
limited by rock|trees|bars */
if ((magr == &gy.youmonst) ? Passes_walls : passes_walls(magr->data))
return TRUE;
/* don't swallow something in a spot where attacker wouldn't
otherwise be able to move onto; we don't want to engulf
a wall-phaser and end up with a non-phaser inside a wall */
dx = mdef->mx, dy = mdef->my;
if (mdef == &gy.youmonst)
dx = u.ux, dy = u.uy;
/* if attacker is phasing in solid rock and defender can't move there,
or vice versa, don't allow engulf to succeeed; otherwise expelling
might not be able to place attacker and defender both back on map;
when defender is the hero, a sanity_check complaint about placing
the hero on top of a monster can occur */
dx = (mdef == &gy.youmonst) ? u.ux : mdef->mx;
dy = (mdef == &gy.youmonst) ? u.uy : mdef->my;
lev = &levl[dx][dy];
if (IS_ROCK(lev->typ) || closed_door(dx, dy) || IS_TREE(lev->typ)
/* not passes_bars(); engulfer isn't squeezing through */
|| (lev->typ == IRONBARS && !is_whirly(magr->data)))
if (!(udef ? Passes_walls : passes_walls(mdef->data))
&& (IS_ROCK(lev->typ) || closed_door(dx, dy) || IS_TREE(lev->typ)
/* not passes_bars(); engulfer isn't squeezing through */
|| (lev->typ == IRONBARS && !is_whirly(magr->data))))
return FALSE;
ax = (magr == &gy.youmonst) ? u.ux : magr->mx;
ay = (magr == &gy.youmonst) ? u.uy : magr->my;
lev = &levl[ax][ay];
if (!(uatk ? Passes_walls : passes_walls(magr->data))
&& (IS_ROCK(lev->typ) || closed_door(ax, ay) || IS_TREE(lev->typ)
|| (lev->typ == IRONBARS && !is_whirly(mdef->data))))
return FALSE;
return TRUE;