redo magic whistle feedback

Give more information when magic whistle is already discovered and
applying it affects multiple pets, without much increase in verbosity.
For each of the three categories
 1) was already in view and moves to another spot still in view,
 2) was out of view and arrives at a spot within view,
 3) was in view but gets sent to a spot out of view,
show the pet by name (which might be "your <monst>" if it hasn't been
named) when there is just one, or "two creatures", "three...", "four...",
"several...", or "many..." when there are more than one.  The first
category with more than 1 says "creatures".  When there are additional
categories with more than 1, their part of the message says "others" if
prior part(s) already mention "creatures", or it says "other creatures"
if the prior part(s) only list pets by name.

For example
|Three creatures appear.
|Fido shifts location and Fang appears.
|Your pony shifts location and two other creatures appear.
|Many creatures shift locations, several others appear, and two others
disappear.
|Two creatures appear and two others disappear.
This commit is contained in:
PatR
2022-05-10 15:53:24 -07:00
parent 6d15142250
commit 97d884585c

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 apply.c $NHDT-Date: 1652091707 2022/05/09 10:21:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.374 $ */
/* NetHack 3.7 apply.c $NHDT-Date: 1652223183 2022/05/10 22:53:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.375 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -492,10 +492,17 @@ static void
magic_whistled(struct obj *obj)
{
struct monst *mtmp, *nextmon;
char buf[BUFSZ];
char buf[BUFSZ], *mnam,
shiftbuf[BUFSZ + sizeof "shifts location"],
appearbuf[BUFSZ + sizeof "appears"],
disappearbuf[BUFSZ + sizeof "disappears"];
boolean oseen, already_discovered = objects[obj->otyp].oc_name_known != 0;
int omx, omy, shift = 0, appear = 0, disappear = 0;
const char *one = 0;
/* need to copy (up to 3) names as they're collected rather than just
save pointers to them, otherwise churning through every mbuf[] might
clobber the ones we care about */
shiftbuf[0] = appearbuf[0] = disappearbuf[0] = '\0';
for (mtmp = fmon; mtmp; mtmp = nextmon) {
nextmon = mtmp->nmon; /* trap might kill mon */
@@ -513,8 +520,8 @@ magic_whistled(struct obj *obj)
}
oseen = canspotmon(mtmp);
if (oseen && !one)
one = upstart(y_monnam(mtmp));
if (oseen) /* get name in case it's one we'll remember */
mnam = y_monnam(mtmp); /* before mnexto(); it might disappear */
/* mimic must be revealed before we know whether it
actually moves because line-of-sight may change */
if (M_AP_TYPE(mtmp))
@@ -525,15 +532,17 @@ magic_whistled(struct obj *obj)
mtmp->mundetected = 0; /* reveal non-mimic hider iff it moved */
if (canspotmon(mtmp)) {
if (!one)
one = upstart(y_monnam(mtmp));
if (oseen)
++shift;
else
++appear;
mnam = y_monnam(mtmp);
if (oseen) {
if (++shift == 1)
Sprintf(shiftbuf, "%s shifts location", mnam);
} else {
if (++appear == 1)
Sprintf(appearbuf, "%s appears", mnam);
}
} else if (oseen) {
++disappear;
if (++disappear == 1)
Sprintf(disappearbuf, "%s disappears", mnam);
}
/*
* FIXME:
@@ -568,47 +577,59 @@ magic_whistled(struct obj *obj)
*/
buf[0] = '\0';
if (!already_discovered) {
/* message(s) handled by rloc(); if the only noticeable change was
/* message(s) were handled by rloc(); if only noticeable change was
pet(s) disappearing, the magic whistle won't become discovered */
if (shift + appear > 0)
makeknown(obj->otyp);
} else if (shift + appear > 0) {
/* rloc() message(s) were suppressed above so issue one now;
'one' should always be non-Null at this point */
if (shift + appear + disappear == 1 && one) {
Sprintf(buf, "%.99s %s", one,
appear ? "appears" : "shifts location");
} else {
Strcpy(buf, (shift == 1) ? "One creature shifts location"
: (shift > 1) ? "Some creatures shift locations"
: "");
if (shift == 0)
Strcpy(buf, (appear == 1) ? "One creature appears"
: (appear > 1) ? "Some creatures appear"
: "");
else if (appear > 0)
Sprintf(eos(buf), "%s%s",
disappear ? ", " : " and ",
(appear == 1) ? "another appears" : "others appear");
#if 0 /* this case can't happen; only get here when shift+appear > 0 */
if (shift == 0 && appear == 0)
Strcpy(buf, (disappear == 1) ? "One creature disappears"
: (disappear > 1) ? "Some creatures disappear"
: "");
else
#endif
if (disappear > 0)
Sprintf(eos(buf), "%s%s",
(shift && appear) ? ", and " : " and ",
(disappear == 1) ? "another disappears"
: "others disappear");
} else {
/* could use array of cardinal number names like wishcmdassist() but
extra precision above 3 or 4 seems pedantic; not used for 0 or 1 */
#define HowMany(n) (((n) < 2) ? "sqrt(-1)" \
: ((n) == 2) ? "two" \
: ((n) == 3) ? "three" \
: ((n) == 4) ? "four" \
: ((n) <= 7) ? "several" \
: "many")
/* magic whistle is already discovered so rloc() message(s)
were suppressed above; if any discernible relocation occured,
construct a message now and issue it below */
if (shift > 0) {
if (shift > 1)
Sprintf(shiftbuf, "%s creatures shift locations",
HowMany(shift));
copynchars(buf, upstart(shiftbuf), (int) sizeof buf - 1);
}
if (appear > 0) {
if (appear > 1)
/* shift==0: N creatures appear;
shift==1: Foo shifts location and N other creatures appear;
shift >1: M creatures shift locations and N others appear */
Sprintf(appearbuf, "%s %s appear", HowMany(appear),
(shift == 0) ? "creatures"
: (shift == 1) ? "other creatures"
: "others");
if (shift == 0)
copynchars(buf, upstart(appearbuf), (int) sizeof buf - 1);
else
Snprintf(eos(buf), sizeof buf - strlen(buf), "%s %s",
/* to get here: appear > 0 and shift != 0,
so "shifters, appearers" if disappear != 0
with ", and disappearers" yet to be appended,
or "shifters and appearers" otherwise */
disappear ? "," : " and", appearbuf);
}
if (disappear > 0) {
if (disappear > 1)
Sprintf(disappearbuf, "%s %s disappear", HowMany(disappear),
(shift == 0 && appear == 0) ? "creatures"
: (shift < 2 && appear < 2) ? "other creatures"
: "others");
if (shift + appear == 0)
copynchars(buf, upstart(disappearbuf), (int) sizeof buf - 1);
else
Snprintf(eos(buf), sizeof buf - strlen(buf), "%s and %s",
(shift && appear) ? "," : "", disappearbuf);
}
} else if (disappear > 0) {
/* none appeared or just shifted; 'one' should be non-Null */
if (shift + appear + disappear == 1 && one)
Sprintf(buf, "%.99s disappears", one);
else
Strcpy(buf, "Some creatures disappear");
}
if (*buf)
pline("%s.", buf);