]> granicus.if.org Git - nethack/commitdiff
fix #K2617 - metallivores eating iron bars
authorPatR <rankin@nethack.org>
Sat, 24 Oct 2020 02:43:10 +0000 (19:43 -0700)
committerPatR <rankin@nethack.org>
Sat, 24 Oct 2020 02:43:10 +0000 (19:43 -0700)
Monsters with rust attacks (rust monster) and corrosion attacks
(black pudding, gray ooze) can eat or otherwise destroy iron bars
but xorns could only move through the iron bars spot without being
able to eat the metal there.  Change xorn to eat bars instead of
phazing through them.  Lets rock moles eat bars too.

Hero polymorphed into a rust monster would eat bars if trying to
move to their location but couldn't do so if already there (maybe
was in xorn form and now in rust monster form).  Xorns could pass
through them but not eat them.  Allow hero metallivores to eat
bars at the current location via 'e', similar to eating food off
the floor.  Hero as rock mole behaves like rust monster.

doc/fixes37.0
include/extern.h
src/eat.c
src/hack.c
src/mondata.c
src/monmove.c

index 163b1c38fc56f4360d06c03a85964042cc1669a0..711d612e74dd80a39f4987054a256a114e785e9b 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.332 $ $NHDT-Date: 1602958104 2020/10/17 18:08:24 $
+NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.337 $ $NHDT-Date: 1603507384 2020/10/24 02:43:04 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -280,6 +280,12 @@ when reporting that hero can't repair a chest's broken lock with key/pick/card
 pre-populate teleport destination prompt with travel destination
 ghosts cannot be renamed
 tossed upwards objects got two times half physical damage reduction
+monster xorns could pass through iron bars but not eat them; monster rock
+       moles could no neither; now they can eat bars when adjacent and will
+       do so if the bars are blocking their path
+hero poly'd into rust monster could implicitly eat bars when adjacent by
+       trying to move there, now when in rock mole form too; in xorn form
+       can explicitly eat them via 'e' after moving onto their spot
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index a8151c0343166cd1a65923d04adb780837560d7a..e24e605b6e3f33df5f1c6675edff86bbe887bf16 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 extern.h        $NHDT-Date: 1602270114 2020/10/09 19:01:54 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.867 $ */
+/* NetHack 3.7 extern.h        $NHDT-Date: 1603507384 2020/10/24 02:43:04 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.873 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -874,6 +874,7 @@ E anything *FDECL(long_to_any, (long));
 E anything *FDECL(monst_to_any, (struct monst *));
 E anything *FDECL(obj_to_any, (struct obj *));
 E boolean FDECL(revive_nasty, (int, int, const char *));
+E int FDECL(still_chewing, (XCHAR_P, XCHAR_P));
 E void FDECL(movobj, (struct obj *, XCHAR_P, XCHAR_P));
 E boolean FDECL(may_dig, (XCHAR_P, XCHAR_P));
 E boolean FDECL(may_passwall, (XCHAR_P, XCHAR_P));
index ffc36dd256eede3330ebd977092cac4c94661643..f73c4d1d5c48cdc7db138027b4c7d81f485470a3 100644 (file)
--- a/src/eat.c
+++ b/src/eat.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 eat.c   $NHDT-Date: 1599258557 2020/09/04 22:29:17 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.233 $ */
+/* NetHack 3.7 eat.c   $NHDT-Date: 1603507384 2020/10/24 02:43:04 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.235 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1449,7 +1449,8 @@ opentin(VOID_ARGS)
 {
     /* perhaps it was stolen (although that should cause interruption) */
     if (!carried(g.context.tin.tin)
-        && (!obj_here(g.context.tin.tin, u.ux, u.uy) || !can_reach_floor(TRUE)))
+        && (!obj_here(g.context.tin.tin, u.ux, u.uy)
+            || !can_reach_floor(TRUE)))
         return 0; /* %% probably we should use tinoid */
     if (g.context.tin.usedtime++ >= 50) {
         You("give up your attempt to open the tin.");
@@ -2488,6 +2489,18 @@ doeat()
         }
     }
 
