]> granicus.if.org Git - nethack/commitdiff
more #U1233 - specifying mon class instead type for polyself (trunk only)
authornethack.rankin <nethack.rankin>
Tue, 10 Apr 2007 03:39:52 +0000 (03:39 +0000)
committernethack.rankin <nethack.rankin>
Tue, 10 Apr 2007 03:39:52 +0000 (03:39 +0000)
     Another item from the Dec'04 report sent in by <email deleted>.  When prompted for a type of monster to polymorph
into, giving a monster class description like "dog or other canine" (or
single letter like 'd'), triggered "I've never heard of such monsters".
Instead of adjusting the message, this chooses a member from the class.

     I put this into the fixes file as a new feature.

doc/fixes35.0
include/extern.h
src/makemon.c
src/mondata.c
src/polyself.c

index a71d585dce5c7c48987823f549ffe4226908313c..00e69a6b496ef34d48d5b5ed3f6f9707fdaa56ec 100644 (file)
@@ -311,6 +311,7 @@ improved container interface
 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
 
 
 Platform- and/or Interface-Specific New Features
index cef64a9d83f1172dbbd460cdfb97c3c1bef79ceb..557784c8f5e0bfcdeeb970ba08159028b03059f1 100644 (file)
@@ -1050,6 +1050,7 @@ E boolean FDECL(create_critters, (int,struct permonst *,BOOLEAN_P));
 E struct permonst *NDECL(rndmonst);
 E void FDECL(reset_rndmonst, (int));
 E struct permonst *FDECL(mkclass, (CHAR_P,int));
+E int FDECL(mkclass_poly, (int));
 E int FDECL(adj_lev, (struct permonst *));
 E struct permonst *FDECL(grow_up, (struct monst *,struct monst *));
 E int FDECL(mongets, (struct monst *,int));
index 6499298eb79c0cb9572185a3a5546b53085e4f4e..58e33278d5959f0a7ed7a1ca933c68bfac3a3478 100644 (file)
@@ -1415,6 +1415,37 @@ int      spc;
        return(&mons[first]);
 }
 
+/* like mkclass(), but excludes difficulty considerations; used when
+   player with polycontrol picks a class instead of a specific type;
+   genocided types are avoided but extinct ones are acceptable */
+int
+mkclass_poly(class)
+int class;
+{
+       register int first, last, num = 0;
+
+       for (first = LOW_PM; first < SPECIAL_PM; first++)
+           if (mons[first].mlet == class) break;
+       if (first == SPECIAL_PM) return NON_PM;
+
+       for (last = first;
+               last < SPECIAL_PM && mons[last].mlet == class; last++)
+           if (!(mvitals[last].mvflags & G_GENOD) &&
+                   !(mons[last].geno & (G_NOGEN|G_UNIQ)) &&
+                   !is_placeholder(&mons[last]))
+               num += mons[last].geno & G_FREQ;
+       if (!num) return NON_PM;
+
+       for (num = rnd(num); num > 0; first++)
+           if (!(mvitals[first].mvflags & G_GENOD) &&
+                   !(mons[first].geno & (G_NOGEN|G_UNIQ)) &&
+                   !is_placeholder(&mons[first]))
+               num -= mons[first].geno & G_FREQ;
+       first--; /* correct an off-by-one error */
+
+       return first;
+}
+
 int
 adj_lev(ptr)   /* adjust strength of monsters based on u.uz and u.ulevel */
 register struct permonst *ptr;
index 3cd514041fb03d8a61974c458125d18b28b73fb6..f3e319fea0f57ac4808030296083ea0e6a69d538 100644 (file)
@@ -664,10 +664,15 @@ int *mndx_p;
        /* multiple-letter input which matches any of these gets rejected */
        "an", "the", "or", "other", "or other", 0
     };
+    /* positive pm_val => specific monster; negative => class */
     static NEARDATA const struct alt_spl truematch[] = {
        /* "long worm" won't match "worm" class but would accidentally match
           "long worm tail" class before the comparison with monster types */
        { "long worm",          PM_LONG_WORM },
+       /* matches wrong--or at least suboptimal--class */
+       { "demon",              -S_DEMON },     /* hits "imp or minor demon" */
+       /* matches specific monster (overly restrictive) */
+       { "devil",              -S_DEMON },     /* always "horned devil" */
        /* some plausible guesses which need help */
        { "bug",                -S_XAN },       /* would match bugbear... */
        { "fish",               -S_EEL },       /* wouldn't match anything */
@@ -685,7 +690,12 @@ int *mndx_p;
     } else if (!in_str[1]) {
        /* single character */
        i = def_char_to_monclass(*in_str);
-       if (i == MAXMCLASSES)
+       if (i == S_MIMIC_DEF) {         /* ']' -> 'm' */
+           i = S_MIMIC;
+       } else if (i == S_WORM_TAIL) {  /* '~' -> 'w' */
+           i = S_WORM;
+           if (mndx_p) *mndx_p = PM_LONG_WORM;
+       } else if (i == MAXMCLASSES)    /* maybe 'I' */
            i = (*in_str == DEF_INVISIBLE) ? S_invisible : 0;
        return i;
     } else {
index 5105d6cd3931b4ac81a03a7e20591a1ee9b64583..7bc84c426958a6bc45598f775fcabc3605d3bb98 100644 (file)
@@ -255,7 +255,7 @@ polyself(psflags)
 int psflags;     
 {
        char buf[BUFSZ];
-       int old_light, new_light, mntmp, tryct;
+       int old_light, new_light, mntmp, class, tryct;
        boolean forcecontrol = (psflags == 1),
                monsterpoly = (psflags == 2),
                draconian = (uarm && Is_dragon_armor(uarm)),
@@ -286,9 +286,18 @@ int psflags;
                do {
                        getlin("Become what kind of monster? [type the name]",
                                buf);
+                       class = 0;
                        mntmp = name_to_mon(buf);
+                       if (mntmp < LOW_PM) {
+                           class = name_to_monclass(buf, &mntmp);
+                           if (class && mntmp == NON_PM)
+                               mntmp = mkclass_poly(class);
+                       }
                        if (mntmp < LOW_PM)
+                           if (!class)
                                pline("I've never heard of such monsters.");
+                           else
+                               You_cant("polymorph into any of those.");
                        else if (iswere && (were_beastie(mntmp) == u.ulycn ||
                                    mntmp == counter_were(u.ulycn) ||
                                    (Upolyd && mntmp == PM_HUMAN)))
@@ -301,7 +310,7 @@ int psflags;
                                      your_race(&mons[mntmp]) ||
                                      mntmp == urole.malenum ||
                                      mntmp == urole.femalenum))
-                               You("cannot polymorph into that.");
+                               You_cant("polymorph into that.");
                        else break;
                } while (--tryct > 0);
                if (!tryct) pline(thats_enough_tries);