]> granicus.if.org Git - nethack/commitdiff
fix #K2203 - animals can talk
authorPatR <rankin@nethack.org>
Mon, 21 Sep 2020 01:38:31 +0000 (18:38 -0700)
committerPatR <rankin@nethack.org>
Mon, 21 Sep 2020 01:38:31 +0000 (18:38 -0700)
The code for peaceful monsters witnessing the hero attack another
peaceful monster and getting angry had a 20% of making them gasp in
surprise or exclaim "why?" in shock.  It was only requiring them to
have humanoid shape rather than checking for speech capability, so
peaceful zruty or minotaur, possibly other animals, could exclaim
comprehensibly.  Other things which shouldn't talk, like mummies,
would behave similarly.

This categorizes how a bunch of MS_foo types should react.  It has
only been lightly tested.

doc/fixes37.0
include/extern.h
src/mon.c
src/sounds.c

index 481ba00664d2b59fe7196143e8e1105ee0e16a17..5329e9833022716ab922e141a82d83b678413d34 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.304 $ $NHDT-Date: 1600469617 2020/09/18 22:53:37 $
+NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.305 $ $NHDT-Date: 1600652305 2020/09/21 01:38:25 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -251,6 +251,9 @@ turning into slime rendered hero as slime one turn too soon
 avoid potential infinite loop if hangup occurs at ring "right or left?" prompt
 randomize the turns where accessories and extrinsics affect nutrition
 handle being interrupted by approaching monsters more consistently
+if hero attacked a peaceful monster, some other peaceful monsters with humanoid
+       shape (minotaur, zruty, perhaps others) that witnessed it but which
+       shouldn't be capable of normal speech expressed their surprise audibly
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 121117674217b9e0ccccfa4ee4451f964ef3e672..0144874994034b2ba37fd7a5835ac045531c61cb 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 extern.h        $NHDT-Date: 1600468452 2020/09/18 22:34:12 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.857 $ */
+/* NetHack 3.7 extern.h        $NHDT-Date: 1600652305 2020/09/21 01:38:25 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.858 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2442,6 +2442,7 @@ E void FDECL(growl, (struct monst *));
 E void FDECL(yelp, (struct monst *));
 E void FDECL(whimper, (struct monst *));
 E void FDECL(beg, (struct monst *));
+E boolean FDECL(maybe_gasp, (struct monst *));
 E int NDECL(dotalk);
 E int NDECL(tiphat);
 #ifdef USER_SOUNDS
index 2df04ef293b6730d1672d6b4aa903f0b12529e44..e3d800b4c5cfd60f9df4c9c7add0bd4bfe91cdbf 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 mon.c   $NHDT-Date: 1599559379 2020/09/08 10:02:59 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.346 $ */
+/* NetHack 3.7 mon.c   $NHDT-Date: 1600652305 2020/09/21 01:38:25 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.347 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -84,6 +84,8 @@ const char *msg;
         }
         if (chk_geno && (g.mvitals[mndx].mvflags & G_GENOD) != 0)
             impossible("genocided %s in play (%s)", mons[mndx].mname, msg);
+        if (mtmp->mtame && !mtmp->mpeaceful)
+            impossible("tame %s is not peaceful (%s)", mons[mndx].mname, msg);
     }
     if (mtmp->isshk && !has_eshk(mtmp))
         impossible("shk without eshk (%s)", msg);
@@ -3182,9 +3184,6 @@ boolean via_attack;
 
     /* make other peaceful monsters react */
     if (!g.context.mon_moving) {
-        static const char *const Exclam[] = {
-            "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?",
-        };
         struct monst *mon;
         int mndx = monsndx(mtmp->data);
 
@@ -3205,8 +3204,7 @@ boolean via_attack;
                         (void) angry_guards(!!Deaf);
                     } else {
                         if (!rn2(5)) {
-                            verbalize("%s", Exclam[mon->m_id % SIZE(Exclam)]);
-                            exclaimed = TRUE;
+                            exclaimed = maybe_gasp(mon);
                         }
                         /* shopkeepers and temple priests might gasp in
                            surprise, but they won't become angry here */
@@ -3218,8 +3216,8 @@ boolean via_attack;
                             exclaimed = TRUE;
                         }
                         if (mon->mtame) {
-                            /* mustn't set mpeaceful to 0 as below;
-                               perhaps reduce tameness? */
+                            /* mustn't set mpeaceful to 0 as below;
+                               perhaps reduce tameness? */
                         } else {
                             mon->mpeaceful = 0;
                             adjalign(-1);
index 806d25129fdd36023d9a89bc7c80286ced91e003..0059743ce0963768e1464150693cd0860cf6db9b 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 sounds.c        $NHDT-Date: 1596498211 2020/08/03 23:43:31 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.101 $ */
+/* NetHack 3.7 sounds.c        $NHDT-Date: 1600652306 2020/09/21 01:38:26 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.102 $ */
 /*      Copyright (c) 1989 Janet Walz, Mike Threepoint */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -479,6 +479,75 @@ register struct monst *mtmp;
     }
 }
 
