]> granicus.if.org Git - nethack/commitdiff
3.7: fix #9397 - pronouns when hallucinating
authorPatR <rankin@nethack.org>
Mon, 25 Nov 2019 02:29:14 +0000 (18:29 -0800)
committerPatR <rankin@nethack.org>
Mon, 25 Nov 2019 02:29:14 +0000 (18:29 -0800)
Developed for 3.6 but deferred to 3.7.  Most of the testing was with
the earlier incarnation.

Report was that pronouns were accurate for the underlying monsters
when hallucination was describing something random, and also that the
gender prefix flag from bogusmon.txt wasn't being used.  The latter
is still the case, but pronouns are now chosen at random while under
the influence of hallucination.  One of the choices is plural and an
attempt is made to make the monster name and verb fit that usage.

|The homunculus picks up a wand of speed monster.
|The large cats zap themselves with a wand of speed monster!
|The blue dragon is suddenly moving faster.

There is no attempt to match gender for the singular cases; you might
get
|The succubus zaps himself [...]
or
|The incubus zaps herself [...]

include/extern.h
include/you.h
src/apply.c
src/do_name.c
src/mondata.c
src/muse.c
src/objnam.c
src/role.c
src/steed.c

index a191b9acf5634836da833bd04b01b665c28dab8b..48c5db5221ed59b0ee7df0c9c0e57c45ded903c6 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1574646942 2019/11/25 01:55:42 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.759 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1574648937 2019/11/25 02:28:57 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.760 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -452,6 +452,8 @@ E char *FDECL(Amonnam, (struct monst *));
 E char *FDECL(a_monnam, (struct monst *));
 E char *FDECL(distant_monnam, (struct monst *, int, char *));
 E char *FDECL(mon_nam_too, (struct monst *, struct monst *));
+E char *FDECL(monverbself, (struct monst *, char *,
+                            const char *, const char *));
 E char *FDECL(minimal_monnam, (struct monst *, BOOLEAN_P));
 E char *FDECL(rndmonnam, (char *));
 E const char *FDECL(hcolor, (const char *));
@@ -1511,7 +1513,7 @@ E int FDECL(monsndx, (struct permonst *));
 E int FDECL(name_to_mon, (const char *));
 E int FDECL(name_to_monclass, (const char *, int *));
 E int FDECL(gender, (struct monst *));
-E int FDECL(pronoun_gender, (struct monst *, BOOLEAN_P));
+E int FDECL(pronoun_gender, (struct monst *, unsigned));
 E boolean FDECL(levl_follower, (struct monst *));
 E int FDECL(little_to_big, (int));
 E int FDECL(big_to_little, (int));
index 657b9c3e7b6dc6f8787043d52deab83a2c28c889..611fcf3b17acd9fbd0b20de965ecf0fa47133ed5 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 you.h   $NHDT-Date: 1547514642 2019/01/15 01:10:42 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.35 $ */
+/* NetHack 3.6 you.h   $NHDT-Date: 1574648937 2019/11/25 02:28:57 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.41 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -237,14 +237,21 @@ extern const struct Gender genders[]; /* table of available genders */
 #define uhe()      (genders[flags.female ? 1 : 0].he)
 #define uhim()     (genders[flags.female ? 1 : 0].him)
 #define uhis()     (genders[flags.female ? 1 : 0].his)
+/* pronoun_gender() flag masks */
+#define PRONOUN_NORMAL 0 /* none of the below */
+#define PRONOUN_NO_IT  1
+#define PRONOUN_HALLU  2
 /* corresponding pronouns for monsters; yields "it" when mtmp can't be seen */
-#define mhe(mtmp)  (genders[pronoun_gender(mtmp, FALSE)].he)
-#define mhim(mtmp) (genders[pronoun_gender(mtmp, FALSE)].him)
-#define mhis(mtmp) (genders[pronoun_gender(mtmp, FALSE)].his)
+#define mhe(mtmp)  (genders[pronoun_gender(mtmp, PRONOUN_HALLU)].he)
+#define mhim(mtmp) (genders[pronoun_gender(mtmp, PRONOUN_HALLU)].him)
+#define mhis(mtmp) (genders[pronoun_gender(mtmp, PRONOUN_HALLU)].his)
 /* override "it" if reason is lack of visibility rather than neuter species */
