diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 4da0d05b9..f4fdb603a 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -342,6 +342,7 @@ when reading an unknown scroll and learning it, discovery of teleporation was too late if hero happened to land on another scroll of teleportation using an unlocking tool on a closed door which was actually a mimic reported that there was no door to unlock instead of exposing the mimic +purple worm could end up in wall or solid rock when swallowing ghost or xorn Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index c4fdf822d..2e599816b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1106,6 +1106,7 @@ E int FDECL(buzzmu, (struct monst *,struct attack *)); E int FDECL(fightm, (struct monst *)); E int FDECL(mattackm, (struct monst *,struct monst *)); +E boolean FDECL(engulf_target, (struct monst *,struct monst *)); #ifdef BARGETHROUGH E int FDECL(mdisplacem, (struct monst *,struct monst *,BOOLEAN_P)); #endif diff --git a/src/mhitm.c b/src/mhitm.c index 81cfe9830..c25432fec 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1,5 +1,4 @@ /* NetHack 3.5 mhitm.c $Date$ $Revision$ */ -/* SCCS Id: @(#)mhitm.c 3.5 2007/12/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -550,6 +549,37 @@ gazemm(magr, mdef, mattk) return(mdamagem(magr, mdef, mattk)); } +/* return True if magr is allowed to swallow mdef, False otherwise */ +boolean +engulf_target(magr, mdef) +struct monst *magr, *mdef; +{ + struct rm *lev; + int dx, dy; + + /* can't swallow something that's too big */ + if (mdef->data->msize >= MZ_HUGE) + return FALSE; + + /* (hypothetical) engulfers who can pass through walls aren't + limited by rock|trees|bars */ + if ((magr == &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 == &youmonst) dx = u.ux, dy = u.uy; + 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))) + return FALSE; + + return TRUE; +} + /* Returns the same values as mattackm(). */ STATIC_OVL int gulpmm(magr, mdef, mattk) @@ -561,7 +591,7 @@ gulpmm(magr, mdef, mattk) char buf[BUFSZ]; struct obj *obj; - if (mdef->data->msize >= MZ_HUGE) return MM_MISS; + if (!engulf_target(magr, mdef)) return MM_MISS; if (vis) { Sprintf(buf,"%s swallows", Monnam(magr)); @@ -777,7 +807,7 @@ mdamagem(magr, mdef, mattk) worm's bite attack to kill a shrieker because then it won't swallow the corpse; but if the target survives, the subsequent engulf attack should accomplish that */ - if (tmp >= mdef->mhp) tmp = mdef->mhp - 1; + if (tmp >= mdef->mhp && mdef->mhp > 1) tmp = mdef->mhp - 1; } break; case AD_FIRE: diff --git a/src/mhitu.c b/src/mhitu.c index e5d6f84b9..e16d982e7 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,5 +1,4 @@ /* NetHack 3.5 mhitu.c $Date$ $Revision$ */ -/* SCCS Id: @(#)mhitu.c 3.5 2009/02/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1636,7 +1635,7 @@ gulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */ if (!u.uswallow) { /* swallows you */ int omx = mtmp->mx, omy = mtmp->my; - if (youmonst.data->msize >= MZ_HUGE) return(0); + if (!engulf_target(mtmp, &youmonst)) return 0; if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))) && sobj_at(BOULDER, u.ux, u.uy)) return(0); diff --git a/src/uhitm.c b/src/uhitm.c index b1c769a34..a69f98272 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1832,7 +1832,7 @@ register struct attack *mattk; * after exactly 1 round of attack otherwise. -KAA */ - if (pd->msize >= MZ_HUGE) return 0; + if (!engulf_target(&youmonst, mdef)) return 0; if(u.uhunger < 1500 && !u.uswallow) { for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)