wishing for artifacts

Use 'fuzzymatch(,," -",)' when checking whether the name specified
in a player's wish text matches an artifact name so that extra or
omitted spaces and dashes are ignored.  Wishing for "firebrand" will
yield "Fire Brand" and "demon bane" will yield "Demonbane".
This commit is contained in:
PatR
2022-04-02 00:28:48 -07:00
parent d7630ebff8
commit eea362249c
6 changed files with 30 additions and 26 deletions

View File

@@ -859,6 +859,8 @@ when teleporting, don't consider pits/spiked pits/trap doors/holes as unsafe
try to avoid locations with engraved Elbereth or scare monster scroll when try to avoid locations with engraved Elbereth or scare monster scroll when
creating new monsters or picking teleport destinations for monsters creating new monsters or picking teleport destinations for monsters
who are susceptible to those who are susceptible to those
be more flexible when wishing checks for artifact name matches; now allows
"firebrand" or "fire-brand" to yield "Fire Brand"
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -67,7 +67,7 @@ extern void save_artifacts(NHFILE *);
extern void restore_artifacts(NHFILE *); extern void restore_artifacts(NHFILE *);
extern const char *artiname(int); extern const char *artiname(int);
extern struct obj *mk_artifact(struct obj *, aligntyp); extern struct obj *mk_artifact(struct obj *, aligntyp);
extern const char *artifact_name(const char *, short *); extern const char *artifact_name(const char *, short *, boolean);
extern boolean exist_artifact(int, const char *); extern boolean exist_artifact(int, const char *);
extern void artifact_exists(struct obj *, const char *, boolean, unsigned); extern void artifact_exists(struct obj *, const char *, boolean, unsigned);
extern void found_artifact(int); extern void found_artifact(int);

View File

