fix #H7397 - pronoun for unseen shopkeeper

Most shop messages accurately identify the shopkeeper even when he
or she can't be seen, but some also include a pronoun reference that
ended up as "it" or "its" when not seen.  Extend pronoun selection
so that visibility can be ignored:  noit_mhe(mon), noit_mhim(mon),
and noit_mhis(mon).  Note that despite being called noit_foo(),
those will still return "it" if mon is neuter.

"Accurately identify shopkeeper" is misleading if the hero is
hallucinating; a random shopkeeper name is used then.  noit_foo()
yields the pronoun applicable to the actual shopkeeper and might
not match the gender of a hallucinatory name.  That could be fixed
in a couple of ways (add shk_mhe()/shk_mhim()/shk_mhis() and either
pass them the randomly chosen name so that they can figure out the
appropriate gender, or just have them use a random gender whenever
hallucinating) but I don't think that's worth bothering with.

A bunch of shop messages needed noit_foo(); only a couple of those
have actually been tested.  A bunch more were using shkname() at
the beginning of a sentence where Shknam() should be used instead.
(All the existing shk names are already capitalized so there's no
noticeable difference.)

The three places outside shk.c and vault.c which directly use
pronoun_gender() have been successfully tested.
This commit is contained in:
PatR
2018-09-24 15:15:04 -07:00
parent 3f5ef9bdf3
commit 8ce81a27ef
10 changed files with 94 additions and 90 deletions

View File

@@ -215,12 +215,9 @@ int rx, ry, *resp;
/* (most corpses don't retain the monster's sex, so
we're usually forced to use generic pronoun here) */
if (mtmp) {
mptr = &mons[mtmp->mnum];
/* can't use mhe() here; it calls pronoun_gender() which
expects monster to be on the map (visibility check) */
if ((humanoid(mptr) || (mptr->geno & G_UNIQ)
|| type_is_pname(mptr)) && !is_neuter(mptr))
gndr = (int) mtmp->female;
mptr = mtmp->data = &mons[mtmp->mnum];
/* TRUE: override visibility check--it's not on the map */
gndr = pronoun_gender(mtmp, TRUE);
} else {
mptr = &mons[corpse->corpsenm];
if (is_female(mptr))

View File

@@ -664,12 +664,8 @@ int x, y;
mon->mundetected = 0; /* wakeup() will handle mimic */
mnam = a_monnam(mon); /* after unhiding */
pronoun = mhim(mon);
pronoun = noit_mhim(mon);
if (!strcmp(mnam, "it")) {
/* mhim() uses pronoun_gender() which forces neuter if monster
can't be seen; we want him/her for humanoid sensed by touch */
if (!strcmp(pronoun, "it") && humanoid(mon->data))
pronoun = genders[mon->female].him;
mnam = !strcmp(pronoun, "it") ? "something" : "someone";
}
if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph))

View File

