]> granicus.if.org Git - nethack/commitdiff
attack/damage by trapper and lurker above
authorPatR <rankin@nethack.org>
Mon, 15 Aug 2022 11:14:36 +0000 (04:14 -0700)
committerPatR <rankin@nethack.org>
Mon, 15 Aug 2022 11:14:36 +0000 (04:14 -0700)
Change trappers and lurkers above to remove digestion damage.  They
fold themselves around rather than swallow the victim.  There were
are lot of places that assumed that an engulfer which is an animal
would swallow and digest the victim.  In hindsight, it might have
been simpler to take the M1_ANIMAL flag off of trappers and lurkers
above.

This adds a new digests() predicate for creatures with AT_ENGL+AD_DGST
(purple worm) and also enfolds() for AT_ENGL+AD_WRAP (both 't'-class
critters).

There are several minor fixes mixed in with this.  I didn't record
them as I went along but the two I remember are
1) if poly'd into a holder and holding on to a monster, the '<' and
   '>' commands refursed to work; release the held creature first
   and then treat those commands as normal;
2) throwing a non-weapon while engulfed by an ochre jelly reported
   "the <item> vanishes into the ochre jelly's /currents/".

This needs a lot more testing.  I found and fixed multiple minor
details before my own testing burned out.

25 files changed:
doc/fixes3-7-0.txt
include/mondata.h
include/monsters.h
src/apply.c
src/detect.c
src/dig.c
src/do.c
src/dokick.c
src/dothrow.c
src/engrave.c
src/explode.c
src/hack.c
src/insight.c
src/mhitm.c
src/mhitu.c
src/mon.c
src/mondata.c
src/pager.c
src/pickup.c
src/polyself.c
src/read.c
src/spell.c
src/trap.c
src/uhitm.c
src/zap.c

index b3473abe233cd67ccf8eb2a46aa59b0b2f1e4c64..fc9fcd74ddfdb47e781f171feceac1228fdce0eb 100644 (file)
@@ -1001,6 +1001,12 @@ blind hero was notified when brass lantern burned out even though it isn't
        on or off can be determined that way so still gives on/off message
 turn on statushilites automatically if any are defined
 change poison instakill to damage with attribute and max hp loss
+trappers and lurkers above enfold themselves around and crush their victims,
+       not swallow and digest
+attempting to move up or down when poly'd into a holder and holding a monster
+       rejected the move; release the monster instead
+thowing a non-weapon while engulfed by an ochre jelly reported that the item
+       vanished into the jelly's "currents"
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index e2cc238957e060a06c5c90ee5ffcbdafd0125b51..854ec06ad16a0b8559432f246f0c562284751a8b 100644 (file)
@@ -86,6 +86,8 @@
 #define is_wooden(ptr) ((ptr) == &mons[PM_WOOD_GOLEM])
 #define thick_skinned(ptr) (((ptr)->mflags1 & M1_THICK_HIDE) != 0L)
 #define hug_throttles(ptr) ((ptr) == &mons[PM_ROPE_GOLEM])
+#define digests(ptr) dmgtype_fromattack((ptr), AD_DGST, AT_ENGL) /* purple w*/
+#define enfolds(ptr) dmgtype_fromattack((ptr), AD_WRAP, AT_ENGL) /* 't' */
 #define slimeproof(ptr) \
     ((ptr) == &mons[PM_GREEN_SLIME] || flaming(ptr) || noncorporeal(ptr))
 #define lays_eggs(ptr) (((ptr)->mflags1 & M1_OVIPAROUS) != 0L)
