diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 5e6707bf8..4e4eb01b8 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 diff --git a/include/extern.h b/include/extern.h index 82765df78..5de433ee8 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/mon.c b/src/mon.c index ebb680780..8276d4792 100644 --- 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); } } } diff --git a/src/mondata.c b/src/mondata.c index a9d054f4c..32ea5bccc 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -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