]> granicus.if.org Git - nethack/commitdiff
setmangry fixes
authorPatR <rankin@nethack.org>
Fri, 21 Apr 2017 00:06:28 +0000 (17:06 -0700)
committerPatR <rankin@nethack.org>
Fri, 21 Apr 2017 00:06:28 +0000 (17:06 -0700)
Some discussion in the newsgroup about nearby peaceful monsters becoming
hostile if they observed the hero attacking a peaceful monster made me
look at the code and I spotted a couple of problems.  An auto array was
being initialized in an inner block--some pre-ANSI compilers couldn't
handle that.  Worse, it was inside a loop and may or may not have
resulted in unnecessary setup each iteration.  Make it static.  Oddly,
the array had the same name as a function but `gcc -Wshadow' either
didn't notice or didn't care.

A more significant problem was that mon->mpeaceful was being set to 0
without checking whether mon->mtame was set, potentially resulting in
humanoid pets being both tame and hostile at the same time.  This change
prevents that but doesn't do anything interesting about pets who observe
attacks against peacefuls.  (I also wonder why chaotic peacefuls now get
upset by seeing other peacefuls be attacked; it seems out of character.)

There was also a check for non-humanoid peacefuls seeing another of the
same species be attacked, but it was checking for an exact match without
regard for littler or bigger incarnations of the same species.  I've
added the latter.

This also reformats a couple of block comments.

doc/fixes36.1
include/extern.h
src/mon.c
src/mondata.c

index 5e6707bf89970d63c0e0955495a9d6bdc2fd104c..4e4eb01b8fd203ab4faf141fed161c23f879b9f1 100644 (file)
@@ -408,6 +408,8 @@ tty: revert to pline() for issuing prompts (override MSGTYPE=hide differently)
 previous tty-revert fix had the override test backwards, breaking MSGTYPE
 save 'autodescribe' option value prior to detection or #terrain display and
        restore it after rather than leave it forced on
+humanoid pet could become hostile but still remain tame if it observed hero
+       attacking a peaceful creature
 
 
 Platform- and/or Interface-Specific Fixes
index 82765df78b248864ed664f587a209684fb1197b0..5de433ee835053b98327ed6dab0290f1e8c01d7b 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1490908458 2017/03/30 21:14:18 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.585 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1492733169 2017/04/21 00:06:09 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.586 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1421,6 +1421,7 @@ E int FDECL(pronoun_gender, (struct monst *));
 E boolean FDECL(levl_follower, (struct monst *));
 E int FDECL(little_to_big, (int));
 E int FDECL(big_to_little, (int));
+E boolean FDECL(big_little_match, (int, int));
 E const char *FDECL(locomotion, (const struct permonst *, const char *));
 E const char *FDECL(stagger, (const struct permonst *, const char *));
 E const char *FDECL(on_fire, (struct permonst *, struct attack *));
index ebb680780e223edf1113c69c2dda7aebb1d53cd8..8276d4792410f73ae12e4d786d6a9f477d1fc2f8 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mon.c   $NHDT-Date: 1466289475 2016/06/18 22:37:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.227 $ */
+/* NetHack 3.6 mon.c   $NHDT-Date: 1492733171 2017/04/21 00:06:11 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.237 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2606,9 +2606,9 @@ struct monst *mtmp;
 
 /* Called whenever the player attacks mtmp; also called in other situations
    where mtmp gets annoyed at the player. Handles mtmp getting annoyed at the
-   attack and any ramifications that might have. Useful also in situations where
-   mtmp was already hostile; it checks for situations where the player shouldn't
-   be attacking and any ramifications /that/ might have. */
+   attack and any ramifications that might have. Useful also in situations
+   where mtmp was already hostile; it checks for situations where the player
+   shouldn't be attacking and any ramifications /that/ might have. */
 void
 setmangry(mtmp, via_attack)
 struct monst *mtmp;
@@ -2616,13 +2616,13 @@ boolean via_attack;
 {
     if (via_attack && sengr_at("Elbereth", u.ux, u.uy, TRUE)) {
         You_feel("like a hypocrite.");
-        /* AIS: Yes, I know alignment penalties and bonuses aren't balanced at
-           the moment. This is about correct relative to other "small"
-           penalties; it should be fairly large, as attacking while standing on
-           an Elbereth means that you're requesting peace and then violating
-           your own request. I know 5 isn't actually large, but it's
-           intentionally larger than the 1s and 2s that are normally given for
-           this sort of thing. */
+        /* AIS: Yes, I know alignment penalties and bonuses aren't balanced
+           at the moment. This is about correct relative to other "small"
+           penalties; it should be fairly large, as attacking while standing
+           on an Elbereth means that you're requesting peace and then
+           violating your own request. I know 5 isn't actually large, but
+           it's intentionally larger than the 1s and 2s that are normally
+           given for this sort of thing. */
         adjalign(-5);
 
         if (!Blind)
@@ -2668,20 +2668,30 @@ boolean via_attack;
                     ++got_mad;
             }
         }
-        if (got_mad && !Hallucination)
-            pline_The("%s appear%s to be angry too...",
-                      got_mad == 1 ? q_guardian->mname
-                                   : makeplural(q_guardian->mname),
-                      got_mad == 1 ? "s" : "");
+        if (got_mad && !Hallucination) {
+            const char *who = q_guardian->mname;
+
+            if (got_mad > 1)
+                who = makeplural(who);
+            pline_The("%s %s to be angry too...",
+                      who, vtense(who, "appear"));
+        }
     }
 
     /* make other peaceful monsters react */
     if (!context.mon_moving) {
+        static const char *const Exclam[] = {
+            "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?",
+        };
         struct monst *mon;
+        int mndx = monsndx(mtmp->data);
 
         for (mon = fmon; mon; mon = mon->nmon) {
             if (DEADMONSTER(mon))
                 continue;
+            if (mon == mtmp) /* the mpeaceful test catches this since mtmp */
+                continue;    /* is no longer peaceful, but be explicit...  */
+
             if (!mindless(mon->data) && mon->mpeaceful
                 && couldsee(mon->mx, mon->my) && !mon->msleeping
                 && mon->mcansee && m_canseeu(mon)) {
@@ -2692,32 +2702,38 @@ boolean via_attack;
                         verbalize("Halt!  You're under arrest!");
                         (void) angry_guards(!!Deaf);
                     } else {
-                        const char *exclam[] = {
-                            "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?"
-                        };
                         if (!rn2(5)) {
-                            verbalize("%s", exclam[mon->m_id % SIZE(exclam)]);
+                            verbalize("%s", Exclam[mon->m_id % SIZE(Exclam)]);
                             exclaimed = TRUE;
                         }
-                        if (!mon->isshk && !mon->ispriest
-                            && (mon->data->mlevel < rn2(10))) {
-                            monflee(mon, rn2(50)+25, TRUE, !exclaimed);
+                        /* shopkeepers and temple priests might gasp in
+                           surprise, but they won't become angry here */
+                        if (mon->isshk || mon->ispriest)
+                            continue;
+
+                        if (mon->data->mlevel < rn2(10)) {
+                            monflee(mon, rn2(50) + 25, TRUE, !exclaimed);
                             exclaimed = TRUE;
                         }
-                        if (!mon->isshk && !mon->ispriest) {
+                        if (mon->mtame) {
+                            /* mustn't set mpeaceful to 0 as below;
+                               perhaps reduce tameness? */
+                        } else {
                             mon->mpeaceful = 0;
                             adjalign(-1);
                             if (!exclaimed)
                                 pline("%s gets angry!", Monnam(mon));
                         }
                     }
-                } else if ((mtmp->data == mon->data) && !rn2(3)) {
+                } else if (mon->data->mlet == mtmp->data->mlet
+                           && big_little_match(mndx, monsndx(mon->data))
+                           && !rn2(3)) {
                     if (!rn2(4)) {
                         growl(mon);
                         exclaimed = TRUE;
                     }
                     if (rn2(6))
-                        monflee(mon, rn2(25)+15, TRUE, !exclaimed);
+                        monflee(mon, rn2(25) + 15, TRUE, !exclaimed);
                 }
             }
         }
index a9d054f4cd2fa57f14c5d1f8d55bf727876f1a2d..32ea5bcccf6d74a9f02d2678923f572ce6d033f7 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mondata.c       $NHDT-Date: 1470966820 2016/08/12 01:53:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */
+/* NetHack 3.6 mondata.c       $NHDT-Date: 1492733172 2017/04/21 00:06:12 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.62 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1009,6 +1009,32 @@ int montype;
     return montype;
 }
 
+/* determine whether two permonst indices are part of the same progression;
+   existence of progressions with more than one step makes it a bit tricky */
+boolean
+big_little_match(montyp1, montyp2)
+int montyp1, montyp2;
+{
+    int l, b;
+
+    /* simplest case: both are same pm */
+    if (montyp1 == montyp2)
+        return TRUE;
+    /* assume it isn't possible to grow from one class letter to another */
+    if (mons[montyp1].mlet != mons[montyp2].mlet)
+        return FALSE;
+    /* check whether montyp1 can grow up into montyp2 */
+    for (l = montyp1; (b = little_to_big(l)) != l; l = b)
+        if (b == montyp2)
+            return TRUE;
+    /* check whether montyp2 can grow up into montyp1 */
+    for (l = montyp2; (b = little_to_big(l)) != l; l = b)
+        if (b == montyp1)
+            return TRUE;
+    /* neither grows up to become the other; no match */
+    return FALSE;
+}
+
 /*
  * Return the permonst ptr for the race of the monster.
  * Returns correct pointer for non-polymorphed and polymorphed