@@ -234,7 +234,10 @@ mk_artifact(
* is non-NULL. * is non-NULL.
*/ */
const char * const char *
artifact_name(const char *name, short *otyp) artifact_name(
const char *name, /* string from player that might be an artifact name */
short *otyp_p, /* secondary output */
boolean fuzzy) /* whether to allow extra or omitted spaces or dashes */
{ {
register const struct artifact *a; register const struct artifact *a;
register const char *aname; register const char *aname;
@@ -246,9 +249,10 @@ artifact_name(const char *name, short *otyp)
aname = a->name; aname = a->name;
if (!strncmpi(aname, "the ", 4)) if (!strncmpi(aname, "the ", 4))
aname += 4; aname += 4;
if (!strcmpi(name, aname)) { if (!fuzzy ? !strcmpi(name, aname)
if (otyp) : fuzzymatch(name, aname, " -", TRUE)) {
*otyp = a->otyp; if (otyp_p)
*otyp_p = a->otyp;
return a->name; return a->name;
} }
} }
@@ -2147,8 +2151,9 @@ Sting_effects(int orc_count) /* new count (warn_obj_cnt is old count); -1 is a f
after undergoing a transformation (alignment change, lycanthropy, after undergoing a transformation (alignment change, lycanthropy,
polymorph) which might affect item access */ polymorph) which might affect item access */
int int
retouch_object(struct obj **objp, /* might be destroyed or unintentionally dropped */ retouch_object(
boolean loseit) /* whether to drop it if hero can longer touch it */ struct obj **objp, /* might be destroyed or unintentionally dropped */
boolean loseit) /* whether to drop it if hero can longer touch it */
{ {
struct obj *obj = *objp; struct obj *obj = *objp;
@@ -2206,7 +2211,8 @@ retouch_object(struct obj **objp, /* might be destroyed or unintentionally dropp
freeinv(obj); freeinv(obj);
hitfloor(obj, TRUE); hitfloor(obj, TRUE);
} else { } else {
/* dropx gives a message iff item lands on an altar */ /* dropx gives a message if a dropped item lands on an altar;
we provide one for other terrain */
if (!IS_ALTAR(levl[u.ux][u.uy].typ)) if (!IS_ALTAR(levl[u.ux][u.uy].typ))
pline("%s to the %s.", Tobjnam(obj, "fall"), pline("%s to the %s.", Tobjnam(obj, "fall"),
surface(u.ux, u.uy)); surface(u.ux, u.uy));

View File

@@ -1269,7 +1269,8 @@ do_oname(register struct obj *obj)
*/ */
/* relax restrictions over proper capitalization for artifacts */ /* relax restrictions over proper capitalization for artifacts */
if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp) if ((aname = artifact_name(buf, &objtyp, TRUE)) != 0
&& objtyp == obj->otyp)
Strcpy(buf, aname); Strcpy(buf, aname);
if (obj->oartifact) { if (obj->oartifact) {

View File

@@ -1104,7 +1104,6 @@ artifact_score(
char pbuf[BUFSZ]; char pbuf[BUFSZ];
struct obj *otmp; struct obj *otmp;
long value, points; long value, points;
short dummy; /* object type returned by artifact_name() */
for (otmp = list; otmp; otmp = otmp->nobj) { for (otmp = list; otmp; otmp = otmp->nobj) {
if (otmp->oartifact || otmp->otyp == BELL_OF_OPENING if (otmp->oartifact || otmp->otyp == BELL_OF_OPENING
@@ -1120,7 +1119,7 @@ artifact_score(
/* assumes artifacts don't have quan > 1 */ /* assumes artifacts don't have quan > 1 */
Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)", Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)",
the_unique_obj(otmp) ? "The " : "", the_unique_obj(otmp) ? "The " : "",
otmp->oartifact ? artifact_name(xname(otmp), &dummy) otmp->oartifact ? artiname(otmp->oartifact)
: OBJ_NAME(objects[otmp->otyp]), : OBJ_NAME(objects[otmp->otyp]),
value, currency(value), points); value, currency(value), points);
putstr(endwin, 0, pbuf); putstr(endwin, 0, pbuf);

View File

@@ -1113,7 +1113,7 @@ doname_base(
format the name like the corresponding artifact, which may or may not format the name like the corresponding artifact, which may or may not
want "the" prefix and when it doesn't, avoid "a"/"an" prefix too */ want "the" prefix and when it doesn't, avoid "a"/"an" prefix too */
fake_arti = (obj->otyp == SLIME_MOLD fake_arti = (obj->otyp == SLIME_MOLD
&& (aname = artifact_name(bp, (short *) 0)) != 0); && (aname = artifact_name(bp, (short *) 0, FALSE)) != 0);
force_the = (fake_arti && !strncmpi(aname, "the ", 4)); force_the = (fake_arti && !strncmpi(aname, "the ", 4));
prefix[0] = '\0'; prefix[0] = '\0';
@@ -1899,7 +1899,7 @@ the(const char* str)
has assigned a capitalized proper name as his/her fruit, has assigned a capitalized proper name as his/her fruit,
unless it matches an artifact name */ unless it matches an artifact name */
|| (fruit_from_name(str, TRUE, (int *) 0) || (fruit_from_name(str, TRUE, (int *) 0)
&& ((aname = artifact_name(str, (short *) 0)) == 0 && ((aname = artifact_name(str, (short *) 0, FALSE)) == 0
|| strncmpi(aname, "the ", 4) == 0))) { || strncmpi(aname, "the ", 4) == 0))) {
/* not a proper name, needs an article */ /* not a proper name, needs an article */
insert_the = TRUE; insert_the = TRUE;
@@ -3890,10 +3890,10 @@ readobjnam_postparse1(struct _readobjnam_data *d)
d->bp += 8; d->bp += 8;
} }
/* intercept pudding globs here; they're a valid wish target, /* Intercept pudding globs here; they're a valid wish target,
* but we need them to not get treated like a corpse. * but we need them to not get treated like a corpse.
* * If a count is specified, it will be used to magnify weight
* also don't let player wish for multiple globs. * rather than to specify quantity (which is always 1 for globs).
*/ */
i = (int) strlen(d->bp); i = (int) strlen(d->bp);
d->p = (char *) 0; d->p = (char *) 0;
@@ -4415,7 +4415,7 @@ readobjnam_postparse3(struct _readobjnam_data *d)
short objtyp; short objtyp;
/* Perhaps it's an artifact specified by name, not type */ /* Perhaps it's an artifact specified by name, not type */
d->name = artifact_name(d->actualn, &objtyp); d->name = artifact_name(d->actualn, &objtyp, TRUE);
if (d->name) { if (d->name) {
d->typ = objtyp; d->typ = objtyp;
return 2; /*goto typfnd;*/ return 2; /*goto typfnd;*/
@@ -4855,22 +4855,18 @@ readobjnam(char *bp, struct obj *no_wish)
set_tin_variety(d.otmp, d.tvariety); set_tin_variety(d.otmp, d.tvariety);
if (d.name) { if (d.name) {
const char *aname; const char *aname, *novelname;
short objtyp; short objtyp;
/* an artifact name might need capitalization fixing */ /* an artifact name might need capitalization fixing */
aname = artifact_name(d.name, &objtyp); aname = artifact_name(d.name, &objtyp, TRUE);
if (aname && objtyp == d.otmp->otyp) if (aname && objtyp == d.otmp->otyp)
d.name = aname; d.name = aname;
/* 3.6 tribute - fix up novel */ /* 3.6 tribute - fix up novel */
if (d.otmp->otyp == SPE_NOVEL) { if (d.otmp->otyp == SPE_NOVEL
const char *novelname; && (novelname = lookup_novel(d.name, &d.otmp->novelidx)) != 0)
d.name = novelname;
novelname = lookup_novel(d.name, &d.otmp->novelidx);
if (novelname)
d.name = novelname;
}
d.otmp = oname(d.otmp, d.name, ONAME_WISH); d.otmp = oname(d.otmp, d.name, ONAME_WISH);
/* name==aname => wished for artifact (otmp->oartifact => got it) */ /* name==aname => wished for artifact (otmp->oartifact => got it) */