]> granicus.if.org Git - nethack/commitdiff
fix #H4204 - shapeshifter taking vampire form
authorPatR <rankin@nethack.org>
Thu, 21 Jan 2016 10:12:47 +0000 (02:12 -0800)
committerPatR <rankin@nethack.org>
Thu, 21 Jan 2016 10:12:47 +0000 (02:12 -0800)
When a chameleon/doppelganger/sandestin took vampire or vampire lord
shape, it stopped taking on new shapes.  Vampire shapeshifting was
being applied to all vampires rather than just to is_vampshifter().
When is_vampshifter() is false, the vampire is some other shapeshifter
or Protection_from_shape_changers is in effect, so vampire shifting
doesn't apply.

While testing, I noticed that vampires/lords only turned into bats/
wolves during initial creation.  They did turn into fog clouds in
order to pass closed doors but the other alternate forms were ignored.
That's fixed too.

doc/fixes36.1
src/mon.c
src/monmove.c

index a719cdd0ef98a542d1e4fe8810c38df19b2e109d..bb35edd09eef91bc6e24100b1f53410523961ffd 100644 (file)
@@ -120,6 +120,7 @@ fix floor descriptions on the Planes when levitating
 fix warning glyph description when monster symbol coincided the warning symbol
 allow the same color names for status hilites and menucolors
 override MSGTYPE=norep while executing the ':' command
+if a chameleon took vampire form, it would stop periodically changing shape
 
 
 Platform- and/or Interface-Specific Fixes
index 802d20bffbec0612ea8a1282ae7d7f18299d71e6..8080fd044529e8fa96a518133c11a7c5554a139d 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mon.c   $NHDT-Date: 1451664800 2016/01/01 16:13:20 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.203 $ */
+/* NetHack 3.6 mon.c   $NHDT-Date: 1453371163 2016/01/21 10:12:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.208 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -588,12 +588,10 @@ mcalcdistress()
         mon_regen(mtmp, FALSE);
 
         /* possibly polymorph shapechangers and lycanthropes */
-        if (mtmp->cham >= LOW_PM) {
-            if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
-                decide_to_shapeshift(mtmp, 0);
-            else if (!rn2(6))
-                (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
-        }
+        if (mtmp->cham >= LOW_PM)
+            decide_to_shapeshift(mtmp, (canspotmon(mtmp)
+                                        || (u.uswallow && mtmp == u.ustuck))
+                                          ? SHIFT_MSG : 0);
         were_change(mtmp);
 
         /* gradually time out temporary problems */
@@ -2859,30 +2857,39 @@ int shiftflags;
         || ((shiftflags & SHIFT_SEENMSG) && sensemon(mon)))
         msg = TRUE;
 
-    if (is_vampshifter(mon)) {
+    if (!is_vampshifter(mon)) {
+        /* regular shapeshifter */
+        if (!rn2(6))
+            (void) newcham(mon, (struct permonst *) 0, FALSE, msg);
+    } else {
         /* The vampire has to be in good health (mhp) to maintain
          * its shifted form.
-             *
+         *
          * If we're shifted and getting low on hp, maybe shift back.
          * If we're not already shifted and in good health, maybe shift.
          */
-        if ((mon->mhp <= mon->mhpmax / 6) && rn2(4) && (mon->cham >= LOW_PM))
-            (void) newcham(mon, &mons[mon->cham], FALSE, msg);
-    } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM && !rn2(6)
-               && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
-        (void) newcham(mon, (struct permonst *) 0, FALSE, msg);
+        if (mon->data->mlet != S_VAMPIRE) {
+            if ((mon->mhp <= (mon->mhpmax + 5) / 6) && rn2(4)
+                && mon->cham >= LOW_PM)
+                (void) newcham(mon, &mons[mon->cham], FALSE, msg);
+        } else {
+            if (mon->mhp >= 9 * mon->mhpmax / 10 && !rn2(6)
+                && (!canseemon(mon)
+                    || distu(mon->mx, mon->my) > BOLT_LIM * BOLT_LIM))
+                (void) newcham(mon, (struct permonst *) 0, FALSE, msg);
+        }
+        /* override the 10% chance for sex change */
+        ptr = mon->data;
+        if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
+            mon->female = was_female;
     }
-    /* override the 10% chance for sex change */
-    ptr = mon->data;
-    if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
-        mon->female = was_female;
 }
 
 STATIC_OVL int
 pickvampshape(mon)
 struct monst *mon;
 {
-    int mndx = mon->cham;
+    int mndx = mon->cham, wolfchance = 10;
     /* avoid picking monsters with lowercase display symbols ('d' for wolf
        and 'v' for fog cloud) on rogue level*/
     boolean uppercase_only = Is_rogue_level(&u.uz);
@@ -2892,9 +2899,10 @@ struct monst *mon;
         /* ensure Vlad can keep carrying the Candelabrum */
         if (mon_has_special(mon))
             break; /* leave mndx as is */
+        wolfchance = 3;
     /*FALLTHRU*/
     case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */
-        if (!rn2(10) && !uppercase_only) {
+        if (!rn2(wolfchance) && !uppercase_only) {
             mndx = PM_WOLF;
             break;
         }
@@ -3045,13 +3053,17 @@ struct monst *mon;
       }
         break;
     }