+/* hero has attacked a peaceful monster within 'mon's view */
+boolean
+maybe_gasp(mon)
+struct monst *mon;
+{
+    static const char *const Exclam[] = {
+        "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?",
+    };
+    struct permonst *mptr = mon->data;
+    int msound = mptr->msound;
+    boolean dogasp = FALSE;
+
+    /* other roles' guardians and cross-aligned priests don't gasp */
+    if ((msound == MS_GUARDIAN && mptr != &mons[g.urole.guardnum])
+        || (msound == MS_PRIEST && !p_coaligned(mon)))
+        msound = MS_SILENT;
+    /* co-aligned angels do gasp */
+    else if (msound == MS_CUSS && has_emin(mon)
+           && (p_coaligned(mon) ? !EMIN(mon)->renegade : EMIN(mon)->renegade))
+        msound = MS_HUMANOID;
+
+    /*
+     * Only called for humanoids so animal noise handling is ignored.
+     */
+    switch (msound) {
+    case MS_HUMANOID:
+    case MS_ARREST: /* Kops */
+    case MS_SOLDIER: /* solider, watchman */
+    case MS_GUARD: /* vault guard */
+    case MS_NURSE:
+    case MS_SEDUCE: /* nymph, succubus/incubus */
+    case MS_LEADER: /* quest leader */
+    case MS_GUARDIAN: /* leader's guards */
+    case MS_SELL: /* shopkeeper */
+    case MS_ORACLE:
+    case MS_PRIEST: /* temple priest, roaming aligned priest (not mplayer) */
+    case MS_BOAST: /* giants */
+    case MS_IMITATE: /* doppelganger, leocrotta, Aleax */
+        dogasp = TRUE;
+        break;
+    /* issue comprehensible word(s) if hero is similar type of creature */
+    case MS_ORC: /* used to be synonym for MS_GRUNT */
+    case MS_GRUNT: /* ogres, trolls, gargoyles, one or two others */
+    case MS_LAUGH: /* leprechaun, gremlin */
+    case MS_ROAR: /* dragon, xorn, owlbear */
+    /* capable of speech but only do so if hero is similar type */
+    case MS_DJINNI:
+    case MS_VAMPIRE: /* vampire in its own form */
+    case MS_WERE: /* lycanthrope in human form */
+    case MS_SPELL: /* titan, barrow wight, Nazgul, nalfeshnee */
+        dogasp = (mptr->mlet == g.youmonst.data->mlet);
+        break;
+    /* capable of speech but don't care if you attack peacefuls */
+    case MS_BRIBE:
+    case MS_CUSS:
+    case MS_RIDER:
+    case MS_NEMESIS:
+    /* can't speak */
+    case MS_SILENT:
+    default:
+        break;
+    }
+    if (dogasp) {
+        verbalize("%s", Exclam[mon->m_id % SIZE(Exclam)]);
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /* return True if mon is a gecko or seems to look like one (hallucination) */
 static boolean
 mon_is_gecko(mon)