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.
This commit is contained in:
nethack.rankin
2011-01-11 02:21:10 +00:00
parent 3b6c59c7fc
commit 72ca745646
5 changed files with 37 additions and 6 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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);

View File

@@ -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)