]> granicus.if.org Git - nethack/commitdiff
fix #K3422 - mimic remains as 'strange object'
authorPatR <rankin@nethack.org>
Tue, 24 Aug 2021 15:09:30 +0000 (08:09 -0700)
committerPatR <rankin@nethack.org>
Tue, 24 Aug 2021 15:09:30 +0000 (08:09 -0700)
even when protection from shape changers is in effect.  I'm not sure
why mimicking other things doesn't trigger the same sanity check
warning.  This fix works for the strange object case and I assume
that it doesn't break the more general case.

When investigating, I noticed that save and restore (even leaving
the level and then returning) causes cancelled shape changers to be
uncancelled.  Treat being cancelled similarly to having to having
protection from shape changers in effect:  shape changer is forced
to revert to its innate form and not allowed to change shape.

doc/fixes37.0
include/extern.h
src/mon.c
src/zap.c

index 8a1149ca06b813a3c55864401104358ed8ae8bef..1e2790bf1217a02fe0d4fdc92ed7080a02b0da6b 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.615 $ $NHDT-Date: 1627951429 2021/08/03 00:43:49 $
+NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.629 $ $NHDT-Date: 1629817676 2021/08/24 15:07:56 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -590,6 +590,10 @@ in wizard mode, polymorphing into hero's role monster in order to revert to
        normal play because role monsters are invalid polymorph targets there]
 revise a 3.6.1 fix: if a spellbook which is being read becomes cursed, always
        stop reading: "The <book> slams shut!" and set book->bknown
+concealed mimic could trigger sanity check warning "mimic concealed as an
+       object despite Prot-from-shape-changers" if hidden as "strange object"
+cancelled shape changer would become uncancelled if saved and restored (even
+       just leaving its level and then returning)
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 88a42725af88c0bcd5ed9865e5b15974a82d47e2..0a6eb66bf4f294b0798640893295464ff2b7221b 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 extern.h        $NHDT-Date: 1624322857 2021/06/22 00:47:37 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.985 $ */
+/* NetHack 3.7 extern.h        $NHDT-Date: 1629817676 2021/08/24 15:07:56 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.998 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1452,6 +1452,7 @@ extern void wakeup(struct monst *, boolean);
 extern void wake_nearby(void);
 extern void wake_nearto(int, int, int);
 extern void seemimic(struct monst *);
+extern void normal_shape(struct monst *mon);
 extern void rescham(void);
 extern void restartcham(void);
 extern void restore_cham(struct monst *);
index 1122385c0f9713e6cf1fbad823542f3f1a05ae55..5af2a429d2f3f24da1c1da9a67fe959d008e8a49 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 mon.c   $NHDT-Date: 1627413528 2021/07/27 19:18:48 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.382 $ */
+/* NetHack 3.7 mon.c   $NHDT-Date: 1629817677 2021/08/24 15:07:57 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.384 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -3644,41 +3644,58 @@ seemimic(register struct monst* mtmp)
     newsym(mtmp->mx, mtmp->my);
 }
 
-/* force all chameleons to become normal */
+/* [taken out of rescham() in order to be shared by restore_cham()] */
+void
+normal_shape(struct monst *mon)
+{
+    int mcham = (int) mon->cham;
+
+    if (mcham >= LOW_PM) {
+        unsigned mcan = mon->mcan;
+
+        (void) newcham(mon, &mons[mcham], FALSE, FALSE);
+        mon->cham = NON_PM;
+        /* newcham() may uncancel a polymorphing monster; override that */
+        if (mcan)
+            mon->mcan = 1;
+        newsym(mon->mx, mon->my);
+    }
+    if (is_were(mon->data) && mon->data->mlet != S_HUMAN) {
+        new_were(mon);
+    }
+    if (M_AP_TYPE(mon) != M_AP_NOTHING) {
+        /* this used to include a cansee() check but Protection_from_
+           _shape_changers shouldn't be trumped by being unseen */
+        if (!mon->meating) {
+            /* make revealed mimic fall asleep in lieu of shape change */
+            if (M_AP_TYPE(mon) != M_AP_MONSTER)
+                mon->msleeping = 1;
+            seemimic(mon);
+        } else {
+            /* quickmimic: pet is midst of eating a mimic corpse;
+               this terminates the meal early */
+            finish_meating(mon);
+        }
+    }
+}
+
+/* force all chameleons and mimics to become themselves and werecreatures
+   to revert to human form; called when Protection_from_shape_changers gets
+   activated via wearing or eating ring */
 void
 rescham(void)
 {
     register struct monst *mtmp;
-    int mcham;
 
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue;
-        mcham = (int) mtmp->cham;
-        if (mcham >= LOW_PM) {
-            (void) newcham(mtmp, &mons[mcham], FALSE, FALSE);
-            mtmp->cham = NON_PM;
-        }
-        if (is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
-            new_were(mtmp);
-        if (M_AP_TYPE(mtmp) != M_AP_NOTHING) {
-            /* this used to include a cansee() check but Protection_from_
-               _shape_changers shouldn't be trumped by being unseen */
-            if (!mtmp->meating) {
-                /* make revealed mimic fall asleep in lieu of shape change */
-                if (M_AP_TYPE(mtmp) != M_AP_MONSTER)
-                    mtmp->msleeping = 1;
-                seemimic(mtmp);
-            } else {
-                /* quickmimic: pet is midst of eating a mimic corpse;
-                   this terminates the meal early */
-                finish_meating(mtmp);
-            }
-        }
+        normal_shape(mtmp);
     }
 }
 
