]> granicus.if.org Git - nethack/commitdiff
more github issue #679 - orc strength
authorPatR <rankin@nethack.org>
Wed, 12 Oct 2022 09:05:32 +0000 (02:05 -0700)
committernhmall <nhmall@nethack.org>
Sat, 15 Oct 2022 16:28:53 +0000 (12:28 -0400)
Handle alternate values for hero poly'd into a 'strongmonst' form
more thoroughly by propagating max values other than 18/100 to the
attribute manipulation routines.

ATTRMAX(A_STR), which used to be a relatively simple expression, now
contains a function call.

Along the way, change the races[] terminator's value for 'mnum' from
0 (giant ant) to NON_PM.

include/attrib.h
include/extern.h
src/polyself.c
src/role.c

index b3a5d82e7269e2cbdea4214188f01e77309c8b15..17671f4648ab74c5c91c8daf48d4b54c4f99bcf0 100644 (file)
@@ -40,10 +40,8 @@ struct attribs {
     schar a[A_MAX];
 };
 
-#define ATTRMAX(x)                                        \
-    ((x == A_STR && Upolyd && strongmonst(g.youmonst.data)) \
-         ? STR18(100)                                     \
-         : g.urace.attrmax[x])
+#define ATTRMAX(x) \
+    ((x == A_STR && Upolyd) ? uasmon_maxStr() : g.urace.attrmax[x])
 #define ATTRMIN(x) (g.urace.attrmin[x])
 
 #endif /* ATTRIB_H */
index 85c0afd0924a476fe2d9f86a9f15d113f5227719..815bf6a4ed000f069d26b38fc3bb1f0afad1bbb1 100644 (file)
@@ -2152,6 +2152,7 @@ extern void change_sex(void);
 extern void livelog_newform(boolean, int, int);
 extern void polyself(int);
 extern int polymon(int);
+extern schar uasmon_maxStr(void);
 extern void rehumanize(void);
 extern int dobreathe(void);
 extern int dospit(void);
@@ -2398,14 +2399,15 @@ extern void rigid_role_checks(void);
 extern boolean setrolefilter(const char *);
 extern boolean gotrolefilter(void);
 extern void clearrolefilter(void);
-extern char *build_plselection_prompt(char *, int, int, int, int, int);
 extern char *root_plselection_prompt(char *, int, int, int, int, int);
+extern char *build_plselection_prompt(char *, int, int, int, int, int);
 extern void plnamesuffix(void);
 extern void role_selection_prolog(int, winid);
 extern void role_menu_extra(int, winid, boolean);
 extern void role_init(void);
 extern const char *Hello(struct monst *);
 extern const char *Goodbye(void);
+extern const struct Race *character_race(short);
 
 /* ### rumors.c ### */
 
index be2ddcbcd34b0efa822d4e90da25669d024ce6f2..e8c2ee35bf482a759f2644b7325e781e2b58a517 100644 (file)
@@ -683,7 +683,7 @@ polymon(int mntmp)
     char buf[BUFSZ];
     boolean sticky = sticks(g.youmonst.data) && u.ustuck && !u.uswallow,
             was_blind = !!Blind, dochange = FALSE;
