From 5ec96751ba5cfa7886c37183929f816efd0a8d6b Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 20 Apr 2020 14:57:17 -0700 Subject: [PATCH] fix issue #325 - wishing for "garlic" doesn't work Wishing allowed "royal jelly" to match "lump of royal jelly" as a special case, but not "wolfsbane" to match "sprig of wolfsbane" or "tricks" to match "bag of tricks". Handle that sort of match in a more general way. While in there, add a minor glob bit: instead of giving a random corpse (because monster is flagged as no-corpse) if someone wishes for "gray ooze corpse" give "glob of gray ooze". Fixes #325 --- doc/fixes37.0 | 3 +++ src/objnam.c | 53 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 81979ff62..55ae20606 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -148,6 +148,9 @@ wishing for werecreature figurine always made one that created the monster in beast form if activated; allow "human were" to explicitly specify werecreature's human form (for corpses and tins as well as figurines); override the restriction against human figurines for that +wishing for "royal jelly" yielded "lump of royal jelly" as a special case, but + other 'of' items such as "clove of garlic", "sprig of wolfsbane", or + "piece of cloth" didn't allow using their post-of words as shorthand Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/objnam.c b/src/objnam.c index c3d19381e..434e74517 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -2842,7 +2842,7 @@ static const struct alt_spellings { { "can opener", TIN_OPENER }, { "kelp", KELP_FROND }, { "eucalyptus", EUCALYPTUS_LEAF }, - { "royal jelly", LUMP_OF_ROYAL_JELLY }, + /* { "royal jelly", LUMP_OF_ROYAL_JELLY }, -- caught by " of " match */ { "lembas", LEMBAS_WAFER }, { "cookie", FORTUNE_COOKIE }, { "pie", CREAM_PIE }, @@ -2896,12 +2896,18 @@ int xtra_prob; /* to force 0% random generation items to also be considered */ { int i, n = 0; short validobjs[NUM_OBJECTS]; - register const char *zn; - int lo, hi, prob, maxprob = 0; + register const char *zn, *of; + boolean check_of; + int lo, hi, minglob, maxglob, prob, maxprob = 0; if (!name || !*name) return STRANGE_OBJECT; + /* only skip "foo of" for "foo of bar" if target doesn't contain " of " */ + check_of = (strstri(name, " of ") == 0); + minglob = GLOB_OF_GRAY_OOZE; + maxglob = GLOB_OF_BLACK_PUDDING; + (void) memset((genericptr_t) validobjs, 0, sizeof validobjs); if (oclass) { lo = g.bases[(uchar) oclass]; @@ -2922,11 +2928,27 @@ int xtra_prob; /* to force 0% random generation items to also be considered */ /* don't match extra descriptions (w/o real name) */ if ((zn = OBJ_NAME(objects[i])) == 0) continue; - if (wishymatch(name, zn, TRUE) + if (wishymatch(name, zn, TRUE) /* objects[] name */ + /* let "" match " of " (already does if foo is + an object class, but this is for lump of royal jelly, + clove of garlic, bag of tricks, &c) with a few exceptions: + for "opening", don't match "bell of opening"; for monster + type ooze/pudding/slime don't match glob of same since that + ought to match "corpse/egg/figurine of type" too but won't */ + || (check_of + && i != BELL_OF_OPENING && i != HUGE_CHUNK_OF_MEAT + && (i < minglob || i > maxglob) + && (of = strstri(zn, " of ")) != 0 + && wishymatch(name, of + 4, FALSE)) /* partial name */ || ((zn = OBJ_DESCR(objects[i])) != 0 - && wishymatch(name, zn, FALSE)) + && wishymatch(name, zn, FALSE)) /* objects[] description */ + /* "cloth" should match "piece of cloth"; there's only one + description containing " of " so no special case handling */ + || (zn && check_of && (of = strstri(zn, " of ")) != 0 + && wishymatch(name, of + 4, FALSE)) /* partial description */ || ((zn = objects[i].oc_uname) != 0 - && wishymatch(name, zn, FALSE))) { + && wishymatch(name, zn, FALSE)) /* user-called name */ + ) { validobjs[n++] = (short) i; maxprob += (objects[i].oc_prob + xtra_prob); } @@ -3613,7 +3635,18 @@ struct obj *no_wish; } /* first change to singular if necessary */ - if (*bp) { + if (*bp + /* we want "tricks" to match "bag of tricks" [rnd_otyp_by_namedesc()] + but that wouldn't work if it gets singularized to "trick" + ["tricks bag" matches whether or not this exception is present + because singularize operates on "bag" and wishymatch()'s + 'of inversion' finds a match] */ + && strcmpi(bp, "tricks") + /* an odd potential wish; fail rather than get a false match with + "cloth" because it might yield a "cloth spellbook" rather than + a "piece of cloth" cloak [maybe we should give random armor?] */ + && strcmpi(bp, "clothes") + ) { char *sng = makesingular(bp); if (strcmp(bp, sng)) { @@ -4022,6 +4055,12 @@ struct obj *no_wish; } } + /* if asking for corpse of a monster which leaves behind a glob, give + glob instead of rejecting the monster type to create random corpse */ + if (typ == CORPSE && mntmp >= LOW_PM && mons[mntmp].mlet == S_PUDDING) { + typ = GLOB_OF_GRAY_OOZE + (mntmp - PM_GRAY_OOZE); + mntmp = NON_PM; /* not used for globs */ + } /* * Create the object, then fine-tune it. */