]> granicus.if.org Git - nethack/commitdiff
#monpolycontrol of unseen monsters and of vampires (trunk only)
authornethack.rankin <nethack.rankin>
Fri, 8 Feb 2008 03:19:09 +0000 (03:19 +0000)
committernethack.rankin <nethack.rankin>
Fri, 8 Feb 2008 03:19:09 +0000 (03:19 +0000)
     I was testing something with #monpolycontrol enabled and got a
series of "Change it into what kind of monster? [type the name]" prompts
when I went to a new level.  It was asking about monsters that were being
created (in this case, multiple vampires for top level of Vlad's Tower)
and naturally I couldn't see them since the level wasn't finished yet.
This switches to noit_mon_nam() to at least be informed about the type
of creature you're being asked to specify a shape for, and adds the map
coordinates so that it doesn't appear to be reprompting for the same
monster over and over when multiple similar ones are being created.

     In the process I discovered that #monpolycontrol would let you give
any type of monster for the shape of vampires.  Unlike chameleons, they
don't change into arbitrary shapes so that was inappropriate.  [And
trying to test the fix for this is what led to the previous ^G patch.]

doc/fixes35.0
src/mon.c

index aef03393384bd0b2e4c875246fcad9e4ecbb19ec..6aa8ba080a8ff28ebf3dfb7c733e7019f3eed47c 100644 (file)
@@ -279,6 +279,7 @@ potion thrown by monster which hit a long worm's tail gave feedback about
 implement energy vortex's previously unused energy drain attack
 changing alignment type resets alignment record to 0 (nomimally aligned)
 while polymorphed, suppress attribute gain/lose earned by pre-poly exercise
+wizard mode #monpolycontrol prompting asked about "it" when monster was unseen
 
 
 Platform- and/or Interface-Specific Fixes
index d0947f842af0392b7bb363165432e26cfe852aff..f7bd465f95bbf0a36fad26653a9815dccf38905f 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)mon.c      3.5     2007/07/13      */
+/*     SCCS Id: @(#)mon.c      3.5     2008/02/07      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -21,6 +21,10 @@ STATIC_DCL long FDECL(mm_displacement, (struct monst *,struct monst *));
 STATIC_DCL int NDECL(pick_animal);
 STATIC_DCL void FDECL(kill_eggs, (struct obj *));
 STATIC_DCL void FDECL(dealloc_mextra, (struct mextra *));
+STATIC_DCL int FDECL(pickvampshape, (struct monst *));
+#ifdef WIZARD
+STATIC_DCL boolean FDECL(validvamp, (struct monst *,int *,int));
+#endif
 
 #ifdef REINCARNATION
 #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
@@ -2517,6 +2521,70 @@ int shiftflags;
            mon->female = was_female;
 }
 
+STATIC_OVL int
+pickvampshape(mon)
+struct monst *mon;
+{
+       int mndx = mon->cham;
+
+       switch (mndx) {
+       case PM_VLAD_THE_IMPALER:
+           /* ensure Vlad can keep carrying the Candelabrum */
+           if (mon_has_special(mon)) break;    /* leave mndx as is */
+           /*FALLTHRU*/
+       case PM_VAMPIRE_LORD:   /* vampire lord or Vlad can become wolf */
+           if (!rn2(10)) {
+               mndx = PM_WOLF;
+               break;
+           }
+           /*FALLTHRU*/
+       case PM_VAMPIRE:        /* any vampire can become fog or bat */
+           mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
+           break;
+       }
+       return mndx;
+}
+
+#ifdef WIZARD
+/* prevent wizard mode user from specifying invalid vampshifter shape */
+static boolean
+validvamp(mon, mndx_p, monclass)
+struct monst *mon;
+int *mndx_p, monclass;
+{
+       if (!is_vampshifter(mon)) return TRUE;  /* simplify caller's usage */
+
+       if (*mndx_p == PM_VAMPIRE || *mndx_p == PM_VAMPIRE_LORD ||
+               *mndx_p == PM_VLAD_THE_IMPALER) {
+           /* player picked some type of vampire; use mon's self */
+           *mndx_p = mon->cham;
+           return TRUE;
+       }
+       if (mon->cham == PM_VLAD_THE_IMPALER && mon_has_special(mon)) {
+           /* Vlad with Candelabrum; override choice, then accept it */
+           *mndx_p = PM_VLAD_THE_IMPALER;
+           return TRUE;
+       }
+       /* basic vampires can't become wolves; any can become fog or bat */
+       if (*mndx_p == PM_WOLF) return (mon->cham != PM_VAMPIRE);
+       if (*mndx_p == PM_FOG_CLOUD || *mndx_p == PM_VAMPIRE_BAT) return TRUE;
+
+       /* if we get here, specific type was no good; try by class */
+       switch (monclass) {
+       case S_VAMPIRE: *mndx_p = mon->cham; break;
+       case S_BAT:     *mndx_p = PM_VAMPIRE_BAT; break;
+       case S_VORTEX:  *mndx_p = PM_FOG_CLOUD; break;
+       case S_DOG:     if (mon->cham != PM_VAMPIRE) {
+                           *mndx_p = PM_WOLF;
+                           break;
+                       }
+                       /*FALLTHRU*/
+       default:        *mndx_p = NON_PM; break;
+       }
+       return (*mndx_p != NON_PM);
+}
+#endif /*WIZARD*/
+
 int
 select_newcham_form(mon)
 struct monst *mon;
@@ -2551,20 +2619,9 @@ struct monst *mon;
                if (!rn2(3)) mndx = pick_animal();
                break;
            case PM_VLAD_THE_IMPALER:
-               if (mon_has_special(mon)) { /* ensure Vlad can carry it still */
-                   mndx = PM_VLAD_THE_IMPALER;
-                   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;
+               mndx = pickvampshape(mon);
                break;
            case NON_PM:        /* ordinary */
              {
@@ -2584,22 +2641,27 @@ struct monst *mon;
            int monclass;
 
            Sprintf(pprompt,
-                   "Change %s into what kind of monster? [type the name]",
-                   mon_nam(mon));
+                   "Change %s @ <%d,%d> into what kind of monster?",
+                   noit_mon_nam(mon), (int)mon->mx, (int)mon->my);
            tryct = 5;
            do {
+               monclass = 0;
                getlin(pprompt, buf);
-               if (*buf == '\033') break;
+               mungspaces(buf);
+               if (*buf == '\033' || !strcmp(buf, "*") ||
+                       !strcmp(buf, "random")) break;  /* mndx == NON_PM */
                mndx = name_to_mon(buf);
-               if (mndx >= LOW_PM) break;
+               if (mndx >= LOW_PM && validvamp(mon, &mndx, monclass)) break;
                monclass = name_to_monclass(buf, &mndx);
                if (monclass && mndx == NON_PM)
                    mndx = mkclass_poly(monclass);
-               if (mndx >= LOW_PM) break;
+               if (mndx >= LOW_PM && validvamp(mon, &mndx, monclass)) break;
 
-               You("cannot polymorph %s into that.", mon_nam(mon));
+               pline("It can't become that.");
            } while (--tryct > 0);
            if (!tryct) pline(thats_enough_tries);
+           if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass))
+               mndx = pickvampshape(mon);      /* don't resort to arbitrary */
        }
 #endif /*WIZARD*/
        if (mndx == NON_PM) mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);