From e1fbfcc8b592c2a88c93cbcc702697c35764681b Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 5 Apr 2017 12:44:55 -0700 Subject: [PATCH 1/9] fix #H5264 fix MSGTYPE handling was being suppressed, except during prompting when it was intended to be suppressed. --- doc/fixes36.1 | 1 + src/pline.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 7fa058915..5ad9d072a 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -403,6 +403,7 @@ DUMPLOG: RIP tombstone was printed for characters who survived (ascended, artifact creation violated illiterate conduct when artifact name was assigned, behavior intended only for creating Sting or Orcrist via naming tty: revert to pline() for issuing prompts (override MSGTYPE=hide differently) +previous tty-revert fix had the override test backwards, breaking MSGTYPE Platform- and/or Interface-Specific Fixes diff --git a/src/pline.c b/src/pline.c index 118ed82ee..2c174e672 100644 --- a/src/pline.c +++ b/src/pline.c @@ -145,7 +145,7 @@ VA_DECL(const char *, line) if ((pline_flags & SUPPRESS_HISTORY) == 0) dumplogmsg(line); #endif - if ((pline_flags & OVERRIDE_MSGTYPE) != 0) { + if ((pline_flags & OVERRIDE_MSGTYPE) == 0) { msgtyp = msgtype_type(line, no_repeat); if (msgtyp == MSGTYP_NOSHOW || (msgtyp == MSGTYP_NOREP && !strcmp(line, prevmsg))) From 5cb4168c580ceffb94d4b492ec47f27ebc8b98ed Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 8 Apr 2017 19:39:43 -0700 Subject: [PATCH 2/9] autodescribe vs detection Temporary map views for detection or #terrain allow moving the cursor around to get the brief location description provided by getpos's autodescribe feature and were doing so by forcing the 'autodescribe' option to True, then leaving it that way. Save the option value prior to such operations and restore it after instead of leaving it changed. --- doc/fixes36.1 | 2 ++ src/detect.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 5ad9d072a..ce42dc224 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -404,6 +404,8 @@ artifact creation violated illiterate conduct when artifact name was assigned, behavior intended only for creating Sting or Orcrist via naming 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 Platform- and/or Interface-Specific Fixes diff --git a/src/detect.c b/src/detect.c index a46cf47f9..def22469e 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 detect.c $NHDT-Date: 1463191981 2016/05/14 02:13:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */ +/* NetHack 3.6 detect.c $NHDT-Date: 1491705573 2017/04/09 02:39:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.76 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -59,13 +59,15 @@ int ter_typ; const char *ter_explain; { coord dummy_pos; /* don't care whether player actually picks a spot */ + boolean save_autodescribe; dummy_pos.x = u.ux, dummy_pos.y = u.uy; /* starting spot for getpos() */ + save_autodescribe = iflags.autodescribe; iflags.autodescribe = TRUE; iflags.terrainmode = ter_typ; getpos(&dummy_pos, FALSE, ter_explain); iflags.terrainmode = 0; - /* leave iflags.autodescribe 'on' even if previously 'off' */ + iflags.autodescribe = save_autodescribe; } /* extracted from monster_detection() so can be shared by do_vicinity_map() */ From 3fbcce5e87a13733ce31fde01d9aa52a400cdbad Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 8 Apr 2017 19:54:18 -0700 Subject: [PATCH 3/9] autodescribe vs DUMPLOG Keep getpos's autodescribe feedback out of the DUMPLOG message history. Unfortunately it still gets put in interface-specific message history and is liable to fill up the buffer there, forcing actual old messages to be flushed away. --- src/do_name.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/do_name.c b/src/do_name.c index 98293152e..34a853159 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -412,9 +412,10 @@ int cx, cy; cc.y = cy; if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) { (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords); - pline("%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf, - (iflags.getloc_travelmode && !is_valid_travelpt(cx,cy)) - ? " (no travel path)" : ""); + custompline(SUPPRESS_HISTORY, + "%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf, + (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy)) + ? " (no travel path)" : ""); curs(WIN_MAP, cx, cy); flush_screen(0); } From ad29017482a3eba6d7d566ae553b0456c345ebcc Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 11 Apr 2017 17:58:14 -0700 Subject: [PATCH 4/9] fix #H5333 - overview annotation for quest summons The automatic annotations supplied for various special levels were treating the quest leader's summons as being mutually exclusive with the other things of interest. It's not, so wasn't shown if the entry portal was on either the bigroom level or the rogue level. Handle it differently from the rest so that it can stack with annotations for those levels. (The annotation for the portal itself, which doesn't get added until traversed, was already handled differently and shown correctly on those levels.) --- doc/fixes36.1 | 2 ++ src/dungeon.c | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index ce42dc224..5e6707bf8 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -370,6 +370,8 @@ g.cubes would eat globs of green slime without harm; engulf those instead fix up true rumor about rock moles vs boots Bell of Opening could trigger segfault attempting to open some types of traps if hero was mounted +automatic #overview annotation for quest summons wasn't shown if the quest + entry portal was on same level as bigroom or rogue level Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/dungeon.c b/src/dungeon.c index d3b603143..5b5e7c369 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dungeon.c $NHDT-Date: 1470275509 2016/08/04 01:51:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.76 $ */ +/* NetHack 3.6 dungeon.c $NHDT-Date: 1491958681 2017/04/12 00:58:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.79 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2951,8 +2951,6 @@ boolean printdun; Sprintf(buf, "%sA very big room.", PREFIX); } else if (mptr->flags.roguelevel) { Sprintf(buf, "%sA primitive area.", PREFIX); - } else if (mptr->flags.quest_summons) { - Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname()); } else if (on_level(&mptr->lev, &qstart_level)) { Sprintf(buf, "%sHome%s.", PREFIX, mptr->flags.unreachable ? " (no way back...)" : ""); @@ -2974,6 +2972,11 @@ boolean printdun; } if (*buf) putstr(win, 0, buf); + /* quest entrance is not mutually-exclusive with bigroom or rogue level */ + if (mptr->flags.quest_summons) { + Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname()); + putstr(win, 0, buf); + } /* print out branches */ if (mptr->br) { From 8fc7bc548c09390d1e638631450d23ded759ac7d Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 20 Apr 2017 17:06:28 -0700 Subject: [PATCH 5/9] setmangry fixes 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 | 2 ++ include/extern.h | 3 ++- src/mon.c | 68 ++++++++++++++++++++++++++++++------------------ src/mondata.c | 28 +++++++++++++++++++- 4 files changed, 73 insertions(+), 28 deletions(-) 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 From f533dbdecc250d52c0cd809aaeff442b98191c5a Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 29 Apr 2017 16:55:38 -0700 Subject: [PATCH 6/9] couple of formatting bits timeout.c: the luck timeout expression caused a bit of thought trying to decide whether it was doing what was intended (it was). Add some parentheses so that thought is no longer required. ;-) worn.c: fix up a macro where automated reformatting mistook a bitwise-and operation for a cast applied to the address of something. --- src/timeout.c | 4 ++-- src/worn.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/timeout.c b/src/timeout.c index 430784e5a..e5187e93b 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 timeout.c $NHDT-Date: 1456526165 2016/02/26 22:36:05 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.65 $ */ +/* NetHack 3.6 timeout.c $NHDT-Date: 1493510119 2017/04/29 23:55:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -249,7 +249,7 @@ nh_timeout() baseluck -= 1; if (u.uluck != baseluck - && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) { + && moves % ((u.uhave.amulet || u.ugangr) ? 300 : 600) == 0) { /* Cursed luckstones stop bad luck from timing out; blessed luckstones * stop good luck from timing out; normal luckstones stop both; * neither is stopped if you don't have a luckstone. diff --git a/src/worn.c b/src/worn.c index 947f367b9..a99d1336d 100644 --- a/src/worn.c +++ b/src/worn.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 worn.c $NHDT-Date: 1446887541 2015/11/07 09:12:21 $ $NHDT-Branch: master $:$NHDT-Revision: 1.47 $ */ +/* NetHack 3.6 worn.c $NHDT-Date: 1493510127 2017/04/29 23:55:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -31,11 +31,11 @@ const struct worn { { 0, 0 } }; /* This only allows for one blocking item per property */ -#define w_blocks(o, m) \ - ((o->otyp == MUMMY_WRAPPING && ((m) &W_ARMC)) \ - ? INVIS \ - : (o->otyp == CORNUTHAUM && ((m) &W_ARMH) && !Role_if(PM_WIZARD)) \ - ? CLAIRVOYANT \ +#define w_blocks(o, m) \ + ((o->otyp == MUMMY_WRAPPING && ((m) & W_ARMC)) \ + ? INVIS \ + : (o->otyp == CORNUTHAUM && ((m) & W_ARMH) && !Role_if(PM_WIZARD)) \ + ? CLAIRVOYANT \ : 0) /* note: monsters don't have clairvoyance, so your role has no significant effect on their use of w_blocks() */ From 6a8364f0255593a2b087201b0e366e36a9b22eae Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 4 May 2017 18:03:12 -0700 Subject: [PATCH 7/9] ^X/enlightenment tweaks Noticed while working on something else: You entered the dungeon N turns ago was missing the terminating period, and when polymorphed into a 1 hit die critter, plural "hit dice" is incorrect. 0 hit dice is confusing even when fully spelled out, so include an explanatory remark with it. Don't include score (available if configured with SCORE_ON_BOTL) unless player has the 'showscore' option enabled. The value is an approximation--accurate as far as it goes, but the value can change depending upon how the game ends. Someone who asks to have it displayed on the status line will probably be used to that, but others might start reporting bugs for it. --- doc/fixes36.1 | 2 ++ src/cmd.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 4e4eb01b8..3db597f9f 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -410,6 +410,8 @@ 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 +minor ^X/enlightenment bugs: grammar when poly'd into '1 hit dice' critter, + missing punctuation for "You entered the dungeon N turns ago" Platform- and/or Interface-Specific Fixes diff --git a/src/cmd.c b/src/cmd.c index f9473e6a7..d88664664 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1457207033 2016/03/05 19:43:53 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.220 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1493946186 2017/05/05 01:03:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.255 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1586,7 +1586,10 @@ int final; } } -/* characteristics: expanded version of bottom line strength, dexterity, &c */ +/* characteristics: expanded version of bottom line strength, dexterity, &c; + [3.6.1: now includes all status info (except things already shown in the + 'background' section), primarily so that blind players can suppress the + status line(s) altogether and use ^X feedback on demand to view HP, &c] */ STATIC_OVL void characteristics_enlightenment(mode, final) int mode; @@ -1612,22 +1615,39 @@ int final; enl_msg("Your armor class ", "is ", "was ", buf, ""); if (Upolyd) { - Sprintf(buf, "%d hit dice", mons[u.umonnum].mlevel); + switch (mons[u.umonnum].mlevel) { + case 0: + /* status line currently being explained shows "HD:0" */ + Strcpy(buf, "0 hit dice (actually 1/2)"); + break; + case 1: + Strcpy(buf, "1 hit die"); + break; + default: + Sprintf(buf, "%d hit dice", mons[u.umonnum].mlevel); + break; + } } else { /* flags.showexp does not matter */ /* experience level is already shown in the Background section */ Sprintf(buf, "%-1ld experience point%s", - u.uexp, u.uexp == 1 ? "" : "s"); + u.uexp, plur(u.uexp)); } you_have(buf, ""); - Sprintf(buf, " You entered the dungeon %ld turn%s ago", - moves, moves == 1 ? "" : "s"); - putstr(en_win, 0, buf); + /* this is shown even if the 'time' option is off */ + Sprintf(buf, "the dungeon %ld turn%s ago", moves, plur(moves)); + /* same phrasing at end of game: "entered" is unconditional */ + enlght_line(You_, "entered ", buf, ""); #ifdef SCORE_ON_BOTL - Sprintf(buf, "%ld", botl_score()); - enl_msg("Your score ", "is ", "was ", buf, ""); + if (flags.showscore) { + /* describes what's shown on status line, which is an approximation; + only show it here if player has the 'showscore' option enabled */ + Sprintf(buf, "%ld%s", botl_score(), + !final ? "" : " before end-of-game adjustments"); + enl_msg("Your score ", "is ", "was ", buf, ""); + } #endif /* bottom line order */ From 35d9cd3fd02937a54c8f44086fe3e9bbaf6c3d63 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 5 May 2017 18:32:40 -0700 Subject: [PATCH 8/9] fix #H5416 - misleading attribute message Report was for losing strength when sitting on a throne, but the message issue was more general than that. Character was wearing gauntlets of power, so no visible change in strength took place, but player was told "you're already as weak as you can get" (because the attempt to reduce strength didn't change current strength; however, it did change the hero's underlying strength, observable once the gloves were removed). There was a beta report last January that was related: in that case the player thought that gauntlets of power were preventing blessed potion of gain ability from raising strength, but it was actually giving a misleading message claiming that strength was already as high as it could get. Fix: vary the message when something prevents an attribute change from being noticeable. --- doc/fixes36.1 | 2 ++ src/attrib.c | 46 +++++++++++++++++++++++++++++++++++----------- src/cmd.c | 13 ++++--------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 3db597f9f..e25a866ae 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -372,6 +372,8 @@ Bell of Opening could trigger segfault attempting to open some types of traps if hero was mounted automatic #overview annotation for quest summons wasn't shown if the quest entry portal was on same level as bigroom or rogue level +gaining or losing strength while wearing gauntlets of power could give + misleading message about already being as strong or weak as possible Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/attrib.c b/src/attrib.c index c87afb683..e0021632f 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 attrib.c $NHDT-Date: 1455357587 2016/02/13 09:59:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.55 $ */ +/* NetHack 3.6 attrib.c $NHDT-Date: 1494034337 2017/05/06 01:32:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.62 $ */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -14,6 +14,10 @@ static const char *const minusattr[] = { "weak", "stupid", "foolish", "clumsy", "fragile", "repulsive" }; +/* also used by enlightenment for non-abbreviated status info */ +const char + *const attrname[] = { "strength", "intelligence", "wisdom", + "dexterity", "constitution", "charisma" }; static const struct innate { schar ulevel; @@ -111,7 +115,7 @@ adjattrib(ndx, incr, msgflg) int ndx, incr; int msgflg; /* positive => no message, zero => message, and */ { /* negative => conditional (msg if change made) */ - int old_acurr; + int old_acurr, old_abase; boolean abonflg; const char *attrstr; @@ -125,6 +129,7 @@ int msgflg; /* positive => no message, zero => message, and */ } old_acurr = ACURR(ndx); + old_abase = ABASE(ndx); if (incr > 0) { ABASE(ndx) += incr; if (ABASE(ndx) > AMAX(ndx)) { @@ -149,9 +154,14 @@ int msgflg; /* positive => no message, zero => message, and */ abonflg = (ABON(ndx) > 0); } if (ACURR(ndx) == old_acurr) { - if (msgflg == 0 && flags.verbose) - pline("You're %s as %s as you can get.", - abonflg ? "currently" : "already", attrstr); + if (msgflg == 0 && flags.verbose) { + if (ABASE(ndx) == old_abase) + pline("You're %s as %s as you can get.", + abonflg ? "currently" : "already", attrstr); + else /* current stayed the same but base value changed */ + Your("innate %s has %s.", attrname[ndx], + (incr > 0) ? "improved" : "declined"); + } return FALSE; } @@ -223,16 +233,28 @@ int typ; /* which attribute */ boolean exclaim; /* emphasis */ { void VDECL((*func), (const char *, ...)) = poiseff[typ].delivery_func; + const char *msg_txt = poiseff[typ].effect_msg; - (*func)("%s%c", poiseff[typ].effect_msg, exclaim ? '!' : '.'); + /* + * "You feel weaker" or "you feel very sick" aren't appropriate when + * wearing or wielding something (gauntlets of power, Ogresmasher) + * which forces the attribute to maintain its maximum value. + * Phrasing for other attributes which might have fixed values + * (dunce cap) is such that we don't need message fixups for them. + */ + if (typ == A_STR && ACURR(A_STR) == STR19(25)) + msg_txt = "innately weaker"; + else if (typ == A_CON && ACURR(A_CON) == 25) + msg_txt = "sick inside"; + + (*func)("%s%c", msg_txt, exclaim ? '!' : '.'); } -/* called when an attack or trap has poisoned the hero (used to be in mon.c) - */ +/* called when an attack or trap has poisoned hero (used to be in mon.c) */ void poisoned(reason, typ, pkiller, fatal, thrown_weapon) const char *reason, /* controls what messages we display */ - *pkiller; /* for score+log file if fatal */ + *pkiller; /* for score+log file if fatal */ int typ, fatal; /* if fatal is 0, limit damage to adjattrib */ boolean thrown_weapon; /* thrown weapons are less deadly */ { @@ -671,7 +693,9 @@ int r; { 0, 0 } }; int i; - for (i = 0; roleabils[i].abil && roleabils[i].role != r; i++); + + for (i = 0; roleabils[i].abil && roleabils[i].role != r; i++) + continue; return roleabils[i].abil; } @@ -996,7 +1020,7 @@ int x; #ifdef WIN32_BUG return (x = ((tmp <= 3) ? 3 : tmp)); #else - return (schar) ((tmp <= 3) ? 3 : tmp); + return (schar) ((tmp <= 3) ? 3 : tmp); #endif } else if (x == A_CHA) { if (tmp < 18 diff --git a/src/cmd.c b/src/cmd.c index d88664664..048fc5bbd 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1493946186 2017/05/05 01:03:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.255 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1494034344 2017/05/06 01:32:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.256 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1664,9 +1664,10 @@ STATIC_OVL void one_characteristic(mode, final, attrindx) int mode, final, attrindx; { + extern const char *const attrname[]; /* attrib.c */ boolean hide_innate_value = FALSE, interesting_alimit; int acurrent, abase, apeak, alimit; - const char *attrname, *paren_pfx; + const char *paren_pfx; char subjbuf[BUFSZ], valubuf[BUFSZ], valstring[32]; /* being polymorphed or wearing certain cursed items prevents @@ -1684,30 +1685,24 @@ int mode, final, attrindx; } switch (attrindx) { case A_STR: - attrname = "strength"; if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER && uarmg->cursed) hide_innate_value = TRUE; break; case A_DEX: - attrname = "dexterity"; break; case A_CON: - attrname = "constitution"; if (uwep && uwep->oartifact == ART_OGRESMASHER && uwep->cursed) hide_innate_value = TRUE; break; case A_INT: - attrname = "intelligence"; if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed) hide_innate_value = TRUE; break; case A_WIS: - attrname = "wisdom"; if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed) hide_innate_value = TRUE; break; case A_CHA: - attrname = "charisma"; break; default: return; /* impossible */ @@ -1718,7 +1713,7 @@ int mode, final, attrindx; acurrent = ACURR(attrindx); (void) attrval(attrindx, acurrent, valubuf); /* Sprintf(valubuf,"%d",) */ - Sprintf(subjbuf, "Your %s ", attrname); + Sprintf(subjbuf, "Your %s ", attrname[attrindx]); if (!hide_innate_value) { /* show abase, amax, and/or attrmax if acurr doesn't match abase From f6b32bf03c3b1d70fd23ca793cead63f8d015d81 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 6 May 2017 14:47:28 -0700 Subject: [PATCH 9/9] fix #H5245 - levitation boots message sequencing Report was for You finish taking off your boots. You float gently to the altar. [destination was a red herring] [take some action to run through moveloop() for next turn] Your movements are slowed slightly because of your load. Having float_down() do the next encumbrance check instead of waiting for moveloop() to do so was straightforward. However, while testing I noticed the reverse situation (not due to the fix for the above) when putting on levitation boots Your movements are now unencumbered. You finish your dressing maneuver. You start to float in the air! Having float_up() do the encumbrance check isn't adequate to fix this, because it takes multiple turns to put on boots but the properties they confer are enabled immediately, so moveloop() runs while hero is already levitating even though the game hasn't told the player about it yet. Fix is a hack to defer the effect of levitation on encumbrance until the boots are fully worn, which might lead to strangeness somewhere. It's also boot-specific so will need to be updated if some other multi-turn armor that confers levitation ever gets added. --- doc/fixes36.1 | 4 ++++ include/extern.h | 3 ++- src/do_wear.c | 7 +++---- src/hack.c | 33 ++++++++++++++++++++++++++------- src/trap.c | 12 +++++++++++- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index e25a866ae..ddad2f371 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -374,6 +374,10 @@ automatic #overview annotation for quest summons wasn't shown if the quest entry portal was on same level as bigroom or rogue level gaining or losing strength while wearing gauntlets of power could give misleading message about already being as strong or weak as possible +levitation vs encumbrance message sequencing issues: putting on boots of + levitation reported reduction of encumbrance before finish-wearing + and float-up messages, taking off such boots didn't report increase + of encumbrance until player took another action Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 5de433ee8..e8e15e701 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1492733169 2017/04/21 00:06:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.586 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1494107197 2017/05/06 21:46:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.587 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -439,6 +439,7 @@ E int NDECL(Armor_off); E int NDECL(Armor_gone); E int NDECL(Helmet_off); E int NDECL(Gloves_off); +E int NDECL(Boots_on); E int NDECL(Boots_off); E int NDECL(Cloak_off); E int NDECL(Shield_off); diff --git a/src/do_wear.c b/src/do_wear.c index 15f00bbee..f0c1038dc 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do_wear.c $NHDT-Date: 1455667557 2016/02/17 00:05:57 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.90 $ */ +/* NetHack 3.6 do_wear.c $NHDT-Date: 1494107204 2017/05/06 21:46:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.94 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,7 +23,7 @@ STATIC_DCL void FDECL(on_msg, (struct obj *)); STATIC_DCL void FDECL(toggle_stealth, (struct obj *, long, BOOLEAN_P)); STATIC_DCL void FDECL(toggle_displacement, (struct obj *, long, BOOLEAN_P)); STATIC_PTR int NDECL(Armor_on); -STATIC_PTR int NDECL(Boots_on); +/* int NDECL(Boots_on); -- moved to extern.h */ STATIC_PTR int NDECL(Cloak_on); STATIC_PTR int NDECL(Helmet_on); STATIC_PTR int NDECL(Gloves_on); @@ -148,7 +148,6 @@ boolean on; * [Blindf_on() is an exception and calls setworn() itself.] */ -STATIC_PTR int Boots_on(VOID_ARGS) { @@ -1274,7 +1273,7 @@ cancel_don() context.takeoff.cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on || afternmv == Gloves_on || afternmv == Armor_on); - afternmv = 0; + afternmv = (int NDECL((*))) 0; nomovemsg = (char *) 0; multi = 0; context.takeoff.delay = 0; diff --git a/src/hack.c b/src/hack.c index 1c7e44804..a250d86de 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1464485934 2016/05/29 01:38:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.168 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1494107206 2017/05/06 21:46:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.174 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -552,10 +552,10 @@ dosinkfall() /* * Interrupt multi-turn putting on/taking off of armor (in which * case we reached the sink due to being teleported while busy; - * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when + * in 3.4.3, Boots_on()/Boots_off() [called via (*afternmv)() when * 'multi' reaches 0] triggered a crash if we were donning/doffing * levitation boots [because the Boots_off() below causes 'uarmf' - * to be null by the time 'aftermv' gets called]). + * to be null by the time 'afternmv' gets called]). * * Interrupt donning/doffing if we fall onto the sink, or if the * code below is going to remove levitation boots even when we @@ -2766,9 +2766,13 @@ const char *msg_override; nomovemsg = 0; u.usleep = 0; multi_reason = NULL; - if (afternmv) - (*afternmv)(); - afternmv = 0; + if (afternmv) { + int NDECL((*f)) = afternmv; + /* clear afternmv before calling it (to override the + encumbrance hack for levitation--see weight_cap()) */ + afternmv = (int NDECL((*))) 0; + (void) (*f)(); + } } STATIC_OVL void @@ -2843,7 +2847,16 @@ boolean k_format; int weight_cap() { - register long carrcap; + long carrcap, save_ELev = ELevitation; + + /* boots take multiple turns to wear but any properties they + confer are enabled at the start rather than the end; that + causes message sequencing issues for boots of levitation + so defer their encumbrance benefit until they're fully worn */ + if (afternmv == Boots_on && (ELevitation & W_ARMF) != 0L) { + ELevitation &= ~W_ARMF; + float_vs_flight(); /* in case Levitation is blocking Flying */ + } carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50; if (Upolyd) { @@ -2873,6 +2886,12 @@ weight_cap() if (carrcap < 0) carrcap = 0; } + + if (ELevitation != save_ELev) { + ELevitation = save_ELev; + float_vs_flight(); + } + return (int) carrcap; } diff --git a/src/trap.c b/src/trap.c index 2c9b4e511..ddf065a0c 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 trap.c $NHDT-Date: 1489745987 2017/03/17 10:19:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.277 $ */ +/* NetHack 3.6 trap.c $NHDT-Date: 1494107206 2017/05/06 21:46:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.278 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2794,6 +2794,9 @@ float_up() if (Flying) You("are no longer able to control your flight."); BFlying |= I_SPECIAL; + /* levitation gives maximum carrying capacity, so encumbrance + state might be reduced */ + (void) encumber_msg(); return; } @@ -2837,12 +2840,14 @@ long hmask, emask; /* might cancel timeout */ BFlying &= ~I_SPECIAL; if (Flying) { You("have stopped levitating and are now flying."); + (void) encumber_msg(); /* carrying capacity might have changed */ return 1; } } if (u.uswallow) { You("float down, but you are still %s.", is_animal(u.ustuck->data) ? "swallowed" : "engulfed"); + (void) encumber_msg(); return 1; } @@ -2924,6 +2929,11 @@ long hmask, emask; /* might cancel timeout */ } } + /* levitation gives maximum carrying capacity, so having it end + potentially triggers greater encumbrance; do this after + 'come down' messages, before trap activation or autopickup */ + (void) encumber_msg(); + /* can't rely on u.uz0 for detecting trap door-induced level change; it gets changed to reflect the new level before we can check it */ assign_level(¤t_dungeon_level, &u.uz);