-#define noit_mhe(mtmp)  (genders[pronoun_gender(mtmp, TRUE)].he)
-#define noit_mhim(mtmp) (genders[pronoun_gender(mtmp, TRUE)].him)
-#define noit_mhis(mtmp) (genders[pronoun_gender(mtmp, TRUE)].his)
+#define noit_mhe(mtmp) \
+    (genders[pronoun_gender(mtmp, (PRONOUN_NO_IT | PRONOUN_HALLU))].he)
+#define noit_mhim(mtmp) \
+    (genders[pronoun_gender(mtmp, (PRONOUN_NO_IT | PRONOUN_HALLU))].him)
+#define noit_mhis(mtmp) \
+    (genders[pronoun_gender(mtmp, (PRONOUN_NO_IT | PRONOUN_HALLU))].his)
 
 /*** Unified structure specifying alignment information ***/
 struct Align {
index ecaccb741470c32bd1bfa20c43f81204faa07bc5..6451187e986139865e786b14ee7240e5125e7c29 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 apply.c $NHDT-Date: 1573778560 2019/11/15 00:42:40 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.284 $ */
+/* NetHack 3.6 apply.c $NHDT-Date: 1574648938 2019/11/25 02:28:58 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.301 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -212,7 +212,7 @@ int rx, ry, *resp;
             if (mtmp) {
                 mptr = mtmp->data = &mons[mtmp->mnum];
                 /* TRUE: override visibility check--it's not on the map */
-                gndr = pronoun_gender(mtmp, TRUE);
+                gndr = pronoun_gender(mtmp, PRONOUN_NO_IT);
             } else {
                 mptr = &mons[corpse->corpsenm];
                 if (is_female(mptr))
@@ -934,8 +934,9 @@ struct obj *obj;
         /* infravision doesn't produce an image in the mirror */
     } else if ((how_seen & SEENMON) == MONSEEN_INFRAVIS) {
         if (vis) /* (redundant) */
-            pline("%s is too far away to see %sself in the dark.",
-                  Monnam(mtmp), mhim(mtmp));
+            pline("%s in the dark.",
+                  monverbself(mtmp, Monnam(mtmp), "are",
+                              "too far away to see"));
         /* some monsters do special things */
     } else if (mlet == S_VAMPIRE || mlet == S_GHOST || is_vampshifter(mtmp)) {
         if (vis)
@@ -965,7 +966,8 @@ struct obj *obj;
         if (vis) {
             char buf[BUFSZ]; /* "She" or "He" */
 
-            pline("%s admires %sself in your %s.", Monnam(mtmp), mhim(mtmp),
+            pline("%s in your %s.", /* "<mon> admires self in your mirror " */
+                  monverbself(mtmp, Monnam(mtmp), "admire", (char *) 0),
                   mirror);
             pline("%s takes it!", upstart(strcpy(buf, mhe(mtmp))));
         } else
index 02ea4230b0fcd917c01c330ef7ef5b4691a39a13..cf812daa31dc5c67e24a1edf49dd9a139fb6fd74 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 do_name.c       $NHDT-Date: 1574419578 2019/11/22 10:46:18 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.152 $ */
+/* NetHack 3.6 do_name.c       $NHDT-Date: 1574648939 2019/11/25 02:28:59 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.167 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1959,7 +1959,7 @@ struct monst *mon, *other_mon;
         outbuf = mon_nam(mon);
     } else {
         outbuf = nextmbuf();
-        switch (pronoun_gender(mon, FALSE)) {
+        switch (pronoun_gender(mon, PRONOUN_HALLU)) {
         case 0:
             Strcpy(outbuf, "himself");
             break;
@@ -1967,13 +1967,49 @@ struct monst *mon, *other_mon;
             Strcpy(outbuf, "herself");
             break;
         default:
+        case 2:
             Strcpy(outbuf, "itself");
             break;
+        case 3: /* could happen when hallucinating */
+            Strcpy(outbuf, "themselves");
+            break;
         }
     }
     return outbuf;
 }
 
+/* construct "<monnamtext> <verb> <othertext> {him|her|it}self" which might
+   be distorted by Hallu; if that's plural, adjust monnamtext and verb */
+char *
+monverbself(mon, monnamtext, verb, othertext)
+struct monst *mon;
+char *monnamtext; /* modifiable 'mbuf' with adequare room at end */
+const char *verb, *othertext;
+{
+    char *verbs, selfbuf[40]; /* sizeof "themselves" suffices */
+
+    /* "himself"/"herself"/"itself", maybe "themselves" if hallucinating */
+    Strcpy(selfbuf, mon_nam_too(mon, mon));
+    /* verb starts plural; this will yield singular except for "themselves" */
+    verbs = vtense(selfbuf, verb);
+    if (!strcmp(verb, verbs)) { /* a match indicates that it stayed plural */
+        monnamtext = makeplural(monnamtext);
+        /* for "it", makeplural() produces "them" but we want "they" */
+        if (!strcmpi(monnamtext, genders[3].he)) {
+            boolean capitaliz = (monnamtext[0] == highc(monnamtext[0]));
+
+            Strcpy(monnamtext, genders[3].him);
+            if (capitaliz)
+                monnamtext[0] = highc(monnamtext[0]);
+        }
+    }
+    Strcat(strcat(monnamtext, " "), verbs);
+    if (othertext && *othertext)
+        Strcat(strcat(monnamtext, " "), othertext);
+    Strcat(strcat(monnamtext, " "), selfbuf);
+    return monnamtext;
+}
+
 /* for debugging messages, where data might be suspect and we aren't
    taking what the hero does or doesn't know into consideration */
 char *
