]> granicus.if.org Git - nethack/commitdiff
chameleon behaviour
authornethack.allison <nethack.allison>
Sun, 12 Mar 2006 04:43:28 +0000 (04:43 +0000)
committernethack.allison <nethack.allison>
Sun, 12 Mar 2006 04:43:28 +0000 (04:43 +0000)
- restore intended behaviour of kill_genocided_monsters().
  It has been incorrect since  the chameleon overhaul in June 2004.
- eliminate CHAM_ORDINARY and use NON_PM instead.

15 files changed:
include/monst.h
include/obj.h
src/dogmove.c
src/makemon.c
src/mhitm.c
src/mhitu.c
src/minion.c
src/mon.c
src/monmove.c
src/monst.c
src/muse.c
src/pline.c
src/read.c
src/trap.c
src/zap.c

index c25344dfb8a9991d62c2283a039aca48dc0ce6d8..b46598dd0574e603a3ea1a6a7131a876d0c66a1e 100644 (file)
@@ -43,7 +43,6 @@ struct monst {
        unsigned m_id;
        short mnum;             /* permanent monster index number */
        short cham;             /* if shapeshifter, orig mons[] idx goes here */
-#define CHAM_ORDINARY  0       /* not a shapechanger */
        short movement;         /* movement points (derived from permonst definition and added effects */
        uchar m_lev;            /* adjusted difficulty level of monster */
        aligntyp malign;        /* alignment of this monster, relative to the
index 355b165563b182cbad24454408189891963a7dac..32b3e0aaeedd36ea17f98b6afbb05899536d8902 100644 (file)
@@ -210,8 +210,7 @@ struct obj {
 #define MAX_EGG_HATCH_TIME 200 /* longest an egg can remain unhatched */
 #define stale_egg(egg) ((monstermoves - (egg)->age) > (2*MAX_EGG_HATCH_TIME))
 #define ofood(o) ((o)->otyp == CORPSE || (o)->otyp == EGG || (o)->otyp == TIN)
-#define polyfodder(obj) (ofood(obj) && \
-                        pm_to_cham((obj)->corpsenm) != CHAM_ORDINARY)
+#define polyfodder(obj) (ofood(obj) && pm_to_cham((obj)->corpsenm) != NON_PM)
 #define mlevelgain(obj) (ofood(obj) && (obj)->corpsenm == PM_WRAITH)
 #define mhealup(obj)   (ofood(obj) && (obj)->corpsenm == PM_NURSE)
 