-    int mlvl;
+    int mlvl, newMaxStr;
 
     if (g.mvitals[mntmp].mvflags & G_GENOD) { /* allow G_EXTINCT */
         You_feel("rather %s-ish.",
@@ -760,33 +760,16 @@ polymon(int mntmp)
     /* New stats for monster, to last only as long as polymorphed.
      * Currently only strength gets changed.
      */
-    if (strongmonst(&mons[mntmp]) && !is_elf(&mons[mntmp])) {
-        /* ettins, titans and minotaurs don't pass the is_giant() test;
-           giant mummies and giant zombies do but we throttle those;
-           Lord Surtur and Cyclops pass the test but can't be poly'd into */
-        boolean live_H = is_giant(&mons[mntmp]) && !is_undead(&mons[mntmp]);
-        int newStr = live_H ? STR19(19) : STR18(100);
-
-        /* hero orcs are limited to 18/50 for maximum strength, so treat
-           hero poly'd into an orc the same; goblins, orc shamans, and orc
-           zombies don't have strongmonst() attribute so won't get here;
-           hobgoblins and orc mummies do get here and are limited to 18/50
-           like normal orcs; however, Uruk-hai retain 18/100 strength;
-           hero gnomes are also limited to 18/50; hero elves are limited to
-           18/00 so we treat strongmonst elves (elf-noble, elven monarch)
-           as if they're not (in 'if' above, so they don't get here) */
-        if ((is_orc(&mons[mntmp])
-             && !strstri(pmname(&mons[mntmp], NEUTRAL), "Uruk"))
-            || is_gnome(&mons[mntmp]))
-            newStr = STR18(50);
-
-        ABASE(A_STR) = AMAX(A_STR) = newStr;
+    newMaxStr = uasmon_maxStr();
+    if (strongmonst(&mons[mntmp])) {
+        ABASE(A_STR) = AMAX(A_STR) = (schar) newMaxStr;
     } else {
         /* not a strongmonst(); if hero has exceptional strength, remove it
            (note: removal is temporary until returning to original form);
            we don't attempt to enforce lower maximum for wimpy forms;
-           we do avoid boosting current strength to 18 if presently less */
-        AMAX(A_STR) = 18; /* same as STR18(0) */
+           unlike for strongmonst, current strength does not get set to max */
+        AMAX(A_STR) = (schar) newMaxStr;
+        /* make sure current is not higher than max (strip exceptional Str) */
         if (ABASE(A_STR) > AMAX(A_STR))
             ABASE(A_STR) = AMAX(A_STR);
     }
@@ -981,6 +964,54 @@ polymon(int mntmp)
     return 1;
 }
 
+/* determine hero's temporary strength value used while polymorphed;
+   hero poly'd into M2_STRONG monster usually gets 18/100 strength but
+   there are exceptions; non-M2_STRONG get maximum strength set to 18 */
+schar
+uasmon_maxStr(void)
+{
+    const struct Race *R;
+    int newMaxStr;
+    int mndx = u.umonnum;
+    struct permonst *ptr = &mons[mndx];
+
+    if (is_orc(ptr)) {
+        if (mndx != PM_URUK_HAI)
+            mndx = PM_ORC;
+    } else if (is_elf(ptr)) {
+        mndx = PM_ELF;
+    } else if (is_dwarf(ptr)) {
+        mndx = PM_DWARF;
+    } else if (is_gnome(ptr)) {
+        mndx = PM_GNOME;
+#if 0   /* use the mons[] value for humans */
+    } else if (is_human(ptr)) {
+        mndx = PM_HUMAN;
+#endif
+    }
+    R = character_race(mndx);
+
+    if (strongmonst(ptr)) {
+        /* ettins, titans and minotaurs don't pass the is_giant() test;
+           giant mummies and giant zombies do but we throttle those */
+        boolean live_H = is_giant(ptr) && !is_undead(ptr);
+
+        /* hero orcs are limited to 18/50 for maximum strength, so treat
+           hero poly'd into an orc the same; goblins, orc shamans, and orc
+           zombies don't have strongmonst() attribute so won't get here;
+           hobgoblins and orc mummies do get here and are limited to 18/50
+           like normal orcs; however, Uruk-hai retain 18/100 strength;
+           hero gnomes are also limited to 18/50; hero elves are limited
+           to 18/00 regardless of whether they're strongmonst, but the two
+           strongmonst types (monarchs and nobles) have current strength
+           set to 18 [by polymon()], the others don't */
+        newMaxStr = R ? R->attrmax[A_STR] : live_H ? STR19(19) : STR18(100);
+    } else {
+        newMaxStr = R ? R->attrmax[A_STR] : 18; /* 18 is same as STR18(0) */
+    }
+    return (schar) newMaxStr;
+}
+
 /* dropx() jacket for break_armor() */
 static void
 dropp(struct obj *obj)
index a83e45706f5855c1d3a73b22d471d82eb4ce3735..613f83c494146e4454eb68dcadc27dd67b60f2c3 100644 (file)
@@ -676,7 +676,7 @@ const struct Race races[] = {
         { 1, 0, 1, 0, 1, 0 }  /* Energy */
     },
     /* Array terminator */
-    { 0, 0, 0, 0 }
+    { 0, 0, 0, 0, { 0, 0 }, NON_PM }
 };
 
 /* Table of all genders */
@@ -1697,11 +1697,10 @@ role_selection_prolog(int which, winid where)
                 : !*g.plname ? not_yet : g.plname);
     putstr(where, 0, buf);
     Sprintf(buf, "%12s ", "role:");