-/* Let the chameleons change again -dgk */
+/* let chameleons change and mimics hide again; called when taking off
+   ring of protection from shape changers */
 void
 restartcham(void)
 {
@@ -3689,8 +3706,7 @@ restartcham(void)
             continue;
         if (!mtmp->mcan)
             mtmp->cham = pm_to_cham(monsndx(mtmp->data));
-        if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping
-            && cansee(mtmp->mx, mtmp->my)) {
+        if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping) {
             set_mimic_sym(mtmp);
             newsym(mtmp->mx, mtmp->my);
         }
@@ -3701,26 +3717,20 @@ restartcham(void)
    against shape-changing might be different now than it was at the
    time the level was saved. */
 void
-restore_cham(struct monstmon)
+restore_cham(struct monst *mon)
 {
-    int mcham;
-
-    if (Protection_from_shape_changers) {
-        mcham = (int) mon->cham;
-        if (mcham >= LOW_PM) {
-            mon->cham = NON_PM;
-            (void) newcham(mon, &mons[mcham], FALSE, FALSE);
-        } else if (is_were(mon->data) && !is_human(mon->data)) {
-            new_were(mon);
-        }
+    if (Protection_from_shape_changers || mon->mcan) {
+        /* force chameleon or mimic to revert to its natural shape */
+        normal_shape(mon);
     } else if (mon->cham == NON_PM) {
+        /* chameleon doesn't change shape here, just gets allowed to do so */
         mon->cham = pm_to_cham(monsndx(mon->data));
     }
 }
 
 /* unwatched hiders may hide again; if so, returns True */
 static boolean
-restrap(struct monstmtmp)
+restrap(struct monst *mtmp)
 {
     struct trap *t;
 
index 0bf4d06db12e8cc0850d2836bcf4f04ce44f49ac..bc57fb7b6dc85761bab2706ee98fcd692d3f9f31 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 zap.c   $NHDT-Date: 1626390628 2021/07/15 23:10:28 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.369 $ */
+/* NetHack 3.7 zap.c   $NHDT-Date: 1629817679 2021/08/24 15:07:59 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.372 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -2898,19 +2898,8 @@ cancel_monst(struct monst *mdef, struct obj *obj, boolean youattack,
         }
     } else {
         mdef->mcan = 1;
-        /* force shapeshifter into its base form */
-        if (M_AP_TYPE(mdef) != M_AP_NOTHING)
-            seemimic(mdef);
-        /* [not 'else if'; chameleon might have been hiding as a mimic] */
-        if (mdef->cham >= LOW_PM) {
-            /* note: newcham() uncancels shapechangers (resets m->mcan
-               to 0), but only for shapechangers whose m->cham is already
-               NON_PM and we just verified that it's LOW_PM or higher */
-            newcham(mdef, &mons[mdef->cham], FALSE, FALSE);
-            mdef->cham = NON_PM; /* cancelled shapeshifter can't shift */
-        }
-        if (is_were(mdef->data) && !is_human(mdef->data))
-            were_change(mdef);
+        /* force shapeshifter into its base form or mimic to unhide */
+        normal_shape(mdef);
 
         if (mdef->data == &mons[PM_CLAY_GOLEM]) {
             if (canseemon(mdef))