index 3675736a015dfc86b3e6a885dbd0eed76cb44628..88224d431804910237e6bc35b217b35942c7ddb0 100644 (file)
@@ -979,7 +979,7 @@ finish_meating(mtmp)
 struct monst *mtmp;
 {
        mtmp->meating = 0;
-       if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == CHAM_ORDINARY) {
+       if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == NON_PM) {
                /* was eating a mimic and now appearance needs resetting */
                mtmp->m_ap_type = 0;
                mtmp->mappearance = 0;
index 8efc35bfdebe2457ec4145a2fa564e820c73d684..6984d593eb3062e818048b5722b0a31d3168cacd 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)makemon.c  3.5     2005/11/02      */
+/*     SCCS Id: @(#)makemon.c  3.5     2006/03/11      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1030,11 +1030,11 @@ register int    mmflags;
 
        if (mndx == PM_VLAD_THE_IMPALER)
                mitem = CANDELABRUM_OF_INVOCATION;
-       mtmp->cham = CHAM_ORDINARY;     /* default is "not a shapechanger" */
-       if ((mcham = pm_to_cham(mndx)) != CHAM_ORDINARY) {
+       mtmp->cham = NON_PM;    /* default is "not a shapechanger" */
+       if ((mcham = pm_to_cham(mndx)) != NON_PM) {
                /* this is a shapechanger after all */
                if (Protection_from_shape_changers) {
-                       ;       /* stuck in its natural form (CHAM_ORDINARY) */
+                       ;       /* stuck in its natural form (NON_PM) */
                } else {
                        /* General shapechangers start out with random form
                           (this explicitly picks something from the normal
index dc8a050c1e7035b7c96982292a051b27c81677bd..eaf960866b130cdf57f984f226397bd8755a9646 100644 (file)
@@ -1237,7 +1237,7 @@ mdamagem(magr, mdef, mattk)
            if (mattk->adtyp == AD_DGST) {
                /* various checks similar to dog_eat and meatobj.
                 * after monkilled() to provide better message ordering */
-               if (mdef->cham != CHAM_ORDINARY) {
+               if (mdef->cham >= LOW_PM) {
                    (void) newcham(magr, (struct permonst *)0, FALSE, TRUE);
                } else if (mdef->data == &mons[PM_GREEN_SLIME]) {
                    (void) newcham(magr, &mons[PM_GREEN_SLIME], FALSE, TRUE);
index 2e4d96df1c8c6707d99e3579af9d3acac2a04551..32d4e9d3a74e021fa28002697cc648661ce58270 100644 (file)
@@ -469,14 +469,14 @@ mattacku(mtmp)
        }
 
 /*     Special demon handling code */
-       if((mtmp->cham == CHAM_ORDINARY) && is_demon(mdat) && !range2
+       if((mtmp->cham == NON_PM) && is_demon(mdat) && !range2
           && mtmp->data != &mons[PM_BALROG]
           && mtmp->data != &mons[PM_SUCCUBUS]
           && mtmp->data != &mons[PM_INCUBUS])
            if (!mtmp->mcan && !rn2(13)) (void)msummon(mtmp);
 
 /*     Special lycanthrope handling code */
-       if((mtmp->cham == CHAM_ORDINARY) && is_were(mdat) && !range2) {
+       if((mtmp->cham == NON_PM) && is_were(mdat) && !range2) {
 
            if(is_human(mdat)) {
                if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
index 07b125b37837998931c93e6f9d68d595b6db933a..6fd9d26b6b029155bdca2d56ac65cdc099ed776e 100644 (file)
@@ -169,7 +169,7 @@ boolean talk;
     }
 }
 
-#define Athome (Inhell && (mtmp->cham == CHAM_ORDINARY))
+#define Athome (Inhell && (mtmp->cham == NON_PM))
 
 int
 demon_talk(mtmp)               /* returns 1 if it won't attack. */
index 91bb3e81c2c73767bf02a2040030cadbb05f685b..dafaee257c02f0e99c42e808722424814100e28d 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -119,18 +119,18 @@ int mndx, mode;
        return mndx;
 }
 
-/* return monster index if chameleon, or CHAM_ORDINARY if not */
+/* return monster index if chameleon, or NON_PM if not */
 int
 pm_to_cham(mndx)
 int mndx;
 {
-       int mcham = CHAM_ORDINARY;
+       int mcham = NON_PM;
 
        /*
         * As of 3.5.0 we just check M2_SHAPESHIFTER instead of having a
         * big switch statement with hardcoded shapeshifter types here.
         */
-       if (mndx > LOW_PM && is_shapeshifter(&mons[mndx])) mcham = mndx;
+       if (mndx >= LOW_PM && is_shapeshifter(&mons[mndx])) mcham = mndx;
        return mcham;
 }
 
@@ -529,7 +529,7 @@ mcalcdistress()
        mon_regen(mtmp, FALSE);
 
        /* possibly polymorph shapechangers and lycanthropes */
-       if (mtmp->cham != CHAM_ORDINARY) {
+       if (mtmp->cham >= LOW_PM) {
            if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
                decide_to_shapeshift(mtmp,0);
            else if (!rn2(6))
@@ -1470,7 +1470,7 @@ register struct monst *mtmp;
                int mndx = mtmp->cham;
                int x = mtmp->mx, y = mtmp->my;
                /* this only happens if shapeshifted */
-               if (mndx != CHAM_ORDINARY && mndx != monsndx(mtmp->data)) {
+               if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
                        char buf[BUFSZ];
                        boolean in_door = amorphous(mtmp->data) &&
                                         closed_door(mtmp->mx,mtmp->my);
@@ -1502,7 +1502,7 @@ register struct monst *mtmp;
                        }
                        newcham(mtmp, &mons[mndx], FALSE, FALSE);
                        if (mtmp->data == &mons[mndx])
-                               mtmp->cham = CHAM_ORDINARY;
+                               mtmp->cham = NON_PM;
                        else
                                mtmp->cham = mndx;
                        if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
@@ -1520,9 +1520,9 @@ register struct monst *mtmp;
 
        mptr = mtmp->data;              /* save this for m_detach() */
        /* restore chameleon, lycanthropes to true form at death */
-       if (mtmp->cham != CHAM_ORDINARY) {
+       if (mtmp->cham >= LOW_PM) {
            set_mon_data(mtmp, &mons[mtmp->cham], -1);
-           mtmp->cham = CHAM_ORDINARY;
+           mtmp->cham = NON_PM;
        }
        else if (mtmp->data == &mons[PM_WEREJACKAL])
            set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
@@ -2231,10 +2231,10 @@ rescham()
        for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                if (DEADMONSTER(mtmp)) continue;
                mcham = (int) mtmp->cham;
-               if (mcham != CHAM_ORDINARY) {
+               if (mcham >= LOW_PM) {
                        (void) newcham(mtmp, &mons[mcham],
                                       FALSE, FALSE);
-                       mtmp->cham = CHAM_ORDINARY;
+                       mtmp->cham = NON_PM;
                }
                if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
                        new_were(mtmp);
@@ -2275,13 +2275,13 @@ struct monst *mon;
 
        if (Protection_from_shape_changers) {
            mcham = (int) mon->cham;
-           if (mcham != CHAM_ORDINARY) {
-               mon->cham = CHAM_ORDINARY;
+           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);
            }
-       } else if (mon->cham == CHAM_ORDINARY) {
+       } else if (mon->cham == NON_PM) {
            mon->cham = pm_to_cham(monsndx(mon->data));
        }
 }
@@ -2291,7 +2291,7 @@ STATIC_OVL boolean
 restrap(mtmp)
 register struct monst *mtmp;
 {
-       if((mtmp->cham != CHAM_ORDINARY) || mtmp->mcan || mtmp->m_ap_type ||
+       if((mtmp->cham >= LOW_PM) || mtmp->mcan || mtmp->m_ap_type ||
           cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck) ||
           (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
                return(FALSE);
@@ -2387,10 +2387,11 @@ int shiftflags;
             * 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))
+               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 == CHAM_ORDINARY
-                  && !rn2(6) && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
+       } 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);
        }
 }
@@ -2428,7 +2429,7 @@ struct monst *mon;
                }
                mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
                break;
-           case CHAM_ORDINARY:
+           case NON_PM:        /* ordinary */
              {
                struct obj *m_armr = which_armor(mon, W_ARM);
 
@@ -2749,12 +2750,9 @@ void
 kill_genocided_monsters()
 {
        struct monst *mtmp, *mtmp2;
-       boolean kill_cham[NUMMONS];
+       boolean kill_cham;
        int mndx;
 
-       kill_cham[CHAM_ORDINARY] = FALSE;       /* (this is mndx==0) */
-       for (mndx = LOW_PM; mndx < NUMMONS; mndx++)
-         kill_cham[mndx] = (mvitals[mndx].mvflags & G_GENOD) != 0;
        /*
         * Called during genocide, and again upon level change.  The latter
         * catches up with any migrating monsters as they finally arrive at
@@ -2766,15 +2764,17 @@ kill_genocided_monsters()
         *      2) otherwise, force every chameleon which is imitating
         *         any genocided species to take on a new form.
         */
-       for (mtmp = fmon; mtmp; mtmp = mtmp2) {
+       for (mtmp = fmon; mtmp; mtmp = mtmp2, kill_cham = FALSE) {
            mtmp2 = mtmp->nmon;
            if (DEADMONSTER(mtmp)) continue;
            mndx = monsndx(mtmp->data);
-           if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham[mtmp->cham]) {
-               if ((mtmp->cham != CHAM_ORDINARY) && !kill_cham[mtmp->cham])
-                   (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
+           if (mtmp->cham >= LOW_PM && (mvitals[mtmp->cham].mvflags & G_GENOD))
+               kill_cham = TRUE;
+           if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
+               if (mtmp->cham >= LOW_PM && !kill_cham)
+                       (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
                else
-                   mondead(mtmp);
+                       mondead(mtmp);
            }
            if (mtmp->minvent) kill_eggs(mtmp->minvent);
        }
index a247d1f3d17824e0aa1c2e94d091b86f9fd82618..ab15b90dc209144ecc1e65b11cd6f7c49a3face1 100644 (file)
@@ -1506,11 +1506,11 @@ struct monst *mon;
 struct permonst *ptr;
 {
        int reslt = 0;
-       if (mon->cham != CHAM_ORDINARY) {
+       if (mon->cham >= LOW_PM) {
                if (ptr == &mons[mon->cham])
-                       mon->cham = CHAM_ORDINARY;
+                       mon->cham = NON_PM;
                reslt = newcham(mon, ptr, FALSE, FALSE);
-       } else if (mon->cham == CHAM_ORDINARY && ptr != mon->data) {
+       } else if (mon->cham == NON_PM && ptr != mon->data) {
                mon->cham = monsndx(mon->data);
                reslt = newcham(mon, ptr, FALSE, FALSE);
        }
index 87a10cf072396f19f8ef5d23259cf2740bcc7ccd..95953e99a540ee0647b8a73ea7aa8b70e9905094 100644 (file)
@@ -90,7 +90,6 @@ NEARDATA struct permonst mons[] = {
 /*
  * ants
  */
-    /* Never use M2_SHAPESHIFTER for mons[0] as long as CHAM_ORDINARY==0 */
     MON("giant ant", S_ANT,
        LVL(2, 18, 3, 0, 0), (G_GENO|G_SGROUP|3),
        A(ATTK(AT_BITE, AD_PHYS, 1, 4),
index 27e111addffaac413264a6e4671df07bae8681fd..9eff9524135433268f3dcd95a78b3b4e4f0119c9 100644 (file)
@@ -1586,7 +1586,7 @@ struct monst *mtmp;
                return FALSE;
 
        if (!stuck && !immobile &&
-               (mtmp->cham == CHAM_ORDINARY) && monstr[monsndx(mdat)] < 6) {
+               (mtmp->cham == NON_PM) && monstr[monsndx(mdat)] < 6) {
          boolean ignore_boulders = (verysmall(mdat) ||
                                     throws_rocks(mdat) ||
                                     passes_walls(mdat));
@@ -1657,14 +1657,14 @@ struct monst *mtmp;
                }
                nomore(MUSE_WAN_POLYMORPH);
                if(obj->otyp == WAN_POLYMORPH && obj->spe > 0
-                               && (mtmp->cham == CHAM_ORDINARY)
+                               && (mtmp->cham == NON_PM)
                                && monstr[monsndx(mdat)] < 6) {
                        m.misc = obj;
                        m.has_misc = MUSE_WAN_POLYMORPH;
                }
                nomore(MUSE_POT_POLYMORPH);
                if(obj->otyp == POT_POLYMORPH
-                               && (mtmp->cham == CHAM_ORDINARY)
+                               && (mtmp->cham == NON_PM)
                                && monstr[monsndx(mdat)] < 6) {
                        m.misc = obj;
                        m.has_misc = MUSE_POT_POLYMORPH;
index 1eac6094a78ec105af38da76511e328308f56978..a992836f45322dd6632e4a4fd29914bb5a78a99b 100644 (file)
@@ -317,7 +317,7 @@ register struct monst *mtmp;
        }
        else if (mtmp->mpeaceful) Strcat(info, ", peaceful");
        if (mtmp->meating)        Strcat(info, ", eating");
-       if (mtmp->meating && (mtmp->cham == CHAM_ORDINARY) &&
+       if (mtmp->meating && (mtmp->cham == NON_PM) &&
            mtmp->mappearance && mtmp->m_ap_type) {
                Sprintf(eos(info), ", mimicing %s",
                    (mtmp->m_ap_type == M_AP_FURNITURE) ?
index 173cdab0595f8a28e34ec6ccd692028ea0b0e78f..1ce663fb689b0ba5f4aea3854cd4bf6622f7f594 100644 (file)
@@ -2068,7 +2068,7 @@ create_particular()
                }
                if (mtmp) {
                    madeany = TRUE;
-                   if (mtmp->cham != CHAM_ORDINARY && firstchoice != NON_PM)
+                   if (mtmp->cham >= LOW_PM && firstchoice != NON_PM)
                        (void)newcham(mtmp, &mons[firstchoice], FALSE, FALSE);
                }
            }
index d8d8eb9cfb6eba1ccf43969897b4a7ea4ecd5ebd..9b757ea8d7dc578d1752a15ce0c65fc80c43d449 100644 (file)
@@ -449,8 +449,8 @@ int *fail_reason;
                mon = makemon(&mons[PM_DOPPELGANGER], x, y,
                              NO_MINVENT | MM_NOCOUNTBIRTH | MM_ADJACENTOK);
                /* if hero has protection from shape changers, cham field will
-                  be CHAM_ORDINARY; otherwise, set form to match the statue */
-               if (mon && mon->cham != CHAM_ORDINARY)
+                  be NON_PM; otherwise, set form to match the statue */
+               if (mon && mon->cham >= LOW_PM)
                    (void) newcham(mon, mptr, FALSE, FALSE);
            } else
                mon = makemon(mptr, x, y, (cause == ANIMATE_SPELL) ?
index ce803bed65d653c623d227eec58e723236b6a248..63ff37de216555a953d67663ef4d3552d2c818e3 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -229,7 +229,7 @@ struct obj *otmp;
                    /* natural shapechangers aren't affected by system shock
                       (unless protection from shapechangers is interfering
                       with their metabolism...) */
-                   if (mtmp->cham == CHAM_ORDINARY && !rn2(25)) {
+                   if (mtmp->cham == NON_PM && !rn2(25)) {
                        if (canseemon(mtmp)) {
                            pline("%s shudders!", Monnam(mtmp));
                            learn_it = TRUE;