-    Strcat(buf, (which == RS_ROLE) ? choosing : (r == ROLE_NONE)
-                                                    ? not_yet
-                                                    : (r == ROLE_RANDOM)
-                                                          ? rand_choice
-                                                          : roles[r].name.m);
+    Strcat(buf, (which == RS_ROLE) ? choosing
+                : (r == ROLE_NONE) ? not_yet
+                  : (r == ROLE_RANDOM) ? rand_choice
+                    : roles[r].name.m);
     if (r >= 0 && roles[r].name.f) {
         /* distinct female name [caveman/cavewoman, priest/priestess] */
         if (gend == 1)
@@ -1713,25 +1712,22 @@ role_selection_prolog(int which, winid where)
     }
     putstr(where, 0, buf);
     Sprintf(buf, "%12s ", "race:");
-    Strcat(buf, (which == RS_RACE) ? choosing : (c == ROLE_NONE)
-                                                    ? not_yet
-                                                    : (c == ROLE_RANDOM)
-                                                          ? rand_choice
-                                                          : races[c].noun);
+    Strcat(buf, (which == RS_RACE) ? choosing
+                : (c == ROLE_NONE) ? not_yet
+                  : (c == ROLE_RANDOM) ? rand_choice
+                    : races[c].noun);
     putstr(where, 0, buf);
     Sprintf(buf, "%12s ", "gender:");
-    Strcat(buf, (which == RS_GENDER) ? choosing : (gend == ROLE_NONE)
-                                                      ? not_yet
-                                                      : (gend == ROLE_RANDOM)
-                                                            ? rand_choice
-                                                            : genders[gend].adj);
+    Strcat(buf, (which == RS_GENDER) ? choosing
+                : (gend == ROLE_NONE) ? not_yet
+                  : (gend == ROLE_RANDOM) ? rand_choice
+                    : genders[gend].adj);
     putstr(where, 0, buf);
     Sprintf(buf, "%12s ", "alignment:");
-    Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
-                                                       ? not_yet
-                                                       : (a == ROLE_RANDOM)
-                                                             ? rand_choice
-                                                             : aligns[a].adj);
+    Strcat(buf, (which == RS_ALGNMNT) ? choosing
+                : (a == ROLE_NONE) ? not_yet
+                  : (a == ROLE_RANDOM) ? rand_choice
+                    : aligns[a].adj);
     putstr(where, 0, buf);
 }
 
@@ -2078,4 +2074,17 @@ Goodbye(void)
     }
 }
 
+/* if pmindex is any player race (not necessarily the hero's),
+   return a pointer to the races[] entry for it */
+const struct Race *
+character_race(short pmindex)
+{
+    const struct Race *r;
+
+    for (r = races; r->mnum >= LOW_PM; ++r)
+        if (r->mnum == pmindex)
+            return r;
+    return (const struct Race *) NULL;
+}
+
 /* role.c */