]> granicus.if.org Git - nethack/commitdiff
wishing fix
authorPatR <rankin@nethack.org>
Sun, 19 Apr 2020 11:58:18 +0000 (04:58 -0700)
committerPatR <rankin@nethack.org>
Sun, 19 Apr 2020 11:58:18 +0000 (04:58 -0700)
name_to_mon() has a bunch of alternate monster names, such as
"gray-elf" to match "grey-elf" and "ki rin" to match "ki-rin".  Those
worked as intended when they occurred at the end of a wish, but only
worked in the middle if their length was the same or one character
less than the canonical name in mons[].mname.

djinni figurine     -> h - a figurine of a djinni
genie figurine      -> i - a figurine of a djinni
figurine of mumak   -> j - a figurine of a mumak
mumak figurine      -> k - a figurine of a mumak
figurine of mumakil -> l - a figurine of a mumak
mumakil figurine    -> nothing fitting that description exists

(The one-less case worked because its following space ended up being
implicitly removed when skipping ahead by the length of mons[].mname;
subsequent explicit removal didn't find a space so was a no-op.)

doc/fixes37.0
include/extern.h
src/botl.c
src/mondata.c
src/objnam.c

index fcbfba74d562b5660318c6eea58407b18dd6657c..31b7b55ee6981531e07bea28f055eb97c7d45948 100644 (file)
@@ -137,6 +137,10 @@ hostile monsters with launcher and ammo try to stay away from melee range
 allow displacing peaceful creatures
 unicorn horns don't restore attribute loss anymore
 when a shop is changed from food to health food, change room type to match
+wish parsing of things containing monster names would accept all supported
+       alternate spellings if they occurred at the end ("corpse of mumakil")
+       but only some when they occurred elsewhere ("gray-elf corpse" worked,
+       "mumakil corpse" yielded "does not exist") depending upon name length
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 7e3b78ad2444343e450158c825d4d294d6fe189d..25d3ce40e4f938bf6009f06d5f2acdf8d81a36cf 100644 (file)
@@ -1558,6 +1558,7 @@ E int FDECL(max_passive_dmg, (struct monst *, struct monst *));
 E boolean FDECL(same_race, (struct permonst *, struct permonst *));
 E int FDECL(monsndx, (struct permonst *));
 E int FDECL(name_to_mon, (const char *));
+E int FDECL(name_to_monplus, (const char *, const char **));
 E int FDECL(name_to_monclass, (const char *, int *));
 E int FDECL(gender, (struct monst *));
 E int FDECL(pronoun_gender, (struct monst *, unsigned));
index db0fd49af7c575278209116e0c71bbcb23e063cc..06f8a35558158153b08649729f9d31bad2615a98 100644 (file)
@@ -329,7 +329,8 @@ int *rank_indx, *title_length;
     register int i, j;
 
     /* Loop through each of the roles */
-    for (i = 0; roles[i].name.m; i++)
+    for (i = 0; roles[i].name.m; i++) {
+        /* loop through each of the rank titles for role #i */
         for (j = 0; j < 9; j++) {
             if (roles[i].rank[j].m
                 && !strncmpi(str, roles[i].rank[j].m,
@@ -351,6 +352,9 @@ int *rank_indx, *title_length;
                                                       : roles[i].malenum;
             }
         }
+    }
+    if (title_length)
+        *title_length = 0;
     return NON_PM;
 }
 
index 9672159ee485dfe5c87c6a251af0a9c12683fb6c..76b92e8bd2160c1a416ae971be16e3d516764b7e 100644 (file)
@@ -678,10 +678,23 @@ struct alt_spl {
     short pm_val;
 };
 
-/* figure out what type of monster a user-supplied string is specifying */
+/* figure out what type of monster a user-supplied string is specifying;
+   ingore anything past the monster name */
 int
 name_to_mon(in_str)
 const char *in_str;
+{
+    return name_to_monplus(in_str, (const char **) 0);
+}
+
+/* figure out what type of monster a user-supplied string is specifying;
+   return a pointer to whatever is past the monster name--necessary if
+   caller wants to strip off the name and it matches one of the alternate
+   names rather the canonical mons[].mname */
+int
+name_to_monplus(in_str, remainder_p)
+const char *in_str;
+const char **remainder_p;
 {
     /* Be careful.  We must check the entire string in case it was
      * something such as "ettin zombie corpse".  The calling routine
@@ -701,6 +714,9 @@ const char *in_str;
     char buf[BUFSZ];
     int len, slen;
 
+    if (remainder_p)
+        *remainder_p = (const char *) 0;
+
     str = strcpy(buf, in_str);
 
     if (!strncmp(str, "a ", 2))
@@ -767,6 +783,7 @@ const char *in_str;
             { "elf lord", PM_ELF_LORD },
             { "olog hai", PM_OLOG_HAI },
             { "arch lich", PM_ARCH_LICH },
+            { "archlich", PM_ARCH_LICH },
             /* Some irregular plurals */
             { "incubi", PM_INCUBUS },
             { "succubi", PM_SUCCUBUS },
@@ -785,9 +802,16 @@ const char *in_str;
         };
         register const struct alt_spl *namep;
 
-        for (namep = names; namep->name; namep++)
-            if (!strncmpi(str, namep->name, (int) strlen(namep->name)))
+        for (namep = names; namep->name; namep++) {
+            len = (int) strlen(namep->name);
+            if (!strncmpi(str, namep->name, len)
+                /* force full word (which could conceivably be possessive) */
+                && (!str[len] || str[len] == ' ' || str[len] == '\'')) {
+                if (remainder_p)
+                    *remainder_p = in_str + (&str[len] - buf);
                 return namep->pm_val;
+            }
+        }
     }
 
     for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