+    /* from floorfood(), &zeroobj means iron bars at current spot */
+    if (otmp == &cg.zeroobj) {
+        /* hero in metallivore form is eating [diggable] iron bars
+           at current location so skip the other assorted checks;
+           operates as if digging rather than via the eat occupation */
+        if (still_chewing(u.ux, u.uy) && levl[u.ux][u.uy].typ == IRONBARS) {
+            /* this is verbose, but player will see the hero rather than the
+               bars so wouldn't know that more turns of eating are required */
+            You("pause to swallow.");
+        }
+        return 1;
+    }
     /* We have to make non-foods take 1 move to eat, unless we want to
      * do ridiculous amounts of coding to deal with partly eaten plate
      * mails, players who polymorph back to human in the middle of their
@@ -3156,18 +3169,18 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */
     register struct obj *otmp;
     char qbuf[QBUFSZ];
     char c;
-    boolean feeding = !strcmp(verb, "eat"),    /* corpsecheck==0 */
-        offering = !strcmp(verb, "sacrifice"); /* corpsecheck==1 */
+    struct permonst *uptr = g.youmonst.data;
+    boolean feeding = !strcmp(verb, "eat"),        /* corpsecheck==0 */
+            offering = !strcmp(verb, "sacrifice"); /* corpsecheck==1 */
 
     /* if we can't touch floor objects then use invent food only */
     if (iflags.menu_requested /* command was preceded by 'm' prefix */
         || !can_reach_floor(TRUE) || (feeding && u.usteed)
         || (is_pool_or_lava(u.ux, u.uy)
-            && (Wwalking || is_clinger(g.youmonst.data)
-                || (Flying && !Breathless))))
+            && (Wwalking || is_clinger(uptr) || (Flying && !Breathless))))
         goto skipfloor;
 
-    if (feeding && metallivorous(g.youmonst.data)) {
+    if (feeding && metallivorous(uptr)) {
         struct obj *gold;
         struct trap *ttmp = t_at(u.ux, u.uy);
 
@@ -3188,8 +3201,30 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */
                 return (struct obj *) 0;
             }
         }