@@ -47,9 +47,10 @@ mon_nam_too(outbuf, mon, other_mon)
char *outbuf;
struct monst *mon, *other_mon;
{
Strcpy(outbuf, mon_nam(mon));
if (mon == other_mon)
switch (pronoun_gender(mon)) {
if (mon != other_mon)
Strcpy(outbuf, mon_nam(mon));
else
switch (pronoun_gender(mon, FALSE)) {
case 0:
Strcpy(outbuf, "himself");
break;

View File

@@ -2613,7 +2613,7 @@ struct monst *mon;
;
} else if (rn2(20) < ACURR(A_CHA)) {
pline("%s demands that you pay %s, but you refuse...",
noit_Monnam(mon), Blind ? (fem ? "her" : "him") : mhim(mon));
noit_Monnam(mon), noit_mhim(mon));
} else if (u.umonnum == PM_LEPRECHAUN) {
pline("%s tries to take your money, but fails...", noit_Monnam(mon));
} else {

View File

@@ -900,10 +900,13 @@ register struct monst *mtmp;
/* Like gender(), but lower animals and such are still "it".
This is the one we want to use when printing messages. */
int
pronoun_gender(mtmp)
pronoun_gender(mtmp, override_vis)
register struct monst *mtmp;
boolean override_vis; /* if True then 'no it' unless neuter */
{
if (is_neuter(mtmp->data) || !canspotmon(mtmp))
if (!override_vis && !canspotmon(mtmp))
return 2;
if (is_neuter(mtmp->data))
return 2;
return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
|| type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;

130
src/shk.c
View File

@@ -435,9 +435,9 @@ boolean newlev;
plname);
else
pline("%s %s that you need to pay before leaving%s",
Shknam(shkp),
NOTANGRY(shkp) ? "points out" : "makes it clear",
NOTANGRY(shkp) ? "." : "!");
Shknam(shkp),
NOTANGRY(shkp) ? "points out" : "makes it clear",
NOTANGRY(shkp) ? "." : "!");
return;
}
@@ -580,12 +580,12 @@ char *enterstring;
return; /* no dialog */
if (Invis) {
pline("%s senses your presence.", shkname(shkp));
pline("%s senses your presence.", Shknam(shkp));
if (!Deaf && !muteshk(shkp))
verbalize("Invisible customers are not welcome!");
else
pline("%s stands firm as if %s knows you are there.",
Shknam(shkp), mhe(shkp));
Shknam(shkp), noit_mhe(shkp));
return;
}
@@ -594,21 +594,18 @@ char *enterstring;
if (ANGRY(shkp)) {
if (!Deaf && !muteshk(shkp))
verbalize("So, %s, you dare return to %s %s?!", plname,
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
else
pline("%s seems %s over your return to %s %s!",
Shknam(shkp),
angrytexts[rn2(SIZE(angrytexts))],
mhis(shkp),
shtypes[rt - SHOPBASE].name);
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
noit_mhis(shkp), shtypes[rt - SHOPBASE].name);
} else if (eshkp->robbed) {
if (!Deaf)
pline("%s mutters imprecations against shoplifters.",
shkname(shkp));
Shknam(shkp));
else
pline("%s is combing through %s inventory list.",
Shknam(shkp),
mhis(shkp));
Shknam(shkp), noit_mhis(shkp));
} else {
if (!Deaf && !muteshk(shkp))
verbalize("%s, %s! Welcome%s to %s %s!", Hello(shkp), plname,
@@ -655,20 +652,20 @@ char *enterstring;
tool, plur(cnt));
else
pline("%s %s to let you in with your %s%s.",
Shknam(shkp),
NOTANGRY(shkp) ? "is hesitant" : "refuses",
tool, plur(cnt));
Shknam(shkp),
NOTANGRY(shkp) ? "is hesitant" : "refuses",
tool, plur(cnt));
should_block = TRUE;
} else if (u.usteed) {
if (!Deaf && !muteshk(shkp))
verbalize(NOTANGRY(shkp) ? "Will you please leave %s outside?"
: "Leave %s outside.",
y_monnam(u.usteed));
y_monnam(u.usteed));
else
pline("%s %s to let you in while you're riding %s.",
Shknam(shkp),
NOTANGRY(shkp) ? "doesn't want" : "refuses",
y_monnam(u.usteed));
Shknam(shkp),
NOTANGRY(shkp) ? "doesn't want" : "refuses",
y_monnam(u.usteed));
should_block = TRUE;
} else {
should_block =
@@ -1343,7 +1340,7 @@ proceed:
} else {
if (umoney > ltmp) {
You("give %s the %ld gold piece%s %s asked for.",
shkname(shkp), ltmp, plur(ltmp), mhe(shkp));
shkname(shkp), ltmp, plur(ltmp), noit_mhe(shkp));
pay(ltmp, shkp);
} else {
You("give %s all your%s gold.", shkname(shkp),
@@ -1353,7 +1350,8 @@ proceed:
pline("But you have hidden gold!");
}
if ((umoney < ltmp / 2L) || (umoney < ltmp && stashed_gold))
pline("Unfortunately, %s doesn't look satisfied.", mhe(shkp));
pline("Unfortunately, %s doesn't look satisfied.",
noit_mhe(shkp));
else
make_happy_shk(shkp, FALSE);
}
@@ -1373,13 +1371,14 @@ proceed:
if (!umoney)
pline(no_money, stashed_gold ? " seem to" : "");
else
pline(not_enough_money, mhim(shkp));
pline(not_enough_money, noit_mhim(shkp));
return 1;
}
pline("But since %s shop has been robbed recently,", mhis(shkp));
pline("But since %s shop has been robbed recently,",
noit_mhis(shkp));
pline("you %scompensate %s for %s losses.",
(umoney < ltmp) ? "partially " : "", shkname(shkp),
mhis(shkp));
noit_mhis(shkp));
pay(umoney < ltmp ? umoney : ltmp, shkp);
make_happy_shk(shkp, FALSE);
} else {
@@ -1390,11 +1389,14 @@ proceed:
if (!umoney)
pline(no_money, stashed_gold ? " seem to" : "");
else
pline(not_enough_money, mhim(shkp));
pline(not_enough_money, noit_mhim(shkp));
return 1;
}
You("try to appease %s by giving %s 1000 gold pieces.",
x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE), mhim(shkp));
canspotmon(shkp)
? x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE)
: shkname(shkp),
noit_mhim(shkp));
pay(1000L, shkp);
if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3))
make_happy_shk(shkp, FALSE);
@@ -1538,13 +1540,13 @@ proceed:
}
if (!ANGRY(shkp) && paid) {
if (!Deaf && !muteshk(shkp))
verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp)),
shtypes[eshkp->shoptype - SHOPBASE].name);
verbalize("Thank you for shopping in %s %s!",
s_suffix(shkname(shkp)),
shtypes[eshkp->shoptype - SHOPBASE].name);
else
pline("%s nods appreciatively at you for shopping in %s %s!",
Shknam(shkp),
mhis(shkp),
shtypes[eshkp->shoptype - SHOPBASE].name);
Shknam(shkp), noit_mhis(shkp),
shtypes[eshkp->shoptype - SHOPBASE].name);
}
return 1;
}
@@ -1778,7 +1780,7 @@ int croaked;
if (cansee(shkp->mx, shkp->my) && croaked) {
takes[0] = '\0';
if (has_head(shkp->data) && !rn2(2))
Sprintf(takes, ", shakes %s %s,", mhis(shkp),
Sprintf(takes, ", shakes %s %s,", noit_mhis(shkp),
mbodypart(shkp, HEAD));
pline("%s %slooks at your corpse%s and %s.", Shknam(shkp),
(!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
@@ -1797,7 +1799,7 @@ int croaked;
taken = (invent != 0);
if (taken)
pline("%s gratefully inherits all your possessions.",
shkname(shkp));
Shknam(shkp));
set_repo_loc(shkp);
goto clear;
}
@@ -1828,7 +1830,7 @@ int croaked;
if (umoney > 0)
money2mon(shkp, umoney);
context.botl = 1;
pline("%s %s all your possessions.", shkname(shkp), takes);
pline("%s %s all your possessions.", Shknam(shkp), takes);
taken = TRUE;
/* where to put player's invent (after disclosure) */
set_repo_loc(shkp);
@@ -1838,7 +1840,7 @@ int croaked;
pline("%s %s the %ld %s %sowed %s.", Shknam(shkp),
takes, loss, currency(loss),
strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "you ",
mhim(shkp));
noit_mhim(shkp));
/* shopkeeper has now been paid in full */
pacify_shk(shkp);
eshkp->following = 0;
@@ -2218,9 +2220,8 @@ boolean quietly;
verbalize("I won't stock that. Take it out of here!");
else
pline("%s shakes %s %s in refusal.",
Shknam(shkp),
mhis(shkp),
mbodypart(shkp, HEAD));
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HEAD));
}
}
return TRUE;
@@ -3010,7 +3011,7 @@ xchar x, y;
if (sell_how == SELL_NORMAL || auto_credit) {
c = sell_response = 'y';
} else if (sell_response != 'n') {
pline("%s cannot pay you at present.", shkname(shkp));
pline("%s cannot pay you at present.", Shknam(shkp));
Sprintf(qbuf, "Will you accept %ld %s in credit for ", tmpcr,
currency(tmpcr));
c = ynaq(safe_qbuf(qbuf, qbuf, "?", obj, doname, thesimpleoname,
@@ -3079,7 +3080,7 @@ xchar x, y;
"... your items in the <bag>. Sell them?"
*/
Sprintf(qbuf, "%s offers%s %ld gold piece%s for %s%s ",
shkname(shkp), short_funds ? " only" : "", offer,
Shknam(shkp), short_funds ? " only" : "", offer,
plur(offer),
(cltmp && !ltmp)
? ((yourc == 1L) ? "your item in " : "your items in ")
@@ -3650,8 +3651,7 @@ struct monst *shkp;
Hello(shkp), plname);
else
pline("%s holds out %s upturned %s.",
Shknam(shkp),
mhis(shkp),
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HAND));
followmsg = moves;
if (!rn2(9)) {
@@ -3805,7 +3805,7 @@ register int fall;
*/
if (lang == 2)
pline("%s curses %s inability to grab your backpack!",
shkname(shkp), mhim(shkp));
Shknam(shkp), noit_mhim(shkp));
rile_shk(shkp);
return;
#endif
@@ -3816,16 +3816,16 @@ register int fall;
if (distu(shkp->mx, shkp->my) > 2) {
if (lang == 2)
pline("%s curses you in anger and frustration!",
shkname(shkp));
Shknam(shkp));
else if (lang == 1)
growl(shkp);
rile_shk(shkp);
return;
} else
pline("%s %s, and %s your backpack!", shkname(shkp),
pline("%s %s, and %s your backpack!", Shknam(shkp),
makeplural(locomotion(shkp->data, "leap")), grabs);
} else
pline("%s %s your backpack!", shkname(shkp), grabs);
pline("%s %s your backpack!", Shknam(shkp), grabs);
for (obj = invent; obj; obj = obj2) {
obj2 = obj->nobj;
@@ -3957,7 +3957,7 @@ boolean cant_mollify;
if (uinshp) {
if (um_dist(shkp->mx, shkp->my, 1)
&& !um_dist(shkp->mx, shkp->my, 3)) {
pline("%s leaps towards you!", shkname(shkp));
pline("%s leaps towards you!", Shknam(shkp));
mnexto(shkp);
}
pursue = um_dist(shkp->mx, shkp->my, 1);
@@ -4004,16 +4004,16 @@ boolean cant_mollify;
else
pline("%s is %s that you decided to %s %s %s!",
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
dmgstr, mhis(shkp), dugwall ? "shop" : "door");
dmgstr, noit_mhis(shkp), dugwall ? "shop" : "door");
} else {
if (!Deaf) {
pline("%s shouts:", shkname(shkp));
pline("%s shouts:", Shknam(shkp));
verbalize("Who dared %s my %s?", dmgstr,
dugwall ? "shop" : "door");
} else {
pline("%s is %s that someone decided to %s %s %s!",
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
dmgstr, mhis(shkp), dugwall ? "shop" : "door");
dmgstr, noit_mhis(shkp), dugwall ? "shop" : "door");
}
}
hot_pursuit(shkp);
@@ -4039,10 +4039,8 @@ boolean cant_mollify;
verbalize("Oh, yes! You'll pay!");
else
pline("%s lunges %s %s toward your %s!",
Shknam(shkp),
mhis(shkp),
mbodypart(shkp, HAND),
body_part(NECK));
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HAND), body_part(NECK));
} else
growl(shkp);
hot_pursuit(shkp);
@@ -4221,9 +4219,9 @@ struct monst *shkp;
eshk = ESHK(shkp);
if (ANGRY(shkp)) {
pline("%s %s how much %s dislikes %s customers.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "mentions" : "indicates",
mhe(shkp), eshk->robbed ? "non-paying" : "rude");
noit_mhe(shkp), eshk->robbed ? "non-paying" : "rude");
} else if (eshk->following) {
if (strncmp(eshk->customer, plname, PL_NSIZ)) {
if (!Deaf && !muteshk(shkp))
@@ -4242,35 +4240,35 @@ struct monst *shkp;
register long total = addupbill(shkp) + eshk->debit;
pline("%s %s that your bill comes to %ld %s.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "says" : "indicates",
total, currency(total));
} else if (eshk->debit) {
pline("%s %s that you owe %s %ld %s.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "reminds you" : "indicates",
mhim(shkp), eshk->debit, currency(eshk->debit));
noit_mhim(shkp), eshk->debit, currency(eshk->debit));
} else if (eshk->credit) {
pline("%s encourages you to use your %ld %s of credit.",
shkname(shkp), eshk->credit, currency(eshk->credit));
Shknam(shkp), eshk->credit, currency(eshk->credit));
} else if (eshk->robbed) {
pline("%s %s about a recent robbery.",
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
} else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
pline("%s %s that business is bad.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
} else if (shkmoney > 4000) {
pline("%s %s that business is good.",
shkname(shkp),
Shknam(shkp),
(!Deaf && !muteshk(shkp)) ? "says" : "indicates");
} else if (is_izchak(shkp, FALSE)) {
if (!Deaf && !muteshk(shkp))
pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
} else {
if (!Deaf && !muteshk(shkp))
pline("%s talks about the problem of shoplifters.", shkname(shkp));
pline("%s talks about the problem of shoplifters.", Shknam(shkp));
}
}
@@ -4472,7 +4470,7 @@ register xchar x, y;
&& ESHK(shkp)->shd.y == y
&& shkp->mcanmove && !shkp->msleeping
&& (ESHK(shkp)->debit || ESHK(shkp)->billct || ESHK(shkp)->robbed)) {
pline("%s%s blocks your way!", shkname(shkp),
pline("%s%s blocks your way!", Shknam(shkp),
Invis ? " senses your motion and" : "");
return TRUE;
}
@@ -4509,7 +4507,7 @@ register xchar x, y;
&& (x == sx - 1 || x == sx + 1 || y == sy - 1 || y == sy + 1)
&& (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
|| u.usteed)) {
pline("%s%s blocks your way!", shkname(shkp),
pline("%s%s blocks your way!", Shknam(shkp),
Invis ? " senses your motion and" : "");
return TRUE;
}

View File

@@ -452,7 +452,8 @@ invault()
if (!Blind)
pline(
"%s holds out %s palm and beckons with %s other hand.",
noit_Monnam(guard), mhis(guard), mhis(guard));
noit_Monnam(guard), noit_mhis(guard),
noit_mhis(guard));
} else {
verbalize(
"Most likely all your gold was stolen from this vault.");
@@ -707,7 +708,7 @@ register struct monst *grd;
if (Deaf) {
if (!Blind)
pline("%s holds out %s palm demandingly!",
noit_Monnam(grd), mhis(grd));
noit_Monnam(grd), noit_mhis(grd));
} else {
verbalize("Drop all your gold, scoundrel!");
}
@@ -716,7 +717,7 @@ register struct monst *grd;
if (Deaf) {
if (!Blind)
pline("%s rubs %s hands with enraged delight!",
noit_Monnam(grd), mhis(grd));
noit_Monnam(grd), noit_mhis(grd));
} else {
verbalize("So be it, rogue!");
}