From 72ca7456465dbf68a56fa7a679d5e9f6e0f9b8dc Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 11 Jan 2011 02:21:10 +0000 Subject: [PATCH] purple worms in wall (trunk only) From a bug report, a purple worm could swallow a ghost or xorn and end up inside solid rock. It took a bunch of tries to reproduce this, but I eventually did. (I'm not sure why it didn't happen every time a worm swallowed a target which was in rock; the code for positioning an engulfer after it digests a target always puts the engulfer in the target's former spot.) After this patch, worms can still swallow ghosts and xorns, but only when they're in locations the worm could walk onto. --- doc/fixes35.0 | 1 + include/extern.h | 1 + src/mhitm.c | 36 +++++++++++++++++++++++++++++++++--- src/mhitu.c | 3 +-- src/uhitm.c | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) 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)