+        if (levl[u.ux][u.uy].typ == IRONBARS) {
+            /* already verified that hero is metallivorous above */
+            boolean nodig = (levl[u.ux][u.uy].wall_info & W_NONDIGGABLE) != 0;
 
-        if (g.youmonst.data != &mons[PM_RUST_MONSTER]
+            c = 'n';
+            Strcpy(qbuf, "There are iron bars here");
+            if (nodig || u.uhunger > 1500) {
+                pline("%s but you %s eat them.", qbuf,
+                      nodig ? "cannot" : "are too full to");
+            } else {
+                Strcat(qbuf, ((!g.context.digging.chew
+                               || g.context.digging.pos.x != u.ux
+                               || g.context.digging.pos.y != u.uy
+                               || !on_level(&g.context.digging.level, &u.uz))
+                              ? "; eat them?"
+                              : "; resume eating them?"));
+                c = yn_function(qbuf, ynqchars, 'n');
+            }
+            if (c == 'y')
+                return (struct obj *) &cg.zeroobj; /* csst away 'const' */
+            else if (c == 'q')
+                return (struct obj *) 0;
+        }
+        if (uptr != &mons[PM_RUST_MONSTER]
             && (gold = g_at(u.ux, u.uy)) != 0) {
             if (gold->quan == 1L)
                 Sprintf(qbuf, "There is 1 gold piece here; eat it?");
index 941643a1209f3d8378ce1ef308e9104af306f688..0e8efb024fea65a1911f5d4012f310ce7a91b2ce 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 hack.c  $NHDT-Date: 1600469617 2020/09/18 22:53:37 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.268 $ */
+/* NetHack 3.7 hack.c  $NHDT-Date: 1603507385 2020/10/24 02:43:05 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.269 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -9,7 +9,6 @@
 
 static void NDECL(maybe_wail);
 static int NDECL(moverock);
-static int FDECL(still_chewing, (XCHAR_P, XCHAR_P));
 static void NDECL(dosinkfall);
 static boolean FDECL(findtravelpath, (int));
 static boolean FDECL(trapmove, (int, int, struct trap *));
@@ -394,7 +393,7 @@ moverock()
  *  Chew on a wall, door, or boulder.  [What about statues?]
  *  Returns TRUE if still eating, FALSE when done.
  */
-static int
+int
 still_chewing(x, y)
 xchar x, y;
 {
@@ -418,7 +417,15 @@ xchar x, y;
                     : "hard stone");
         nomul(0);
         return 1;
-    } else if (g.context.digging.pos.x != x || g.context.digging.pos.y != y
+    } else if (lev->typ == IRONBARS
+               && metallivorous(g.youmonst.data) && u.uhunger > 1500) {
+        /* finishing eating via 'morehungry()' doesn't handle choking */
+        You("are too full to eat the bars.");
+        nomul(0);
+        return 1;
+    } else if (!g.context.digging.chew
+               || g.context.digging.pos.x != x
+               || g.context.digging.pos.y != y
                || !on_level(&g.context.digging.level, &u.uz)) {
         g.context.digging.down = FALSE;
         g.context.digging.chew = TRUE;
@@ -504,7 +511,20 @@ xchar x, y;
         digtxt = "chew through the tree.";
         lev->typ = ROOM;
     } else if (lev->typ == IRONBARS) {
-        digtxt = "eat through the bars.";
+        if (metallivorous(g.youmonst.data)) { /* should always be True here */
+            /* arbitrary amount; unlike proper eating, nutrition is
+               bestowed in a lump sum at the end */
+            int nut = (int) objects[HEAVY_IRON_BALL].oc_weight;
+
+            /* lesshungry() requires that victual be set up, so skip it;
+               morehungry() of a negative amount will increase nutrition
+               without any possibility of choking to death on the meal;
+               updates hunger state and requests status update if changed */
+            morehungry(-nut);
+        }
+        digtxt = (x == u.ux && y == u.uy)
+                 ? "devour the iron bars."
+                 : "eat through the bars.";
         dissolve_bars(x, y);
     } else if (lev->typ == SDOOR) {
         if (lev->doormask & D_TRAPPED) {
@@ -745,8 +765,10 @@ int mode;
                 pline("There is an obstacle there.");
             return FALSE;
         } else if (tmpr->typ == IRONBARS) {
-            if ((dmgtype(g.youmonst.data, AD_RUST)
-                 || dmgtype(g.youmonst.data, AD_CORR)) && mode == DO_MOVE
+            if (mode == DO_MOVE
+                && (dmgtype(g.youmonst.data, AD_RUST)
+                    || dmgtype(g.youmonst.data, AD_CORR)
+                    || metallivorous(g.youmonst.data))
                 && still_chewing(x, y)) {
                 return FALSE;
             }
index 497beef069585c8aa0da4ac097f119d9f81c10b4..5ccc48bb31d125196c38896777065133019ee58f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 mondata.c       $NHDT-Date: 1596498186 2020/08/03 23:43:06 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.83 $ */
+/* NetHack 3.7 mondata.c       $NHDT-Date: 1603507386 2020/10/24 02:43:06 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.86 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -334,7 +334,10 @@ struct permonst *mptr;
 {
     return (boolean) (passes_walls(mptr) || amorphous(mptr) || unsolid(mptr)
                       || is_whirly(mptr) || verysmall(mptr)
-                      || dmgtype(mptr, AD_CORR) || dmgtype(mptr, AD_RUST)
+                      /* rust monsters and some puddings can destroy bars */
+                      || dmgtype(mptr, AD_RUST) || dmgtype(mptr, AD_CORR)
+                      /* rock moles can eat bars */
+                      || metallivorous(mptr)
                       || (slithy(mptr) && !bigmonst(mptr)));
 }
 
index b367096e81cc0673c8a7107014afb010c419caa9..00986f4fb35540241b70e0b174da17f0389c01be 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 monmove.c       $NHDT-Date: 1600469618 2020/09/18 22:53:38 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.143 $ */
+/* NetHack 3.7 monmove.c       $NHDT-Date: 1603507386 2020/10/24 02:43:06 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.146 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1477,9 +1477,12 @@ register int after;
                         add_damage(mtmp->mx, mtmp->my, 0L);
                 }
             } else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
-                /* 3.6.2: was using may_dig() but it doesn't handle bars */
+                /* 3.6.2: was using may_dig() but that doesn't handle bars;
+                   AD_RUST catches rust monsters but metallivorous() is
+                   needed for xorns and rock moles */
                 if (!(levl[mtmp->mx][mtmp->my].wall_info & W_NONDIGGABLE)
-                    && (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR))) {
+                    && (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR)
+                        || metallivorous(ptr))) {
                     if (canseemon(mtmp))
                         pline("%s eats through the iron bars.", Monnam(mtmp));
                     dissolve_bars(mtmp->mx, mtmp->my);
@@ -1631,6 +1634,8 @@ register int x, y;
     levl[x][y].typ = (Is_special(&u.uz) || *in_rooms(x, y, 0)) ? ROOM : CORR;
     levl[x][y].flags = 0;
     newsym(x, y);
+    if (x == u.ux && y == u.uy)
+        switch_terrain();
 }
 
 boolean