index f510afcfd531032958aae85f2d027c6b9534b6bc..ba5b27d0aaf8023947bcfec5873b7f4aeb6065d4 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mondata.c       $NHDT-Date: 1550525093 2019/02/18 21:24:53 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.72 $ */
+/* NetHack 3.6 mondata.c       $NHDT-Date: 1574648940 2019/11/25 02:29:00 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.76 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -910,13 +910,20 @@ register struct monst *mtmp;
     return mtmp->female;
 }
 
-/* Like gender(), but lower animals and such are still "it".
-   This is the one we want to use when printing messages. */
+/* Like gender(), but unseen humanoids are "it" rather than "he" or "she"
+   and lower animals and such are "it" even when seen; hallucination might
+   yield "they".  This is the one we want to use when printing messages. */
 int
-pronoun_gender(mtmp, override_vis)
+pronoun_gender(mtmp, pg_flags)
 register struct monst *mtmp;
-boolean override_vis; /* if True then 'no it' unless neuter */
+unsigned pg_flags; /* flags&1: 'no it' unless neuter,
+                    * flags&2: random if hallucinating */
 {
+    boolean override_vis = (pg_flags & PRONOUN_NO_IT) ? TRUE : FALSE,
+            hallu_rand = (pg_flags & PRONOUN_HALLU) ? TRUE : FALSE;
+
+    if (hallu_rand && Hallucination)
+        return rn2(4); /* 0..3 */
     if (!override_vis && !canspotmon(mtmp))
         return 2;
     if (is_neuter(mtmp->data))
index 770e6b60d216e528dbcbacea74831d29f1cab057..25e29ed91ea3af74c96a4af65631971d2412853a 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 muse.c  $NHDT-Date: 1560161807 2019/06/10 10:16:47 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.96 $ */
+/* NetHack 3.6 muse.c  $NHDT-Date: 1574648940 2019/11/25 02:29:00 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.115 $ */
 /*      Copyright (C) 1990 by Ken Arromdee                         */
 /* NetHack may be freely redistributed.  See license for details.  */
 
@@ -161,7 +161,8 @@ boolean self;
                                  ? "nearby" : "distant");
         otmp->known = 0;
     } else if (self) {
-        pline("%s zaps %sself with %s!", Monnam(mtmp), mhim(mtmp),
+        pline("%s with %s!",
+              monverbself(mtmp, Monnam(mtmp), "zap", (char *) 0),
               doname(otmp));
     } else {
         pline("%s zaps %s!", Monnam(mtmp), an(xname(otmp)));
@@ -186,9 +187,15 @@ boolean self;
                  ? "nearby" : "in the distance");
         otmp->known = 0; /* hero doesn't know how many charges are left */
     } else {
+        char *objnamp, objbuf[BUFSZ];
+
         otmp->dknown = 1;
-        pline("%s plays a %s directed at %s!", Monnam(mtmp), xname(otmp),
-              self ? mon_nam_too(mtmp, mtmp) : (char *) "you");
+        objnamp = xname(otmp);
+        if (strlen(objnamp) >= QBUFSZ)
+            objnamp = simpleonames(otmp);
+        Sprintf(objbuf, "a %s directed at", objnamp);
+        /* "<mon> plays a <horn> directed at himself!" */
+        pline("%s!", monverbself(mtmp, Monnam(mtmp), "play", objbuf));
         makeknown(otmp->otyp); /* (wands handle this slightly differently) */
         if (!self)
             stop_occupation();
@@ -2461,7 +2468,7 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
     } else if (otyp == STRANGE_OBJECT) {
         /* monster is using fire breath on self */
         if (vis)
-            pline("%s breathes fire on %sself.", Monnam(mon), mhim(mon));
+            pline("%s.", monverbself(mon, Monnam(mon), "breath", "fire on"));
         if (!rn2(3))
             mon->mspec_used = rn1(10, 5);
         /* -21 => monster's fire breath; 1 => # of damage dice */
index 7aba0526c290cf7fad525d129534d0152066e5c3..64f8b473f8fa1deb8b86eda84bf4ebec3ab198ec 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 objnam.c        $NHDT-Date: 1573290418 2019/11/09 09:06:58 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.248 $ */
+/* NetHack 3.6 objnam.c        $NHDT-Date: 1574648942 2019/11/25 02:29:02 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.271 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -2310,7 +2310,7 @@ const char *oldstr;
     register char *spot;
     char lo_c, *str = nextobuf();
     const char *excess = (char *) 0;
-    int len;
+    int len, i;
 
     if (oldstr)
         while (*oldstr == ' ')
@@ -2320,6 +2320,26 @@ const char *oldstr;
         Strcpy(str, "s");
         return str;
     }
+    /* makeplural() is sometimes used on monsters rather than objects
+       and sometimes pronouns are used for monsters, so check those;
+       unfortunately, "her" (which matches genders[1].him and [1].his)
+       and "it" (which matches genders[2].he and [2].him) are ambiguous;
+       we'll live with that; caller can fix things up if necessary */
+    *str = '\0';
+    for (i = 0; i <= 2; ++i) {
+        if (!strcmpi(genders[i].he, oldstr))
+            Strcpy(str, genders[3].he); /* "they" */
+        else if (!strcmpi(genders[i].him, oldstr))
+            Strcpy(str, genders[3].him); /* "them" */
+        else if (!strcmpi(genders[i].his, oldstr))
+            Strcpy(str, genders[3].his); /* "their" */
+        if (*str) {
+            if (oldstr[0] == highc(oldstr[0]))
+                str[0] = highc(str[0]);
+            return str;
+        }
+    }
+
     Strcpy(str, oldstr);
 
     /*
@@ -2498,6 +2518,20 @@ const char *oldstr;
         str[0] = '\0';
         return str;
     }
+    /* makeplural() of pronouns isn't reversible but at least we can
+       force a singular value */
+    *str = '\0';
+    if (!strcmpi(genders[3].he, oldstr)) /* "they" */
+        Strcpy(str, genders[2].he); /* "it" */
+    else if (!strcmpi(genders[3].him, oldstr)) /* "them" */
+        Strcpy(str, genders[2].him); /* also "it" */
+    else if (!strcmpi(genders[3].his, oldstr)) /* "their" */
+        Strcpy(str, genders[2].his); /* "its" */
+    if (*str) {
+        if (oldstr[0] == highc(oldstr[0]))
+            str[0] = highc(str[0]);
+        return str;
+    }
 
     bp = strcpy(str, oldstr);
 
index 349c736b85f3f29c47b129191c0051e957bb15c5..a62d042a7d673e3c196bd5603addd51515834bb7 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 role.c  $NHDT-Date: 1547086250 2019/01/10 02:10:50 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.56 $ */
+/* NetHack 3.6 role.c  $NHDT-Date: 1574648943 2019/11/25 02:29:03 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.65 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -701,7 +701,9 @@ const struct Race races[] = {
 const struct Gender genders[] = {
     { "male", "he", "him", "his", "Mal", ROLE_MALE },
     { "female", "she", "her", "her", "Fem", ROLE_FEMALE },
-    { "neuter", "it", "it", "its", "Ntr", ROLE_NEUTER }
+    { "neuter", "it", "it", "its", "Ntr", ROLE_NEUTER },
+    /* used by pronoun_gender() when hallucinating */
+    { "group", "they", "them", "their", "Grp", 0 },
 };
 
 /* Table of all alignments */
index cc0c165cdbd90baa5df35d916be9cebe72c524bd..c145b09a140f7a57b48ed98f2207c256c7eb9954 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 steed.c $NHDT-Date: 1573940541 2019/11/16 21:42:21 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.67 $ */
+/* NetHack 3.6 steed.c $NHDT-Date: 1574648944 2019/11/25 02:29:04 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.74 $ */
 /* Copyright (c) Kevin Hugo, 1998-1999. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -377,7 +377,7 @@ exercise_steed()
 void
 kick_steed()
 {
-    char He[4];
+    char He[BUFSZ]; /* monverbself() appends to the "He"/"She"/"It" value */
     if (!u.usteed)
         return;
 
@@ -400,7 +400,9 @@ kick_steed()
             if (u.usteed->msleeping || !u.usteed->mcanmove)
                 pline("%s stirs.", He);
             else
-                pline("%s rouses %sself!", He, mhim(u.usteed));
+                /* if hallucinating, might yield "He rouses herself" or
+                   "She rouses himself" */
+                pline("%s!", monverbself(u.usteed, He, "rouse", (char *) 0));
         } else
             pline("%s does not respond.", He);
         return;