+
     /* for debugging: allow control of polymorphed monster */
     if (wizard && iflags.mon_polycontrol) {
         char pprompt[BUFSZ], buf[BUFSZ];
         int monclass;
 
-        Sprintf(pprompt, "Change %s @ <%d,%d> into what kind of monster?",
-                noit_mon_nam(mon), (int) mon->mx, (int) mon->my);
+        Sprintf(pprompt, "Change %s @ %s into what kind of monster?",
+                noit_mon_nam(mon),
+                coord_desc((int) mon->mx, (int) mon->my, buf,
+                           (iflags.getpos_coords != GPCOORDS_NONE)
+                              ? iflags.getpos_coords : GPCOORDS_MAP));
         tryct = 5;
         do {
             monclass = 0;
@@ -3274,9 +3286,10 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
 
                     /* Do this even if msg is FALSE */
                     You("%s %s%s!",
-                        (amorphous(olddata) || is_whirly(olddata)) ?
-                            "emerge from" : "break out of",
+                        (amorphous(olddata) || is_whirly(olddata))
+                            "emerge from" : "break out of",
                         l_oldname, msgtrail);
+                    msg = FALSE; /* message has been given */
                     mtmp->mhp = 1; /* almost dead */
                 }
                 expels(mtmp, olddata, FALSE);
index 86432a6c5e6c417bb262476bfae48ecc458c4b82..55892716436f1910fa1dab21269171f434181503 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 monmove.c       $NHDT-Date: 1451866935 2016/01/04 00:22:15 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
+/* NetHack 3.6 monmove.c       $NHDT-Date: 1453371163 2016/01/21 10:12:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.83 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1023,9 +1023,7 @@ not_special:
         flag |= ALLOW_DIG;
     if (is_human(ptr) || ptr == &mons[PM_MINOTAUR])
         flag |= ALLOW_SSM;
-    if (is_undead(ptr) && ptr->mlet != S_GHOST)
-        flag |= NOGARLIC;
-    if (is_vampshifter(mtmp))
+    if ((is_undead(ptr) && ptr->mlet != S_GHOST) || is_vampshifter(mtmp))
         flag |= NOGARLIC;
     if (throws_rocks(ptr))
         flag |= ALLOW_ROCK;
@@ -1215,10 +1213,11 @@ postmov:
                 boolean btrapped = (here->doormask & D_TRAPPED),
                         observeit = canseeit && canspotmon(mtmp);
 
-                if (here->doormask & (D_LOCKED | D_CLOSED)
+                if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
                     && (amorphous(ptr)
-                        || (!amorphous(ptr) && can_fog(mtmp)
-                            && vamp_shift(mtmp, &mons[PM_FOG_CLOUD],canspotmon(mtmp))))) {
+                        || (can_fog(mtmp)
+                            && vamp_shift(mtmp, &mons[PM_FOG_CLOUD],
+                                          canspotmon(mtmp))))) {
                     if (flags.verbose && canseemon(mtmp))
                         pline("%s %s under the door.", Monnam(mtmp),
                               (ptr == &mons[PM_FOG_CLOUD]
@@ -1581,7 +1580,7 @@ boolean
 can_fog(mtmp)
 struct monst *mtmp;
 {
-    if ((is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
+    if (!(mvitals[PM_FOG_CLOUD].mvflags & G_GENOD) && is_vampshifter(mtmp)
         && !Protection_from_shape_changers && !stuff_prevents_passage(mtmp))
         return TRUE;
     return FALSE;
@@ -1601,12 +1600,11 @@ boolean domsg;
                 sensemon(mon) ? "now detect" : "observe",
                 an(m_monnam(mon)));
     }
-    if (mon->cham >= LOW_PM) {
-        if (ptr == &mons[mon->cham])
-            mon->cham = NON_PM;
-        reslt = newcham(mon, ptr, FALSE, FALSE);
-    } else if (mon->cham == NON_PM && ptr != mon->data) {
-        mon->cham = monsndx(mon->data);
+    if (mon->data == ptr) {
+        /* already right shape */
+        reslt = 1;
+        domsg = FALSE;
+    } else if (is_vampshifter(mon)) {
         reslt = newcham(mon, ptr, FALSE, FALSE);
     }
     if (reslt && domsg) {