]> granicus.if.org Git - nethack/commitdiff
purple worms in wall (trunk only)
authornethack.rankin <nethack.rankin>
Tue, 11 Jan 2011 02:21:10 +0000 (02:21 +0000)
committernethack.rankin <nethack.rankin>
Tue, 11 Jan 2011 02:21:10 +0000 (02:21 +0000)
     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
include/extern.h
src/mhitm.c
src/mhitu.c
src/uhitm.c

index 4da0d05b9464569b6b2fe9f6e6829d822439c137..f4fdb603a10a9590f2900fab60e7a3549395f414 100644 (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
index c4fdf822d28e6d47ec940469b6320d6c3788af82..2e599816be88ff4e8bcd0c9d1044c0081f0d9e3c 100644 (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
index 81cfe9830234345fd31bd099631f53985db49581..c25432fec1cd7a14911f2ddb0c80844aa1b898b7 100644 (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:
index e5d6f84b99f4e2c939a40be96c832f0ec55acd72..e16d982e71ec5f099c6a344e9df619437124a189 100644 (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);
index b1c769a34be73c0ccd5818fbca096916ddc44168..a69f98272d556bf1531b4d99facb49bfb76d1faa 100644 (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)