@@ -813,7 +837,9 @@ const char *in_str;
         }
     }
     if (mntmp == NON_PM)
-        mntmp = title_to_mon(str, (int *) 0, (int *) 0);
+        mntmp = title_to_mon(str, (int *) 0, &len);
+    if (len && remainder_p)
+        *remainder_p = in_str + (&str[len] - buf);
     return mntmp;
 }
 
index 237795c90fdd2d3418511ad3fe4be838fe7c9eca..bd89a89ec8a86b5797380b0f03f5cdc43d5e299b 100644 (file)
@@ -3585,19 +3585,24 @@ struct obj *no_wish;
         && strncmpi(bp, "ninja-to", 8)     /* not the "ninja" rank */
         && strncmpi(bp, "master key", 10)  /* not the "master" rank */
         && strncmpi(bp, "magenta", 7)) {   /* not the "mage" rank */
+        const char *rest = 0;
+
         if (mntmp < LOW_PM && strlen(bp) > 2
-            && (mntmp = name_to_mon(bp)) >= LOW_PM) {
-            int mntmptoo, mntmplen; /* double check for rank title */
+            && (mntmp = name_to_monplus(bp, &rest)) >= LOW_PM) {
             char *obp = bp;
 
-            mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
-            bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
-                                      : mntmplen;
+            /* 'rest' is a pointer past the matching portion; if that was
+               an alternate name or a rank title rather than the canonical
+               monster name we wouldn't otherwise know how much to skip */
+            bp = (char *) rest; /* cast away const */
+
             if (*bp == ' ') {
                 bp++;
-            } else if (!strncmpi(bp, "s ", 2)) {
+            } else if (!strncmpi(bp, "s ", 2)
+                       || (bp > origbp && !strncmpi(bp - 1, "s' ", 3))) {
                 bp += 2;
-            } else if (!strncmpi(bp, "es ", 3)) {
+            } else if (!strncmpi(bp, "es ", 3)
+                       || !strncmpi(bp, "'s ", 3)) {
                 bp += 3;
             } else if (!*bp && !actualn && !dn && !un && !oclass) {
                 /* no referent; they don't really mean a monster type */