From: PatR Date: Sun, 19 Apr 2020 11:58:18 +0000 (-0700) Subject: wishing fix X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=05403182ebc542da4bacd716cef408a27372c1ad;p=nethack wishing fix 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.) --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index fcbfba74d..31b7b55ee 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 7e3b78ad2..25d3ce40e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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)); diff --git a/src/botl.c b/src/botl.c index db0fd49af..06f8a3555 100644 --- a/src/botl.c +++ b/src/botl.c @@ -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; } diff --git a/src/mondata.c b/src/mondata.c index 9672159ee..76b92e8bd 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -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; } diff --git a/src/objnam.c b/src/objnam.c index 237795c90..bd89a89ec 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -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 */