]> granicus.if.org Git - nethack/commitdiff
shapechanger polymorph bit
authorPatR <rankin@nethack.org>
Fri, 25 Mar 2016 23:49:01 +0000 (16:49 -0700)
committerPatR <rankin@nethack.org>
Fri, 25 Mar 2016 23:49:01 +0000 (16:49 -0700)
Rescuing an old revision from bit rot:  If one of fog clouds or
vampire bats has been genocided and you try to polymorph a vampire
disguised as the other, it won't change form because the shape it's
currently in is the only candidate shape left for vampshifting.
This makes shapechangers who fail to take on a new shape when
polymorphed try again, specifying original form on the second try.
It's unlikely to affect chameleons, but disguised vampires will
sometimes become undisguised instead of seeming to be immune from
polymorph.

src/mon.c
src/zap.c

index b0eec652ef7f2d99601c7bab70b59be86f44bdb6..b3e95eca69a02f6de7bbad61af1dfc14f3cdc624 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -3209,7 +3209,7 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
     int hpn, hpd;
     int mndx, tryct;
     struct permonst *olddata = mtmp->data;
-    char oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
+    char *p, oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
 
     /* Riders are immune to polymorph and green slime
        (but apparent Rider might actually be a doppelganger) */
@@ -3224,7 +3224,7 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
     }
     /* we need this one whether msg is true or not */
     Strcpy(l_oldname, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
-                (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE));
+                               has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE));
 
     /* mdat = 0 -> caller wants a random monster shape */
     if (mdat == 0) {
@@ -3247,23 +3247,18 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
     } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
         return 0; /* passed in mdat is genocided */
 
-    if (mdat == mtmp->data)
+    if (mdat == olddata)
         return 0; /* still the same monster */
 
     mgender_from_permonst(mtmp, mdat);
-
-    if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) {
-        /* mplayers start out as "Foo the Bar", but some of the
-         * titles are inappropriate when polymorphed, particularly
-         * into the opposite sex.  players don't use ranks when
-         * polymorphed, so dropping the rank for mplayers seems
-         * reasonable.
-         */
-        char *p = index(MNAME(mtmp), ' ');
-
-        if (p)
-            *p = '\0';
-    }
+    /* Endgame mplayers start out as "Foo the Bar", but some of the
+     * titles are inappropriate when polymorphed, particularly into
+     * the opposite sex.  Player characters don't use ranks when
+     * polymorphed, so dropping rank for mplayers seems reasonable.
+     */
+    if (In_endgame(&u.uz) && is_mplayer(olddata)
+        && has_mname(mtmp) && (p = strstr(MNAME(mtmp), " the ")) != 0)
+        *p = '\0';
 
     if (mtmp->wormno) { /* throw tail away */
         wormgone(mtmp);
index 854c62fad5789884d21c3e12aae97d1ee9b2085d..daa4d5ec6564d84bb8dbef0c7b30c4d474db9677 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -221,11 +221,17 @@ struct obj *otmp;
                it guard against involuntary polymorph attacks too... */
             shieldeff(mtmp->mx, mtmp->my);
         } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+            boolean polyspot = (otyp != POT_POLYMORPH),
+                    give_msg = (!Hallucination
+                                && (canseemon(mtmp)
+                                    || (u.uswallow && mtmp == u.ustuck)));
+
             /* dropped inventory (due to death by system shock,
                or loss of wielded weapon and/or worn armor due to
                limitations of new shape) won't be hit by this zap */
-            for (obj = mtmp->minvent; obj; obj = obj->nobj)
-                bypass_obj(obj);
+            if (polyspot)
+                for (obj = mtmp->minvent; obj; obj = obj->nobj)
+                    bypass_obj(obj);
             /* natural shapechangers aren't affected by system shock
                (unless protection from shapechangers is interfering
                with their metabolism...) */
@@ -238,8 +244,15 @@ struct obj *otmp;
                 /* no corpse after system shock */
                 xkilled(mtmp, 3);
             } else if (newcham(mtmp, (struct permonst *) 0,
-                               (otyp != POT_POLYMORPH), FALSE)) {
-                if (!Hallucination && canspotmon(mtmp))
+                               polyspot, give_msg) != 0
+                       /* if shapechange failed because there aren't
+                          enough eligible candidates (most likely for
+                          vampshifter), try reverting to original form */
+                       || (mtmp->cham >= LOW_PM
+                           && newcham(mtmp, &mons[mtmp->cham],
+                                      polyspot, give_msg) != 0)) {
+                if (give_msg && (canspotmon(mtmp)
+                                 || (u.uswallow && mtmp == u.ustuck)))
                     learn_it = TRUE;
             }
         }