index 294ac954a4364f36de35adeb52c895854654b263..0d4f8dbb1e4c1d4526771de2d2358e00670b876d 100644 (file)
         M2_HOSTILE, 0, 8, CLR_RED, SCORPION),
     /*
      * trappers, lurkers, &c
+     * Note:  prior to 3.7, these were defined to do AD_DGST damage,
+     * but they don't swallow their victims into their stomachs and
+     * digest, they enfold and crush or suffocate.
+     * The Monster Manual states that someone engulfed by a trapper
+     * can't use weapons but we do not enforce that.
      */
     MON("lurker above", S_TRAPPER, LVL(10, 3, 3, 0, 0), (G_GENO | 2),
-        A(ATTK(AT_ENGL, AD_DGST, 1, 8), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+        A(ATTK(AT_ENGL, AD_WRAP, 1, 6), ATTK(AT_ENGL, AD_PHYS, 2, 6),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(800, 350, MS_SILENT, MZ_HUGE), 0, 0,
         M1_HIDE | M1_FLY | M1_ANIMAL | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
             | M1_CARNIVORE,
         M2_HOSTILE | M2_STALK | M2_STRONG, 0, 12, CLR_GRAY, LURKER_ABOVE),
     MON("trapper", S_TRAPPER, LVL(12, 3, 3, 0, 0), (G_GENO | 2),
-        A(ATTK(AT_ENGL, AD_DGST, 1, 10), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+        A(ATTK(AT_ENGL, AD_WRAP, 1, 8), ATTK(AT_ENGL, AD_PHYS, 2, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(800, 350, MS_SILENT, MZ_HUGE), 0, 0,
         M1_HIDE | M1_ANIMAL | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
             | M1_CARNIVORE,
      * vortices
      */
     MON("fog cloud", S_VORTEX, LVL(3, 1, 0, 0, 0), (G_GENO | G_NOCORPSE | 2),
-        A(ATTK(AT_ENGL, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+        A(ATTK(AT_ENGL, AD_PHYS, 1, 6),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_SLEEP | MR_POISON | MR_STONE, 0,
         M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
             | M1_MINDLESS | M1_AMORPHOUS | M1_UNSOLID,
         M2_HOSTILE | M2_NEUTER, 0, 4, CLR_GRAY, FOG_CLOUD),
     MON("dust vortex", S_VORTEX, LVL(4, 20, 2, 30, 0),
-        (G_GENO | G_NOCORPSE | 2), A(ATTK(AT_ENGL, AD_BLND, 2, 8), NO_ATTK,
-                                     NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+        (G_GENO | G_NOCORPSE | 2),
+        A(ATTK(AT_ENGL, AD_BLND, 2, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_SLEEP | MR_POISON | MR_STONE, 0,
         M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
             | M1_MINDLESS,
index b2c7b5e152975d136cb71bdc366ac1df820cec4c..ad7ea0dd67e18801b3338dd079f66438c2abe5f8 100644 (file)
@@ -2722,8 +2722,7 @@ use_trap(struct obj *otmp)
     else if (Stunned)
         what = "while stunned";
     else if (u.uswallow)
-        what =
-            is_animal(u.ustuck->data) ? "while swallowed" : "while engulfed";
+        what = digests(u.ustuck->data) ? "while swallowed" : "while engulfed";
     else if (Underwater)
         what = "underwater";
     else if (Levitation)
index 78311aa1302e5ca2a4dae6673cc504d969cc54e2..f042f719acbbd847783128788fe80f71fbd9c119 100644 (file)
@@ -1676,11 +1676,17 @@ openit(void)
     int num = 0;
 
     if (u.uswallow) {
-        if (is_animal(u.ustuck->data)) {
+        if (digests(u.ustuck->data)) {
+            /* purple worm */
             if (Blind)
                 pline("Its mouth opens!");
             else
                 pline("%s opens its mouth!", Monnam(u.ustuck));
+#if 0   /* expels() will take care of this */
+        } else if (enfolds(u.ustuck->data)) {
+            /* trapper or lurker above */
+            pline("%s unfolds!", Monnam(u.ustuck));
+#endif
         }
         expels(u.ustuck, u.ustuck->data, TRUE);
         return -1;
index 8fe5d0fda368e7c1e797829da2fe2704b2595166..0e92c6019e36700851229dd17b2ad0a1070ad137 100644 (file)
--- a/src/dig.c
+++ b/src/dig.c
@@ -1411,14 +1411,14 @@ zap_dig(void)
         mtmp = u.ustuck;
 
         if (!is_whirly(mtmp->data)) {
-            if (is_animal(mtmp->data))
+            if (digests(mtmp->data))
                 You("pierce %s %s wall!", s_suffix(mon_nam(mtmp)),
                     mbodypart(mtmp, STOMACH));
             if (unique_corpstat(mtmp->data))
                 mtmp->mhp = (mtmp->mhp + 1) / 2;
             else
                 mtmp->mhp = 1; /* almost dead */
-            expels(mtmp, mtmp->data, !is_animal(mtmp->data));
+            expels(mtmp, mtmp->data, !digests(mtmp->data));
         }
         return;
     } /* swallowed */
index 2ca0b940e93400869584d7e2e0b44a3432222df1..c6267249f0c2213377338b2b1858e7d5e196adae 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -647,13 +647,18 @@ drop(struct obj *obj)
     if (u.uswallow) {
         /* barrier between you and the floor */
         if (Verbose(0, drop1)) {
-            char *onam_p, monbuf[BUFSZ];
+            char *onam_p, *mnam_p, monbuf[BUFSZ];
 
+            mnam_p = mon_nam(u.ustuck);
             /* doname can call s_suffix, reusing its buffer */
-            Strcpy(monbuf, s_suffix(mon_nam(u.ustuck)));
+            if (digests(u.ustuck->data)) {
+                Sprintf(monbuf, "%s %s", s_suffix(mnam_p),
+                        mbodypart(u.ustuck, STOMACH));
+                mnam_p = monbuf;
+            }
             onam_p = is_unpaid(obj) ? yobjnam(obj, (char *) 0) : doname(obj);
-            You("drop %s into %s %s.", onam_p, monbuf,
-                mbodypart(u.ustuck, STOMACH));
+
+            You("drop %s into %s.", onam_p, mnam_p);
         }
     } else {
         if ((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING)
@@ -752,9 +757,9 @@ dropz(struct obj *obj, boolean with_impact)
 static boolean
 engulfer_digests_food(struct obj *obj)
 {
-    /* animal swallower (purple worn, trapper, lurker above) eats any
+    /* animal swallower (purple worn) eats any
        corpse, glob, or meat <item> but not other types of food */
-    if (is_animal(u.ustuck->data)
+    if (digests(u.ustuck->data)
         && (obj->otyp == CORPSE || obj->globby
             || obj->otyp == MEATBALL || obj->otyp == HUGE_CHUNK_OF_MEAT
             || obj->otyp == MEAT_RING || obj->otyp == MEAT_STICK)) {
@@ -1070,11 +1075,18 @@ dodown(void)
     }
 
     if (u.ustuck) {
-        You("are %s, and cannot go down.",
-            !u.uswallow ? "being held" : is_animal(u.ustuck->data)
-                                             ? "swallowed"
-                                             : "engulfed");
-        return ECMD_TIME;
+        if (u.uswallow || !sticks(g.youmonst.data)) {
+            You("are %s, and cannot go down.",
+                !u.uswallow ? "being held"
+                : digests(u.ustuck->data) ? "swallowed"
+                  : "engulfed");
+            return ECMD_TIME;
+        } else {
+            struct monst *mtmp = u.ustuck;
+
+            set_ustuck((struct monst *) 0);
+            You("release %s.", mon_nam(mtmp));
+        }
     }
 
     if (!stairs_down && !ladder_down) {
@@ -1168,11 +1180,18 @@ doup(void)
         return ECMD_OK;
     }
     if (u.ustuck) {
-        You("are %s, and cannot go up.",
-            !u.uswallow ? "being held" : is_animal(u.ustuck->data)
-                                             ? "swallowed"
-                                             : "engulfed");
-        return ECMD_TIME;
+        if (u.uswallow || !sticks(g.youmonst.data)) {
+            You("are %s, and cannot go up.",
+                !u.uswallow ? "being held"
+                : digests(u.ustuck->data) ? "swallowed"
+                  : "engulfed");
+            return ECMD_TIME;
+        } else {
+            struct monst *mtmp = u.ustuck;
+
+            set_ustuck((struct monst *) 0);
+            You("release %s.", mon_nam(mtmp));
+        }
     }
     if (near_capacity() > SLT_ENCUMBER) {
         /* No levitation check; inv_weight() already allows for it */
index 1236dc6904072fe4612139cba4e654c2a70ceabc..4f1b8797a08fc09571538f28523747dfb58121f8 100644 (file)
@@ -933,7 +933,7 @@ dokick(void)
             You_cant("move your %s!", body_part(LEG));
             break;
         case 1:
-            if (is_animal(u.ustuck->data)) {
+            if (digests(u.ustuck->data)) {
                 pline("%s burps loudly.", Monnam(u.ustuck));
                 break;
             }
index a75fac95fe41b43fa4d714654b18c7d8ad9177ab..bdf78ef5c8fed645195533a85625508a9b3eaa49 100644 (file)
@@ -2068,10 +2068,14 @@ thitmonst(
             mon->mstrategy &= ~STRAT_WAITMASK;
         }
     } else if (guaranteed_hit) {
+        char trail[BUFSZ];
+        char *monname;
+        struct permonst *md = u.ustuck->data;
+
         /* this assumes that guaranteed_hit is due to swallowing */
         wakeup(mon, TRUE);
         if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
-            if (is_animal(u.ustuck->data)) {
+            if (is_animal(md)) {
                 minstapetrify(u.ustuck, TRUE);
                 /* Don't leave a cockatrice corpse available in a statue */
                 if (!u.uswallow) {
@@ -2080,9 +2084,12 @@ thitmonst(
                 }
             }
         }
-        pline("%s into %s %s.", Tobjnam(obj, "vanish"),
-              s_suffix(mon_nam(mon)),
-              is_animal(u.ustuck->data) ? "entrails" : "currents");
+        Strcpy(trail,
+               digests(md) ? " entrails" : is_whirly(md) ? " currents" : "");
+        monname = mon_nam(mon);
+        if (*trail)
+            monname = s_suffix(monname);
+        pline("%s into %s%s.", Tobjnam(obj, "vanish"), monname, trail);
     } else {
         tmiss(obj, mon, TRUE);
     }
@@ -2429,10 +2436,11 @@ throw_gold(struct obj *obj)
     freeinv(obj);
     if (u.uswallow) {
         const char *swallower = mon_nam(u.ustuck);
-        if (is_animal(u.ustuck->data))
-            swallower = s_suffix(swallower);
-        pline_The("gold disappears into %s%s.", swallower,
-                  is_animal(u.ustuck->data) ? " entrails" : "");
+
+        if (digests(u.ustuck->data))
+            /* note: s_suffix() returns a modifiable buffer */
+            swallower = strcat(s_suffix(swallower), " entrails");
+        pline_The("gold disappears into %s.", swallower);
         add_to_minv(u.ustuck, obj);
         return ECMD_TIME;
     }
index 975b79a09f934e6068a69f15318c5e83e5a0147c..b76ed91b825b318ec4960fda120c8f30b6f24f4e 100644 (file)
@@ -192,7 +192,10 @@ surface(coordxy x, coordxy y)
     struct rm *lev = &levl[x][y];
 
     if (u_at(x, y) && u.uswallow && is_animal(u.ustuck->data))
-        return "maw";
+        /* 'husk' is iffy but maw is wrong for 't' class */
+        return digests(u.ustuck->data) ? "maw"
+               : enfolds(u.ustuck->data) ? "husk"
+                 : "nonesuch"; /* can't happen (fingers crossed...) */
     else if (IS_AIR(lev->typ) && Is_airlevel(&u.uz))
         return "air";
     else if (is_pool(x, y))
@@ -461,6 +464,8 @@ u_can_engrave(void)
             cant_reach_floor(u.ux, u.uy, FALSE, FALSE);
             return FALSE;
         }
+        /* Note: for amorphous engulfers, writing attempt is allowed here
+           but yields the 'jello' result in doengrave() */
     } else if (is_lava(u.ux, u.uy)) {
         You_cant("write on the %s!", surface(u.ux, u.uy));
         return FALSE;
index 227bb636b69741ffcb40ad02bf28dc27332c62e2..ee56eb6dcc558686b5462019f70710c7c305c7ba 100644 (file)
@@ -372,7 +372,7 @@ explode(
                 if (engulfing_u(mtmp)) {
                     const char *adj = (char *) 0;
 
-                    if (is_animal(u.ustuck->data)) {
+                    if (digests(u.ustuck->data)) {
                         switch (adtyp) {
                         case AD_FIRE:
                             adj = "heartburn";
index 5412e47f2a2eb3b0ed4260ceeb54573e9a2565d2..41acee2a743ac4d5bffeb8ec965e9ebf82e54cb6 100644 (file)
@@ -1404,7 +1404,7 @@ is_valid_travelpt(coordxy x, coordxy y)
    (all failures and most successful escapes leave hero at original spot) */
 static boolean
 trapmove(
-    coordxy x, coordxy y,          /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
+    coordxy x, coordxy y, /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
     struct trap *desttrap) /* nonnull if another trap at <x,y> */
 {
     boolean anchored = FALSE;
@@ -3204,7 +3204,7 @@ pickup_checks(void)
     /* uswallow case added by GAN 01/29/87 */
     if (u.uswallow) {
         if (!u.ustuck->minvent) {
-            if (is_animal(u.ustuck->data)) {
+            if (digests(u.ustuck->data)) {
                 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
                 pline("But it's kind of slimy, so you drop it.");
             } else
index 3dfada4ad1bdcd51fc2274665231292a05c52d92..bce4ae428fbb910b2eb02d53098b4ce14bfde514 100644 (file)
@@ -1036,7 +1036,7 @@ status_enlightenment(int mode, int final)
     }
     if (u.uswallow) { /* implies u.ustuck is non-Null */
         Snprintf(buf, sizeof buf, "%s by %s",
-                is_animal(u.ustuck->data) ? "swallowed" : "engulfed",
+                digests(u.ustuck->data) ? "swallowed" : "engulfed",
                 heldmon);
         if (dmgtype(u.ustuck->data, AD_DGST)) {
             /* if final, death via digestion can be deduced by u.uswallow
@@ -3023,13 +3023,26 @@ mstatusline(struct monst *mtmp)
                          : ", [? speed]");
     if (mtmp->minvis)
         Strcat(info, ", invisible");
-    if (mtmp == u.ustuck)
-        Strcat(info, sticks(g.youmonst.data) ? ", held by you"
-                      : !u.uswallow ? ", holding you"
-                         : attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_DGST)
-                            ? ", digesting you"
-                            : is_animal(u.ustuck->data) ? ", swallowing you"
-                               : ", engulfing you");
+    if (mtmp == u.ustuck) {
+        struct permonst *pm = u.ustuck->data;
+
+        /* being swallowed/engulfed takes priority over sticks(youmonst);
+           this used to have that backwards and checked sticks() first */
+        Strcat(info, u.uswallow ? (digests(pm)
+                                   ? ", digesting you"
+                                   /* note: the "swallowing you" case won't
+                                      happen because all animal engulfers
+                                      either digest their victims (purple
+                                      worm) or enfold them (trappers and
+                                      lurkers above) */
+                                   : (is_animal(pm) && !enfolds(pm))
+                                     ? ", swallowing you"
+                                     : ", engulfing you")
+                     /* !u.uswallow; if both youmonst and ustuck are holders,
+                        youmonst wins */
+                     : (!sticks(g.youmonst.data) ? ", holding you"
+                                                 : ", held by you"));
+    }
     if (mtmp == u.usteed) {
         Strcat(info, ", carrying you");
         if (Wounded_legs) {
index a51dc9db504a44d63dceb9eeaf0dda9e550a8d60..1b539c9231f1ee0b525636b9c8b828ce783bef4a 100644 (file)
@@ -766,7 +766,8 @@ gulpmm(
         /* [this two-part formatting dates back to when only one x_monnam
            result could be included in an expression because the next one
            would overwrite first's result -- that's no longer the case] */
-        Sprintf(buf, "%s swallows", Monnam(magr));
+        Sprintf(buf, "%s %s", Monnam(magr),
+                digests(magr->data) ? "swallows" : "engulfs");
         pline("%s %s.", buf, mon_nam(mdef));
     }
     if (!flaming(magr->data)) {
index 27c2c9de9dbd0d6770979e04a1f9d7ce729f0181..77f32c6394516d7b17dc691e9b613be4b0d14999 100644 (file)
@@ -232,14 +232,17 @@ wildmiss(struct monst *mtmp, struct attack *mattk)
 }
 
 void
-expels(struct monst *mtmp,
-       struct permonst *mdat, /* if mtmp is polymorphed, mdat != mtmp->data */
-       boolean message)
+expels(
+    struct monst *mtmp,
+    struct permonst *mdat, /* if mtmp is polymorphed, mdat != mtmp->data */
+    boolean message)
 {
     g.context.botl = 1;
     if (message) {
-        if (is_animal(mdat)) {
+        if (digests(mdat)) {
             You("get regurgitated!");
+        } else if (enfolds(mdat)) {
+            pline("%s unfolds and you are released!", Monnam(mtmp));
         } else {
             char blast[40];
             struct attack *attk = attacktype_fordmg(mdat, AT_ENGL, AD_ANY);
@@ -717,7 +720,7 @@ mattacku(register struct monst *mtmp)
                     } else {
                         missmu(mtmp, (tmp == j), mattk);
                     }
-                } else if (is_animal(mtmp->data)) {
+                } else if (digests(mtmp->data)) {
                     pline("%s gulps some air!", Monnam(mtmp));
                 } else {
                     if (youseeit)
@@ -897,8 +900,13 @@ diseasemu(struct permonst *mdat)
 boolean
 u_slip_free(struct monst *mtmp, struct attack *mattk)
 {
-    struct obj *obj = (uarmc ? uarmc : uarm);
+    struct obj *obj;
 
+    /* greased armor does not protect against AT_ENGL+AD_WRAP */
+    if (mattk->aatyp == AT_ENGL)
+        return FALSE;
+
+    obj = (uarmc ? uarmc : uarm);
     if (!obj)
         obj = uarmu;
     if (mattk->adtyp == AD_DRIN)
@@ -1165,8 +1173,8 @@ gulpmu(struct monst *mtmp, struct attack *mattk)
             dismount_steed(DISMOUNT_ENGULFED);
         } else {
             urgent_pline("%s %s!", Monnam(mtmp),
-                         is_animal(mtmp->data) ? "swallows you whole"
-                            : "engulfs you");
+                         digests(mtmp->data) ? "swallows you whole"
+                           : "engulfs you");
         }
         stop_occupation();
         reset_occupations(); /* behave as if you had moved */
@@ -1278,7 +1286,8 @@ gulpmu(struct monst *mtmp, struct attack *mattk)
             if (Amphibious && !flaming(g.youmonst.data))
                 tmp = 0;
         } else {
-            You("are pummeled with debris!");
+            You("are %s!", enfolds(mtmp->data) ? "being squashed"
+                                               : "pummeled with debris");
             exercise(A_STR, FALSE);
         }
         break;
@@ -1378,17 +1387,20 @@ gulpmu(struct monst *mtmp, struct attack *mattk)
         ; /* life-saving has already expelled swallowed hero */
     } else if (touch_petrifies(g.youmonst.data) && !resists_ston(mtmp)) {
         pline("%s very hurriedly %s you!", Monnam(mtmp),
-              is_animal(mtmp->data) ? "regurgitates" : "expels");
+              digests(mtmp->data) ? "regurgitates"
+              : enfolds(mtmp->data) ? "releases"
+                : "expels");
         expels(mtmp, mtmp->data, FALSE);
     } else if (!u.uswldtim || g.youmonst.data->msize >= MZ_HUGE) {
         /* As of 3.6.2: u.uswldtim used to be set to 0 by life-saving but it
            expels now so the !u.uswldtim case is no longer possible;
            however, polymorphing into a huge form while already
            swallowed is still possible */
-        You("get %s!", is_animal(mtmp->data) ? "regurgitated" : "expelled");
+        You("get %s!", digests(mtmp->data) ? "regurgitated"
+                       : enfolds(mtmp->data) ? "released"
+                         : "expelled");
         if (Verbose(1, gulpmu)
-            && (is_animal(mtmp->data)
-                || (dmgtype(mtmp->data, AD_DGST) && Slow_digestion)))
+            && (digests(mtmp->data) && Slow_digestion))
             pline("Obviously %s doesn't like your taste.", mon_nam(mtmp));
         expels(mtmp, mtmp->data, FALSE);
     }
@@ -1712,8 +1724,9 @@ mdamageu(struct monst *mtmp, int n)
  *         2 if wrong gender for nymph
  */
 int
-could_seduce(struct monst *magr, struct monst *mdef,
-             struct attack *mattk) /* non-Null: current attack; Null: general capability */
+could_seduce(
+    struct monst *magr, struct monst *mdef,
+    struct attack *mattk) /* non-Null: current atk; Null: general capability */
 {
     struct permonst *pagr;
     boolean agrinvis, defperc;
index d3a271fca39b1a8eeb3ae4ceeaf3c8e5cdbb950a..cbcbadb0676c897c8be8f3f9ceca9a816245d3c4 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -2893,13 +2893,13 @@ monstone(struct monst* mdef)
         unmap_object(x, y);
     if (cansee(x, y))
         newsym(x, y);
-    /* We don't currently trap the hero in the statue in this case but we
-     * could */
+    /* we don't currently trap the hero in the statue in this case but we
+       could */
     if (engulfing_u(mdef))
         wasinside = TRUE;
     mondead(mdef);
     if (wasinside) {
-        if (is_animal(mdef->data))
+        if (digests(mdef->data))
             You("%s through an opening in the new %s.",
                 u_locomotion("jump"), xname(otmp));
     }
@@ -4675,7 +4675,7 @@ newcham(
                     if (is_vampshifter(mtmp)) {
                         Sprintf(msgtrail, " which was a shapeshifted %s",
                                 noname_monnam(mtmp, ARTICLE_NONE));
-                    } else if (is_animal(mdat)) {
+                    } else if (digests(mdat)) {
                         Strcpy(msgtrail, "'s stomach");
                     } else {
                         msgtrail[0] = '\0';
index 764be912429170b897c6e49cc27fe5f90f30cd79..e66bfed72fe02ebe23c329fcda9c70dd5e87b453 100644 (file)
@@ -456,7 +456,8 @@ breakarm(register struct permonst* ptr)
 boolean
 sticks(register struct permonst* ptr)
 {
-    return (boolean) (dmgtype(ptr, AD_STCK) || dmgtype(ptr, AD_WRAP)
+    return (boolean) (dmgtype(ptr, AD_STCK)
+                      || (dmgtype(ptr, AD_WRAP) && !attacktype(ptr, AT_ENGL))
                       || attacktype(ptr, AT_HUGS));
 }
 
index b9a5d2b5b80e262e384f836a7c21163069b6230c..3983216e2f18d92e98d9df62f2782f1f8f252116 100644 (file)
@@ -352,8 +352,8 @@ look_at_monster(char *buf,
             name);
     if (u.ustuck == mtmp) {
         if (u.uswallow || iflags.save_uswallow) /* monster detection */
-            Strcat(buf, is_animal(mtmp->data)
-                          ? ", swallowing you" : ", engulfing you");
+            Strcat(buf, digests(mtmp->data) ? ", swallowing you"
+                                            : ", engulfing you");
         else
             Strcat(buf, (Upolyd && sticks(g.youmonst.data))
                           ? ", being held" : ", holding you");
index c7bb2603ce67dadd312b6b790d41d733d3ceda6e..973da2d653af606ebea426342b5406a3b85399cb 100644 (file)
@@ -1064,7 +1064,7 @@ query_objlist(const char *qstr,        /* query string */
         any = cg.zeroany;
         if (sorted && n > 1) {
             Sprintf(buf, "%s Creatures",
-                    is_animal(u.ustuck->data) ? "Swallowed" : "Engulfed");
+                    digests(u.ustuck->data) ? "Swallowed" : "Engulfed");
             add_menu(win, &nul_glyphinfo, &any, 0, 0, iflags.menu_headings,
                      clr, buf, MENU_ITEMFLAGS_NONE);
         }
index 655616953da53aab33fa486faae41b6b971f2d50..f68477049ef9e79afca83cb5923a3fce1904833a 100644 (file)
@@ -1590,8 +1590,8 @@ dohide(void)
     if (u.ustuck || (u.utrap && (u.utraptype != TT_PIT || on_ceiling))) {
         You_cant("hide while you're %s.",
                  !u.ustuck ? "trapped"
-                   : u.uswallow ? (is_animal(u.ustuck->data) ? "swallowed"
-                                                             : "engulfed")
+                   : u.uswallow ? (digests(u.ustuck->data) ? "swallowed"
+                                                           : "engulfed")
                      : !sticks(g.youmonst.data) ? "being held"
                        : (humanoid(u.ustuck->data) ? "holding someone"
                                                    : "holding that creature"));
index 5089314a6b160fd73c9244a7aedec4093a410c93..284569e7b06416bdf5d45c0507757e3e6e2d9cca 100644 (file)
@@ -2385,7 +2385,7 @@ litroom(
         if (u.uswallow) {
             if (Blind)
                 ; /* no feedback */
-            else if (is_animal(u.ustuck->data))
+            else if (digests(u.ustuck->data))
                 pline("%s %s is lit.", s_suffix(Monnam(u.ustuck)),
                       mbodypart(u.ustuck, STOMACH));
             else if (is_whirly(u.ustuck->data))
index 7ef7547137e3126cc0e239199c4f148e4b1bad4c..8e2bc0e485d4d3fa1ea1706416c4d5f6aeddab22 100644 (file)
@@ -822,24 +822,20 @@ cast_protection(void)
             if (u.uspellprot) {
                 pline_The("%s haze around you becomes more dense.", hgolden);
             } else {
+                struct permonst *pm = u.ustuck ? u.ustuck->data : 0;
+
                 rmtyp = levl[u.ux][u.uy].typ;
                 atmosphere = u.uswallow
-                                ? ((u.ustuck->data == &mons[PM_FOG_CLOUD])
-                                   ? "mist"
-                                   : is_whirly(u.ustuck->data)
-                                      ? "maelstrom"
-                                      : is_animal(u.ustuck->data)
-                                         ? "maw"
+                                ? ((pm == &mons[PM_FOG_CLOUD]) ? "mist"
+                                   : is_whirly(u.ustuck->data) ? "maelstrom"
+                                     : enfolds(pm) ? "folds"
+                                       : is_animal(u.ustuck->data) ? "maw"
                                          : "ooze")
-                                : (u.uinwater
-                                   ? hliquid("water")
-                                   : (rmtyp == CLOUD)
-                                      ? "cloud"
-                                      : IS_TREE(rmtyp)
-                                         ? "vegetation"
-                                         : IS_STWALL(rmtyp)
-                                            ? "stone"
-                                            : "air");
+                                : (u.uinwater ? hliquid("water")
+                                   : (rmtyp == CLOUD) ? "cloud"
+                                     : IS_TREE(rmtyp) ? "vegetation"
+                                       : IS_STWALL(rmtyp) ? "stone"
+                                         : "air");
                 pline_The("%s around you begins to shimmer with %s haze.",
                           atmosphere, an(hgolden));
             }
index 3ba2729a5a04f5a8793170943f51328ef519d7e9..ede15c7631035d53b89908da0184adf064defd34 100644 (file)
@@ -3419,10 +3419,11 @@ float_up(void)
     } else if (u.uinwater) {
         spoteffects(TRUE);
     } else if (u.uswallow) {
-        You(is_animal(u.ustuck->data) ? "float away from the %s."
-                                      : "spiral up into %s.",
-            is_animal(u.ustuck->data) ? surface(u.ux, u.uy)
-                                      : mon_nam(u.ustuck));
+        /* FIXME: this isn't correct for trapper/lurker above */
+        if (is_animal(u.ustuck->data))
+            You("float away from the %s.", surface(u.ux, u.uy));
+        else
+            You("spiral up into %s.", mon_nam(u.ustuck));
     } else if (Hallucination) {
         pline("Up, up, and awaaaay!  You're walking on air!");
     } else if (Is_airlevel(&u.uz)) {
@@ -3506,7 +3507,7 @@ float_down(
     }
     if (u.uswallow) {
         You("float down, but you are still %s.",
-            is_animal(u.ustuck->data) ? "swallowed" : "engulfed");
+            digests(u.ustuck->data) ? "swallowed" : "engulfed");
         (void) encumber_msg();
         return 1;
     }
index 568f545177d50409986e627fc9c117c9bfbb1966..68c351ba9a092dd32c6ed1814602fb76f7497b6b 100644 (file)
@@ -4547,7 +4547,7 @@ gulpum(struct monst *mdef, struct attack *mattk)
                 if (DEADMONSTER(mdef)) /* not lifesaved */
                     return MM_DEF_DIED;
             }
-            You("%s %s!", is_animal(g.youmonst.data) ? "regurgitate" : "expel",
+            You("%s %s!", digests(g.youmonst.data) ? "regurgitate" : "expel",
                 mon_nam(mdef));
             if (Slow_digestion || is_animal(g.youmonst.data)) {
                 pline("Obviously, you didn't like %s taste.",
@@ -4559,7 +4559,10 @@ gulpum(struct monst *mdef, struct attack *mattk)
 }
 
 void
-missum(struct monst *mdef, struct attack *mattk, boolean wouldhavehit)
+missum(
+    struct monst *mdef,
+    struct attack *mattk,
+    boolean wouldhavehit)
 {
     if (wouldhavehit) /* monk is missing due to penalty for wearing suit */
         Your("armor is rather cumbersome...");
index e6f6c4d9dcfda18ec8df324f9ab010b93fc8c4ca..1900846fe2c8e7cd9cf1e06b90a44b5c7cdf2a69 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -490,7 +490,7 @@ release_hold(void)
     if (!mtmp) {
         impossible("release_hold when not held?");
     } else if (u.uswallow) { /* possible for sticky hero to be swallowed */
-        if (is_animal(mtmp->data)) {
+        if (digests(mtmp->data)) {
             if (!Blind)
                 pline("%s opens its mouth!", Monnam(mtmp));
             else