]> granicus.if.org Git - nethack/commitdiff
last #U1233 - doppelganger shapes (trunk only)
authornethack.rankin <nethack.rankin>
Sat, 14 Apr 2007 02:38:56 +0000 (02:38 +0000)
committernethack.rankin <nethack.rankin>
Sat, 14 Apr 2007 02:38:56 +0000 (02:38 +0000)
     My last fix from the Dec'04 report sent by <email deleted>.  Many of its remaining observations/complaints are
about things which aren't bugs.  This implements the suggestion that
doppelgangers should take on humanoid form, although it doesn't take away
the 1/7 chance for pick_nasty() and it can still fall back to arbitrary
shapes when it doesn't pick a humanoid within 5 tries.  This also allows
doppelgangers to take on the shape of the various quest guardian monsters
[mostly the quest leaders' attendants, although there is at least one
extra foe (ninja)].  It excludes the quest guardian for the player's own
role, and I don't think there are any cases where it can yield unexpected
quest guardian behavior.

     This also allows specifying monster class (via description or letter)
when #monpolycontrol asks for type of monster to give to a polymorphing/
shapechanging monster.

doc/fixes35.0
src/mon.c

index 9618a15f23fa66510317b0df883670ec5b381be7..f6e9bf41b4189a9c603b7ae5bbe1848b98eb9e7c 100644 (file)
@@ -215,6 +215,8 @@ bear traps and webs are harmless to water elementals
 hero with polymorph control and inflicted with lycanthropy can specify own
        werecritter or human werecritter monster types as polymorph target
 hero undergoing semi-controlled polymorph won't also undergo sex change
+when doppelgangers taking on new shape don't specifically pick nasty monster
+       or role monster, bias the random form towards humanoid
 
 
 Platform- and/or Interface-Specific Fixes
@@ -312,7 +314,9 @@ acid can destroy iron bars
 OPTIONS=playmode:normal|explore|debug to choose mode without command-line
 score bonus for ascending is reduced or denied for changing alignment
 player can give a monster class when asked for type of monster to poly into
+likewise when asked about type for #monpolycontrol
 scroll of taming/spell of charm monster now gives some feedback
+doppelgangers can take on the shape of alternate roles' quest guardians
 
 
 Platform- and/or Interface-Specific New Features
index b537635a35e25b9955d3c229d73e55ed4c83bc38..f2e163bb1615ee4794a4e3241405987a28f05b32 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -2539,33 +2539,49 @@ int
 select_newcham_form(mon)
 struct monst *mon;
 {
-       int mndx = NON_PM;
+       int mndx = NON_PM, tryct;
 
        switch (mon->cham) {
            case PM_SANDESTIN:
                if (rn2(7)) mndx = pick_nasty();
                break;
            case PM_DOPPELGANGER:
-               if (!rn2(7)) mndx = pick_nasty();
-               else if (rn2(3)) mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
-                                           PM_ARCHEOLOGIST);
+               if (!rn2(7)) {
+                   mndx = pick_nasty();
+               } else if (rn2(3)) {    /* role monsters */
+                   mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
+                              PM_ARCHEOLOGIST);
+               } else if (!rn2(3)) {   /* quest guardians */
+                   mndx = rn1(PM_APPRENTICE - PM_STUDENT + 1,
+                              PM_STUDENT);
+                   /* avoid own role's guardian */
+                   if (mndx == urole.guardnum) mndx = NON_PM;
+               } else {                /* general humanoids */
+                   tryct = 5;
+                   do {
+                       mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
+                       if (humanoid(&mons[mndx]) && polyok(&mons[mndx])) break;
+                   } while (--tryct > 0);
+                   if (!tryct) mndx = NON_PM;
+               }
                break;
            case PM_CHAMELEON:
                if (!rn2(3)) mndx = pick_animal();
                break;
            case PM_VLAD_THE_IMPALER:
-           case PM_VAMPIRE_LORD:
-           case PM_VAMPIRE:
-               if (mon_has_special(mon) &&  /* ensure Vlad can carry it still */
-                   mon->cham == PM_VLAD_THE_IMPALER) {
-                       mndx = PM_VLAD_THE_IMPALER;
-                       break;
+               if (mon_has_special(mon)) { /* ensure Vlad can carry it still */
+                   mndx = PM_VLAD_THE_IMPALER;
+                   break;
                }
-               if (!rn2(10) && mon->cham != PM_VAMPIRE) {
-                       /* VAMPIRE_LORD || VLAD */
-                       mndx = PM_WOLF;
-                       break;
+               /*FALLTHRU*/
+           case PM_VAMPIRE_LORD:
+               if (!rn2(10)) {
+                   /* VAMPIRE_LORD || VLAD */
+                   mndx = PM_WOLF;
+                   break;
                }
+               /*FALLTHRU*/
+           case PM_VAMPIRE:
                mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
                break;
            case NON_PM:        /* ordinary */
@@ -2580,21 +2596,28 @@ struct monst *mon;
                break;
        }
 #ifdef WIZARD
-       /* For debugging: allow control of polymorphed monster; not saved */
+       /* for debugging: allow control of polymorphed monster */
        if (wizard && iflags.mon_polycontrol) {
            char pprompt[BUFSZ], buf[BUFSZ];
-           int tries = 0;
+           int monclass;
+
+           Sprintf(pprompt,
+                   "Change %s into what kind of monster? [type the name]",
+                   mon_nam(mon));
+           tryct = 5;
            do {
-               Sprintf(pprompt,
-                       "Change %s into what kind of monster? [type the name]",
-                       mon_nam(mon));
-               getlin(pprompt,buf);
+               getlin(pprompt, buf);
+               if (*buf == '\033') break;
                mndx = name_to_mon(buf);
-               if (mndx < LOW_PM)
-                   You("cannot polymorph %s into that.", mon_nam(mon));
-               else break;
-           } while(++tries < 5);
-           if (tries==5) pline(thats_enough_tries);
+               if (mndx >= LOW_PM) break;
+               monclass = name_to_monclass(buf, &mndx);
+               if (monclass && mndx == NON_PM)
+                   mndx = mkclass_poly(monclass);
+               if (mndx >= LOW_PM) break;
+
+               You("cannot polymorph %s into that.", mon_nam(mon));
+           } while (--tryct > 0);
+           if (!tryct) pline(thats_enough_tries);
        }
 #endif /*WIZARD*/
        if (mndx == NON_PM) mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);