From 0b74f2adeba57262979cc8a39b06eab003e4d843 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 2 Jun 2019 17:21:35 -0400 Subject: [PATCH 01/16] makedefs: add enum support when generating pm.h Only changes pm.h content if ENUM_PM is defined when compiling util/makedefs.c While NON_PM and LOW_PM could be included, it would require for the makedefs.c compile, as well as an around their macro definitions in permonst.h so for now those particular lines are commented out in makedefs.c --- sys/winnt/Makefile.msc | 2 +- util/makedefs.c | 33 +++++++++++++++++++++++++++---- win/win32/vs2017/makedefs.vcxproj | 4 ++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 355fe9791..d2dd88414 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -924,7 +924,7 @@ $(O)makedefs.o: $(CONFIG_H) $(INCL)\monattk.h $(INCL)\monflag.h $(INCL)\objcla $(U)makedefs.c @if not exist $(OBJ)\*.* echo creating directory $(OBJ:\=/) @if not exist $(OBJ)\*.* mkdir $(OBJ) - @$(cc) $(cflagsBuild) -Fo$@ $(U)makedefs.c + @$(cc) -DENUM_PM $(cflagsBuild) -Fo$@ $(U)makedefs.c # # date.h should be remade every time any of the source or include diff --git a/util/makedefs.c b/util/makedefs.c index 744ace151..813b649e7 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -218,6 +218,13 @@ static int FDECL(case_insensitive_comp, (const char *, const char *)); /* input, output, tmp */ static FILE *ifp, *ofp, *tfp; +static boolean use_enum = +#ifdef ENUM_PM + TRUE; +#else + FALSE; +#endif + #if defined(__BORLANDC__) && !defined(_WIN32) extern unsigned _stklen = STKSIZ; #endif @@ -2337,10 +2344,20 @@ do_permonst() Fprintf(ofp, "%s", Dont_Edit_Code); Fprintf(ofp, "#ifndef PM_H\n#define PM_H\n"); + if (use_enum) { + Fprintf(ofp, "\nenum monnums {"); +#if 0 + /* need #define ENUM_PM for the full NetHack build to include these */ + Fprintf(ofp, "\n NON_PM = -1,"); + Fprintf(ofp, "\n LOW_PM = 0,"); +#endif + } for (i = 0; mons[i].mlet; i++) { SpinCursor(3); - - Fprintf(ofp, "\n#define\tPM_"); + if (use_enum) + Fprintf(ofp, "\n PM_"); + else + Fprintf(ofp, "\n#define\tPM_"); if (mons[i].mlet == S_HUMAN && !strncmp(mons[i].mname, "were", 4)) Fprintf(ofp, "HUMAN_"); for (nam = c = tmpdup(mons[i].mname); *c; c++) @@ -2348,9 +2365,17 @@ do_permonst() *c -= (char) ('a' - 'A'); else if (*c < 'A' || *c > 'Z') *c = '_'; - Fprintf(ofp, "%s\t%d", nam, i); + if (use_enum) + Fprintf(ofp, "%s = %d,", nam, i); + else + Fprintf(ofp, "%s\t%d", nam, i); + } + if (use_enum) { + Fprintf(ofp, "\n\n NUMMONS = %d", i); + Fprintf(ofp, "\n};\n"); + } else { + Fprintf(ofp, "\n\n#define\tNUMMONS\t%d\n", i); } - Fprintf(ofp, "\n\n#define\tNUMMONS\t%d\n", i); Fprintf(ofp, "\n#endif /* PM_H */\n"); Fclose(ofp); return; diff --git a/win/win32/vs2017/makedefs.vcxproj b/win/win32/vs2017/makedefs.vcxproj index 708802ec9..1f6c1c49f 100644 --- a/win/win32/vs2017/makedefs.vcxproj +++ b/win/win32/vs2017/makedefs.vcxproj @@ -26,7 +26,7 @@ $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) - WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + WIN32CON;DLB;MSWIN_GRAPHICS;ENUM_PM;%(PreprocessorDefinitions) @@ -59,4 +59,4 @@ - \ No newline at end of file + From 689e7490eca26cb5991d4682646ff398fc73bce7 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 3 Jun 2019 02:36:44 -0700 Subject: [PATCH 02/16] extended ball&chain sanity check Verify that the locations of ball and chain are consistent. If chain is on floor then ball is on floor or in hero's inventory else if chain is free then ball is free or in hero's inventory. When chain is on floor it is under hero or one step away from hero and when ball is on floor it is on chain or one step away from chain. --- src/ball.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/ball.c b/src/ball.c index 66ad2ffd8..ab1024a9a 100644 --- a/src/ball.c +++ b/src/ball.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 ball.c $NHDT-Date: 1558920171 2019/05/27 01:22:51 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.38 $ */ +/* NetHack 3.6 ball.c $NHDT-Date: 1559554598 2019/06/03 09:36:38 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.39 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) David Cohrs, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -853,7 +853,7 @@ drag_down() void bc_sanity_check() { - int otyp; + int otyp, freeball, freechain; const char *onam; if (Punished && (!uball || !uchain)) { @@ -867,11 +867,18 @@ bc_sanity_check() (uchain && uball) ? " and " : "", uball ? "iron ball" : ""); } - /* ball is free when swallowed, changing levels, other times? */ + /* ball is free when swallowed, when changing levels or during air bubble + management on Plane of Water (both of which start and end in between + sanity checking cycles, so shouldn't be relevant), other times? */ + freechain = (!uchain || uchain->where == OBJ_FREE); + freeball = (!uball || uball->where == OBJ_FREE + /* lie to simplify the testing logic */ + || (freechain && uball->where == OBJ_INVENT)); if (uball && (uball->otyp != HEAVY_IRON_BALL || (uball->where != OBJ_FLOOR && uball->where != OBJ_INVENT && uball->where != OBJ_FREE) + || (freeball ^ freechain) || (uball->owornmask & W_BALL) == 0L || (uball->owornmask & ~(W_BALL | W_WEAPON)) != 0L)) { otyp = uball->otyp; @@ -883,6 +890,7 @@ bc_sanity_check() if (uchain && (uchain->otyp != IRON_CHAIN || (uchain->where != OBJ_FLOOR && uchain->where != OBJ_FREE) + || (freechain ^ freeball) /* [could simplify this to owornmask != W_CHAIN] */ || (uchain->owornmask & W_CHAIN) == 0L || (uchain->owornmask & ~W_CHAIN) != 0L)) { @@ -891,6 +899,25 @@ bc_sanity_check() impossible("uchain: type %d (%s), where %d, wornmask=0x%08lx", otyp, onam, uchain->where, uchain->owornmask); } + if (uball && uchain && !(freeball && freechain)) { + int bx, by, cx, cy, bdx, bdy, cdx, cdy; + + /* non-free chain should be under or next to the hero; + non-free ball should be on or next to the chain or else carried */ + cx = uchain->ox, cy = uchain->oy; + cdx = cx - u.ux, cdy = cy - u.uy; + cdx = abs(cdx), cdy = abs(cdy); + if (uball->where == OBJ_INVENT) /* carried(uball) */ + bx = u.ux, by = u.uy; /* get_obj_location() */ + else + bx = uball->ox, by = uball->oy; + bdx = bx - cx, bdy = by - cy; + bdx = abs(bdx), bdy = abs(bdy); + if (cdx > 1 || cdy > 1 || bdx > 1 || bdy > 1) + impossible( + "b&c distance: you@<%d,%d>, chain@<%d,%d>, ball@<%d,%d>", + u.ux, u.uy, cx, cy, bx, by); + } /* [check bc_order too?] */ } From bf5878076f8c4ae2861aa463e9608c5db0676845 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 3 Jun 2019 17:11:54 -0400 Subject: [PATCH 03/16] more precautions for monster obliteration during overcrowding --- src/mon.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mon.c b/src/mon.c index ac29cf866..a20592fc7 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1559422247 2019/06/01 20:50:47 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.287 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1559596286 2019/06/03 21:11:26 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.291 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2617,7 +2617,8 @@ struct monst *mtmp; * here (return FALSE). */ if (mtmp->data == &mons[PM_WIZARD_OF_YENDOR] || is_rider(mtmp->data) - || has_emin(mtmp) || has_epri(mtmp) || has_eshk(mtmp)) + || has_emin(mtmp) || has_epri(mtmp) || has_eshk(mtmp) + || (u.ustuck == mtmp) || (u.usteed == mtmp)) return FALSE; return TRUE; } From cccdeb6b01ef5a1bba2d32249909bbe84386193c Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 3 Jun 2019 18:00:19 -0400 Subject: [PATCH 04/16] data.base update --- dat/data.base | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dat/data.base b/dat/data.base index f098dd7c7..d62ce4788 100644 --- a/dat/data.base +++ b/dat/data.base @@ -5344,11 +5344,26 @@ valkyrie vampire ~vampire bat vampire lord + He can transform himself to wolf, as we gather from the ship + arrival in Whitby, when he tear open the dog; he can be as + bat, as Madam Mina saw him on the window at Whitby, and as + friend John saw him fly from this so near house, and as my + friend Quincey saw him at the window of Miss Lucy. He can come + in mist which he create--that noble ship's captain proved him + of this; but, from what we know, the distance he can make this + mist is limited, and it can only be round himself. He come on + moonlight rays as elemental dust--as again Jonathan saw those + sisters in the castle of Dracula. He become so small--we + ourselves saw Miss Lucy, ere she was at peace, slip through a + hairbreadth space at the tomb door. + [ Dracula, by Bram Stoker ] + The Oxford English Dictionary is quite unequivocal: _vampire_ - "a preternatural being of a malignant nature (in the original and usual form of the belief, a reanimated corpse), supposed to seek nourishment, or do harm, by sucking the blood of sleeping persons. ..." + [] venus Venus, the goddess of love and beauty, was the daughter of Jupiter and Dione. Others say that Venus sprang from the From fd585a58c23fba020d463acf3e68fd0e7486ce94 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 3 Jun 2019 18:37:45 -0400 Subject: [PATCH 05/16] add some debugging BREADCRUMBS to identify caller of some functions Only takes effect if a developer uncomments BREADCRUMBS in config.h --- doc/fixes36.3 | 4 ++- include/config.h | 8 +++++- include/decl.h | 8 +++++- include/extern.h | 9 ++++++- src/ball.c | 69 +++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 82ada4627..7aef2fdf8 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.31 $ $NHDT-Date: 1559422205 2019/06/01 20:50:05 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.33 $ $NHDT-Date: 1559601004 2019/06/03 22:30:04 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -91,4 +91,6 @@ add a couple of engraving suggestions in pull request #79 Code Cleanup and Reorganization ------------------------------- +began to add some function caller BREADCRUMBS to aid debugging + diff --git a/include/config.h b/include/config.h index 1fa760d90..d12576f9d 100644 --- a/include/config.h +++ b/include/config.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 config.h $NHDT-Date: 1558248715 2019/05/19 06:51:55 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.122 $ */ +/* NetHack 3.6 config.h $NHDT-Date: 1559601008 2019/06/03 22:30:08 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.123 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2016. */ /* NetHack may be freely redistributed. See license for details. */ @@ -526,6 +526,12 @@ typedef unsigned char uchar; * probably not useful for normal play */ /* #define EXTRA_SANITY_CHECKS */ +/* BREADCRUMBS employs the use of predefined compiler macros + * __FUNCTION__ and __LINE__ to store some caller breadcrumbs + * for use during heavy debugging sessions. Only define if your + * compiler supports those predefined macros and you are debugging */ +/* #define BREADCRUMBS */ + /* EDIT_GETLIN makes the string input in TTY, curses, Qt4, and X11 for some prompts be pre-loaded with previously input text (from a previous instance of the same prompt) as the default response. diff --git a/include/decl.h b/include/decl.h index eb3c904c4..0b7a929a1 100644 --- a/include/decl.h +++ b/include/decl.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 decl.h $NHDT-Date: 1547025154 2019/01/09 09:12:34 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.147 $ */ +/* NetHack 3.6 decl.h $NHDT-Date: 1559601011 2019/06/03 22:30:11 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.150 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2007. */ /* NetHack may be freely redistributed. See license for details. */ @@ -431,6 +431,12 @@ struct plinemsg_type { E struct plinemsg_type *plinemsg_types; +struct breadcrumbs { + const char *funcnm; + int linenum; + boolean in_effect; +}; + #ifdef PANICTRACE E const char *ARGV0; #endif diff --git a/include/extern.h b/include/extern.h index dd4ce99d5..cc62a61b5 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1559422206 2019/06/01 20:50:06 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.707 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1559601014 2019/06/03 22:30:14 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.708 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -127,8 +127,15 @@ E void FDECL(uchangealign, (int, int)); E void FDECL(ballrelease, (BOOLEAN_P)); E void NDECL(ballfall); +#ifndef BREADCRUMBS E void NDECL(placebc); E void NDECL(unplacebc); +#else +E void FDECL(Placebc, (const char *, int)); +E void FDECL(Unplacebc, (const char *, int)); +#define placebc() Placebc(__FUNCTION__, __LINE__) +#define unplacebc() Unplacebc(__FUNCTION__, __LINE__) +#endif E void FDECL(set_bc, (int)); E void FDECL(move_bc, (int, int, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); E boolean FDECL(drag_ball, (XCHAR_P, XCHAR_P, int *, xchar *, xchar *, diff --git a/src/ball.c b/src/ball.c index ab1024a9a..75822f88b 100644 --- a/src/ball.c +++ b/src/ball.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 ball.c $NHDT-Date: 1559554598 2019/06/03 09:36:38 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.39 $ */ +/* NetHack 3.6 ball.c $NHDT-Date: 1559601027 2019/06/03 22:30:27 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.40 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) David Cohrs, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,6 +10,13 @@ STATIC_DCL int NDECL(bc_order); STATIC_DCL void NDECL(litter); +STATIC_OVL void NDECL(placebc_core); +STATIC_OVL void NDECL(unplacebc_core); + +#ifdef BREADCRUMBS +static struct breadcrumbs bcpbreadcrumbs = { (const char *) 0, 0, FALSE}, + bcubreadcrumbs = { (const char *) 0, 0, FALSE}; +#endif void ballrelease(showmsg) @@ -106,8 +113,8 @@ ballfall() * * Should not be called while swallowed except on waterlevel. */ -void -placebc() +STATIC_OVL void +placebc_core() { if (!uchain || !uball) { impossible("Where are your ball and chain?"); @@ -132,8 +139,34 @@ placebc() newsym(u.ux, u.uy); } +#ifdef BREADCRUMBS void -unplacebc() +Placebc(funcnm, linenum) +const char *funcnm; +int linenum; +{ + if (uball && bcpbreadcrumbs.in_effect && uball->where == OBJ_FLOOR) { + impossible("placebc collision from %s:%d, already placed by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + return; + } + bcpbreadcrumbs.in_effect = TRUE; + bcubreadcrumbs.in_effect = FALSE; + bcpbreadcrumbs.funcnm = funcnm; + bcpbreadcrumbs.linenum = linenum; + placebc_core(); +} +#else +void +placebc() +{ + placebc_core(); +} +#endif + +STATIC_OVL void +unplacebc_core() { if (u.uswallow) { if (Is_waterlevel(&u.uz)) { @@ -164,6 +197,34 @@ unplacebc() u.bc_felt = 0; /* feel nothing */ } +#ifdef BREADCRUMBS +void +Unplacebc(funcnm, linenum) +const char *funcnm; +int linenum; +{ +#if 0 + if (uball && bcubreadcrumbs.in_effect && uball->where == OBJ_FREE) { + impossible("placebc collision from %s:%d, already placed by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + return; + } +#endif + bcpbreadcrumbs.in_effect = FALSE; + bcubreadcrumbs.in_effect = TRUE; + bcubreadcrumbs.funcnm = funcnm; + bcubreadcrumbs.linenum = linenum; + unplacebc_core(); +} +#else +void +unplacebc() +{ + unplacebc_core(); +} +#endif + /* * Return the stacking of the hero's ball & chain. This assumes that the * hero is being punished. From 4519e21a2102f958377a6e2d16a2e51beec837a7 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 3 Jun 2019 18:45:02 -0400 Subject: [PATCH 06/16] disabled code bit --- src/ball.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ball.c b/src/ball.c index 75822f88b..00352e2b7 100644 --- a/src/ball.c +++ b/src/ball.c @@ -205,9 +205,9 @@ int linenum; { #if 0 if (uball && bcubreadcrumbs.in_effect && uball->where == OBJ_FREE) { - impossible("placebc collision from %s:%d, already placed by %s:%d", + impossible("unplacebc collision from %s:%d, already placed by %s:%d", funcnm, linenum, - bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + bcubreadcrumbs.funcnm, bcubreadcrumbs.linenum); return; } #endif From ac79fedf6040acee5fd95c2b7e19bffa0304b63b Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 4 Jun 2019 09:16:00 -0700 Subject: [PATCH 07/16] fix github issue #196 - green slime feedback Fixes #196 If you didn't die from turning into green slime but then died because green slimes had been genocided, the message given assumed that you had just seen "OK, you don't die" from answering No to "Really die?". Its wording didn't make sense if the reason you didn't die was an amulet of life-saving. Give a different message for that case. Also, if you survive turning into slime (via either method) and either green slimes are still around or you answer No to "Really die?" when they've been genocided, give a message after "You survived that attempt on your life" pointing out that you have done so in green slime form. Useful since prior to 3.6.2 you would have reverted to original form-- despite the Slimed countdown saying you had turned into green slime. --- doc/fixes36.3 | 7 ++++++- include/flag.h | 5 +++-- src/end.c | 3 ++- src/hack.c | 12 ++++++++++-- src/polyself.c | 6 ++++-- src/potion.c | 11 +++++++++-- src/timeout.c | 17 ++++++++++++++--- 7 files changed, 48 insertions(+), 13 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 7aef2fdf8..cc5ebceb7 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.33 $ $NHDT-Date: 1559601004 2019/06/03 22:30:04 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.34 $ $NHDT-Date: 1559664948 2019/06/04 16:15:48 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -38,6 +38,10 @@ on the Plane of Air, make clouds disrupt line of sight along the edges have '&' (whatdoes) command describe movement keystrokes instead of reporting them as unknown or showing their number_pad action when that is Off some improvement to the handling of endgame levels filling up with monsters +if you survive turning into green slime due to life-saving (surviving as a + green slime) then die again due to green slimes having been genocided, + the feedback was strange because it assumed that the prior message + came from answering No to "Really die?" in explore or wizard mode Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository @@ -60,6 +64,7 @@ curses: if message window is only one line, cancelling some prompts with ESC left the prompts visible on the message line instead of erasing them curses: support EDIT_GETLIN (but like with tty, it's disabled by default) to pre-load an earlier response as the default answer for some prompts + (however, it's skipped if the 'popup_dialog' option is On) curses: when display windows get reconfigured (after setting align_status, align_message, statuslines, windowborders or due to external resize), the message window was being refreshed with the oldest available N diff --git a/include/flag.h b/include/flag.h index b5e1bcfda..56352dded 100644 --- a/include/flag.h +++ b/include/flag.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 flag.h $NHDT-Date: 1554155745 2019/04/01 21:55:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.150 $ */ +/* NetHack 3.6 flag.h $NHDT-Date: 1559664948 2019/06/04 16:15:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.151 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -484,7 +484,8 @@ enum plnmsg_types { PLNMSG_TOWER_OF_FLAME, /* scroll of fire */ PLNMSG_CAUGHT_IN_EXPLOSION, /* explode() feedback */ PLNMSG_OBJ_GLOWS, /* "the glows " */ - PLNMSG_OBJNAM_ONLY /* xname/doname only, for #tip */ + PLNMSG_OBJNAM_ONLY, /* xname/doname only, for #tip */ + PLNMSG_OK_DONT_DIE /* overriding death in explore/wizard mode */ }; /* runmode options */ diff --git a/src/end.c b/src/end.c index 67ae532f1..e9b9d88ab 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1558921075 2019/05/27 01:37:55 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.174 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1559664950 2019/06/04 16:15:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.175 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1177,6 +1177,7 @@ int how; if (!survive && (wizard || discover) && how <= GENOCIDED && !paranoid_query(ParanoidDie, "Die?")) { pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die"); + iflags.last_msg = PLNMSG_OK_DONT_DIE; savelife(how); survive = TRUE; } diff --git a/src/hack.c b/src/hack.c index 7c80a8c1e..74a13af98 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1559313320 2019/05/31 14:35:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.212 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1559664951 2019/06/04 16:15:51 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.213 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2901,8 +2901,16 @@ const char *msg_override; nomovemsg = msg_override; else if (!nomovemsg) nomovemsg = You_can_move_again; - if (*nomovemsg) + if (*nomovemsg) { pline("%s", nomovemsg); + /* follow "you survived that attempt on your life" with a message + about current form if it's not the default; primarily for + life-saving while turning into green slime but is also a reminder + if life-saved while poly'd and Unchanging (explore or wizard mode + declining to die since can't be both Unchanging and Lifesaved) */ + if (Upolyd && !strncmpi(nomovemsg, "You survived that ", 18)) + You("are %s", an(mons[u.umonnum].mname)); /* (ignore Hallu) */ + } nomovemsg = 0; u.usleep = 0; multi_reason = NULL; diff --git a/src/polyself.c b/src/polyself.c index a8e434206..3f33c8e9b 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 polyself.c $NHDT-Date: 1556497911 2019/04/29 00:31:51 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.132 $ */ +/* NetHack 3.6 polyself.c $NHDT-Date: 1559664952 2019/06/04 16:15:52 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.133 $ */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -163,7 +163,7 @@ polyman(fmt, arg) const char *fmt, *arg; { boolean sticky = (sticks(youmonst.data) && u.ustuck && !u.uswallow), - was_mimicking = (U_AP_TYPE == M_AP_OBJECT); + was_mimicking = (U_AP_TYPE != M_AP_NOTHING); boolean was_blind = !!Blind; if (Upolyd) { @@ -186,6 +186,7 @@ const char *fmt, *arg; if (multi < 0) unmul(""); youmonst.m_ap_type = M_AP_NOTHING; + youmonst.mappearance = 0; } newsym(u.ux, u.uy); @@ -633,6 +634,7 @@ int mntmp; if (mons[mntmp].mlet != S_MIMIC) { /* as in polyman() */ youmonst.m_ap_type = M_AP_NOTHING; + youmonst.mappearance = 0; } if (is_male(&mons[mntmp])) { if (flags.female) diff --git a/src/potion.c b/src/potion.c index 7d8afd0ba..a07fcd0d8 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 potion.c $NHDT-Date: 1549074254 2019/02/02 02:24:14 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.160 $ */ +/* NetHack 3.6 potion.c $NHDT-Date: 1559664951 2019/06/04 16:15:51 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.161 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -185,8 +185,15 @@ const char *msg; if (msg) pline("%s", msg); } - if (!Slimed) + if (!Slimed) { dealloc_killer(find_delayed_killer(SLIMED)); + /* fake appearance is set late in turn-to-slime countdown */ + if (youmonst.m_ap_type == M_AP_MONSTER + && youmonst.mappearance == PM_GREEN_SLIME) { + youmonst.m_ap_type = M_AP_NOTHING; + youmonst.mappearance = 0; + } + } } /* start or stop petrification */ diff --git a/src/timeout.c b/src/timeout.c index a4408de5c..54a2943c3 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 timeout.c $NHDT-Date: 1545182148 2018/12/19 01:15:48 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.89 $ */ +/* NetHack 3.6 timeout.c $NHDT-Date: 1559664953 2019/06/04 16:15:53 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.90 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -403,6 +403,7 @@ struct kinfo *kptr; del_light_source(LS_MONSTER, monst_to_any(&youmonst)); save_mvflags = mvitals[PM_GREEN_SLIME].mvflags; mvitals[PM_GREEN_SLIME].mvflags = save_mvflags & ~G_GENOD; + /* become a green slime; also resets youmonst.m_ap_type+.mappearance */ (void) polymon(PM_GREEN_SLIME); mvitals[PM_GREEN_SLIME].mvflags = save_mvflags; done(TURNED_SLIME); @@ -410,10 +411,20 @@ struct kinfo *kptr; /* life-saved; even so, hero still has turned into green slime; player may have genocided green slimes after being infected */ if ((mvitals[PM_GREEN_SLIME].mvflags & G_GENOD) != 0) { + char slimebuf[BUFSZ]; + killer.format = KILLED_BY; Strcpy(killer.name, "slimicide"); - /* immediately follows "OK, so you don't die." */ - pline("Yes, you do. Green slime has been genocided..."); + /* vary the message depending upon whether life-save was due to + amulet or due to declining to die in explore or wizard mode */ + Strcpy(slimebuf, "green slime has been genocided..."); + if (iflags.last_msg == PLNMSG_OK_DONT_DIE) + /* follows "OK, so you don't die." and arg is second sentence */ + pline("Yes, you do. %s", upstart(slimebuf)); + else + /* follows "The medallion crumbles to dust." */ + pline("Unfortunately, %s", slimebuf); + /* die again; no possibility of amulet this time */ done(GENOCIDED); /* could be life-saved again (only in explore or wizard mode) but green slimes are gone; just stay in current form */ From 43afa91ff80217b2e8d4b7350053b9c35b50d716 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 4 Jun 2019 10:50:24 -0700 Subject: [PATCH 08/16] fix #H8850 - bless/curse state in perm_invent Changing an inventory item's bknown flag wasn't followed by a call to update_inventory() in many circumstances, so information which should have appeared wasn't showing up until some other event triggered an update. --- doc/fixes36.3 | 6 +++++- include/extern.h | 3 ++- src/apply.c | 8 ++++---- src/do.c | 8 ++++---- src/do_wear.c | 16 ++++++++-------- src/eat.c | 4 ++-- src/files.c | 4 ++-- src/mkobj.c | 27 ++++++++++++++++++++------- src/objnam.c | 9 ++++++--- src/pickup.c | 8 ++++---- src/pray.c | 18 +++++++++--------- src/sit.c | 4 ++-- src/steed.c | 4 ++-- src/wield.c | 10 +++++----- 14 files changed, 75 insertions(+), 54 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index cc5ebceb7..d4800b4a2 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.34 $ $NHDT-Date: 1559664948 2019/06/04 16:15:48 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.35 $ $NHDT-Date: 1559670600 2019/06/04 17:50:00 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -42,6 +42,10 @@ if you survive turning into green slime due to life-saving (surviving as a green slime) then die again due to green slimes having been genocided, the feedback was strange because it assumed that the prior message came from answering No to "Really die?" in explore or wizard mode +various cases where objects had their bless/curse state become known weren't + updating persistent inventory window, when enabled, to reflect changes + (cited case was trying to remove cursed armor and being told of the + curse but there were lots of other situations with the same issue) Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index cc62a61b5..f7e762bda 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1559601014 2019/06/03 22:30:14 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.708 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1559670600 2019/06/04 17:50:00 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.709 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1341,6 +1341,7 @@ E void FDECL(unbless, (struct obj *)); E void FDECL(curse, (struct obj *)); E void FDECL(uncurse, (struct obj *)); E void FDECL(blessorcurse, (struct obj *, int)); +E void FDECL(set_bknown, (struct obj *, unsigned)); E boolean FDECL(is_flammable, (struct obj *)); E boolean FDECL(is_rottable, (struct obj *)); E void FDECL(place_object, (struct obj *, int, int)); diff --git a/src/apply.c b/src/apply.c index 998d4ddec..879c6a3cb 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 apply.c $NHDT-Date: 1553363415 2019/03/23 17:50:15 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.272 $ */ +/* NetHack 3.6 apply.c $NHDT-Date: 1559670602 2019/06/04 17:50:02 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.274 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -668,7 +668,7 @@ struct obj *obj; pline("This leash is not attached to that creature."); } else if (obj->cursed) { pline_The("leash would not come off!"); - obj->bknown = 1; + set_bknown(obj, 1); } else { mtmp->mleashed = 0; obj->leashmon = 0; @@ -2773,7 +2773,7 @@ struct obj *obj; pline("%s welded to %s %s%c", (otmp->quan == 1L) ? "It is" : "They are", mhis(mtmp), mon_hand, !otmp->bknown ? '!' : '.'); - otmp->bknown = 1; + set_bknown(otmp, 1); gotit = FALSE; /* can't pull it free */ } if (gotit) { @@ -3629,7 +3629,7 @@ doapply() if (!rn2(49)) { if (!Blind) { pline("%s %s.", Yobjnam2(obj, "glow"), hcolor("brown")); - obj->bknown = 1; + set_bknown(obj, 1); } unbless(obj); } diff --git a/src/do.c b/src/do.c index c899676ef..035fd3a8e 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1559299314 2019/05/31 10:41:54 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.191 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1559670603 2019/06/04 17:50:03 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.192 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -286,11 +286,11 @@ register struct obj *obj; an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)), doname(obj), otense(obj, "hit")); if (!Hallucination) - obj->bknown = 1; + obj->bknown = 1; /* ok to bypass set_bknown() */ } else { pline("%s %s on the altar.", Doname2(obj), otense(obj, "land")); if (obj->oclass != COIN_CLASS) - obj->bknown = 1; + obj->bknown = 1; /* ok to bypass set_bknown() */ } } @@ -575,7 +575,7 @@ const char *word; obj->corpsenm ? " any of" : "", plur(obj->quan)); } obj->corpsenm = 0; /* reset */ - obj->bknown = 1; + set_bknown(obj, 1); return FALSE; } if (obj->otyp == LEASH && obj->leashmon != 0) { diff --git a/src/do_wear.c b/src/do_wear.c index 9132e7535..6c99c1a5d 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do_wear.c $NHDT-Date: 1551138255 2019/02/25 23:44:15 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.108 $ */ +/* NetHack 3.6 do_wear.c $NHDT-Date: 1559670603 2019/06/04 17:50:03 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.109 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1515,7 +1515,7 @@ doremring() /* Check if something worn is cursed _and_ unremovable. */ int cursed(otmp) -register struct obj *otmp; +struct obj *otmp; { if (!otmp) { impossible("cursed without otmp"); @@ -1527,7 +1527,7 @@ register struct obj *otmp; || otmp->otyp == LENSES || otmp->quan > 1L); You("can't. %s cursed.", use_plural ? "They are" : "It is"); - otmp->bknown = TRUE; + set_bknown(otmp, 1); return 1; } return 0; @@ -1535,7 +1535,7 @@ register struct obj *otmp; int armoroff(otmp) -register struct obj *otmp; +struct obj *otmp; { register int delay = -objects[otmp->otyp].oc_delay; @@ -1859,7 +1859,7 @@ struct obj *obj; } if (uarmg && uarmg->cursed) { res = !uarmg->bknown; - uarmg->bknown = 1; + set_bknown(uarmg, 1); You("cannot remove your gloves to put on the ring."); return res; /* uses move iff we learned gloves are cursed */ } @@ -2249,7 +2249,7 @@ register struct obj *otmp; } if (why) { You("cannot %s to remove the ring.", buf); - why->bknown = TRUE; + set_bknown(why, 1); return 0; } } @@ -2258,7 +2258,7 @@ register struct obj *otmp; if (welded(uwep)) { You("are unable to take off your %s while wielding that %s.", c_gloves, is_sword(uwep) ? c_sword : c_weapon); - uwep->bknown = TRUE; + set_bknown(uwep, 1); return 0; } else if (Glib) { You_cant("take off the slippery %s with your slippery %s.", @@ -2296,7 +2296,7 @@ register struct obj *otmp; } if (why) { You("cannot %s to take off %s.", buf, the(xname(otmp))); - why->bknown = TRUE; + set_bknown(why, 1); return 0; } } diff --git a/src/eat.c b/src/eat.c index 4dd3a0a31..de0563310 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 eat.c $NHDT-Date: 1542765357 2018/11/21 01:55:57 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.197 $ */ +/* NetHack 3.6 eat.c $NHDT-Date: 1559670604 2019/06/04 17:50:04 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.202 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2503,7 +2503,7 @@ doeat() * against the possibility just in case. */ if (welded(otmp) || (otmp->cursed && (otmp->owornmask & W_RING))) { - otmp->bknown = 1; /* for ring; welded() does this for weapon */ + set_bknown(otmp, 1); /* for ring; welded() does this for weapon */ You("spit out %s.", the(xname(otmp))); } else { You("spit %s out onto the %s.", the(xname(otmp)), diff --git a/src/files.c b/src/files.c index 00d1fe972..92940c9b0 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 files.c $NHDT-Date: 1546144856 2018/12/30 04:40:56 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.249 $ */ +/* NetHack 3.6 files.c $NHDT-Date: 1559670605 2019/06/04 17:50:05 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.250 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2946,7 +2946,7 @@ struct obj *obj; /* subset of starting inventory pre-ID */ obj->dknown = 1; if (Role_if(PM_PRIEST)) - obj->bknown = 1; + obj->bknown = 1; /* ok to bypass set_bknown() */ /* same criteria as lift_object()'s check for available inventory slot */ if (obj->oclass != COIN_CLASS && inv_cnt(FALSE) >= 52 && !merge_choice(invent, obj)) { diff --git a/src/mkobj.c b/src/mkobj.c index 4b64a3f44..5f98fe34e 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1559476922 2019/06/02 12:02:02 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.149 $ */ +/* NetHack 3.6 mkobj.c $NHDT-Date: 1559670606 2019/06/04 17:50:06 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.150 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -698,7 +698,7 @@ int alter_type; { xchar ox, oy; char objroom; - boolean set_bknown; + boolean learn_bknown; const char *those, *them; struct monst *shkp = 0; @@ -738,21 +738,21 @@ int alter_type; /* when shopkeeper describes the object as being uncursed or unblessed hero will know that it is now uncursed; will also make the feedback from `I x' after bill_dummy_object() be more specific for this item */ - set_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS); + learn_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS); switch (obj->where) { case OBJ_FREE: /* obj_no_longer_held() */ case OBJ_INVENT: - if (set_bknown) - obj->bknown = 1; + if (learn_bknown) + set_bknown(obj, 1); verbalize("You %s %s %s, you pay for %s!", alteration_verbs[alter_type], those, simpleonames(obj), them); bill_dummy_object(obj); break; case OBJ_FLOOR: - if (set_bknown) - obj->bknown = 1; + if (learn_bknown) + obj->bknown = 1; /* ok to bypass set_bknown() here */ if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) { verbalize("You %s %s, you pay for %s!", alteration_verbs[alter_type], those, them); @@ -1389,6 +1389,19 @@ register struct obj *otmp; return (!!otmp->blessed - !!otmp->cursed); } +/* set the object's bless/curse-state known flag */ +void +set_bknown(obj, onoff) +struct obj *obj; +unsigned onoff; /* 1 or 0 */ +{ + if (obj->bknown != onoff) { + obj->bknown = onoff; + if (obj->where == OBJ_INVENT && moves > 1L) + update_inventory(); + } +} + /* * Calculate the weight of the given object. This will recursively follow * and calculate the weight of any containers. diff --git a/src/objnam.c b/src/objnam.c index 90ac6c44c..5e51bee9b 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1558485650 2019/05/22 00:40:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.241 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1559670607 2019/06/04 17:50:07 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.242 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -450,9 +450,12 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */ if (!nn && ocl->oc_uses_known && ocl->oc_unique) obj->known = 0; if (!Blind && !distantname) - obj->dknown = TRUE; + obj->dknown = 1; if (Role_if(PM_PRIEST)) - obj->bknown = TRUE; + obj->bknown = 1; /* actively avoid set_bknown(); + * we mustn't call update_inventory() now because + * it would call xname() (via doname()) recursively + * and could end up clobbering all the obufs... */ if (iflags.override_ID) { known = dknown = bknown = TRUE; diff --git a/src/pickup.c b/src/pickup.c index 151a63808..336719b0a 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pickup.c $NHDT-Date: 1559130050 2019/05/29 11:40:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.226 $ */ +/* NetHack 3.6 pickup.c $NHDT-Date: 1559670608 2019/06/04 17:50:08 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.227 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -408,8 +408,8 @@ struct obj *obj; ? TRUE : FALSE) : TRUE; /* catchall: no filters specified, so accept */ - if (Role_if(PM_PRIEST)) - obj->bknown = TRUE; + if (Role_if(PM_PRIEST) && !obj->bknown) + set_bknown(obj, 1); /* * There are three types of filters possible and the first and @@ -2113,7 +2113,7 @@ register struct obj *obj; Icebox ? "refrigerate" : "stash", something); return 0; } else if ((obj->otyp == LOADSTONE) && obj->cursed) { - obj->bknown = 1; + set_bknown(obj, 1); pline_The("stone%s won't leave your person.", plur(obj->quan)); return 0; } else if (obj->otyp == AMULET_OF_YENDOR diff --git a/src/pray.c b/src/pray.c index bc9a9ba82..0a192d65a 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pray.c $NHDT-Date: 1549074257 2019/02/02 02:24:17 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.110 $ */ +/* NetHack 3.6 pray.c $NHDT-Date: 1559670608 2019/06/04 17:50:08 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.112 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -499,7 +499,7 @@ int trouble; what ? what : (const char *) Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); iflags.last_msg = PLNMSG_OBJ_GLOWS; - otmp->bknown = !Hallucination; + otmp->bknown = !Hallucination; /* ok to skip set_bknown() */ } uncurse(otmp); update_inventory(); @@ -558,7 +558,7 @@ int trouble; otmp = which_armor(u.usteed, W_SADDLE); if (!Blind) { pline("%s %s.", Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); - otmp->bknown = TRUE; + set_bknown(otmp, 1); } uncurse(otmp); break; @@ -805,7 +805,7 @@ gcrownu() make_splbk: obj = mksobj(class_gift, TRUE, FALSE); bless(obj); - obj->bknown = TRUE; + obj->bknown = 1; /* ok to skip set_bknown() */ at_your_feet("A spellbook"); dropy(obj); u.ugifts++; @@ -892,7 +892,7 @@ gcrownu() bless(obj); obj->oeroded = obj->oeroded2 = 0; obj->oerodeproof = TRUE; - obj->bknown = obj->rknown = TRUE; + obj->bknown = obj->rknown = 1; /* ok to skip set_bknown() */ if (obj->spe < 1) obj->spe = 1; /* acquire skill in this weapon */ @@ -1024,7 +1024,7 @@ aligntyp g_align; You_feel("the power of %s over %s.", u_gname(), yname(uwep)); uncurse(uwep); - uwep->bknown = TRUE; + uwep->bknown = 1; /* ok to bypass set_bknown() */ *repair_buf = '\0'; } else if (!uwep->blessed) { if (!Blind) { @@ -1036,7 +1036,7 @@ aligntyp g_align; You_feel("the blessing of %s over %s.", u_gname(), yname(uwep)); bless(uwep); - uwep->bknown = TRUE; + uwep->bknown = 1; /* ok to bypass set_bknown() */ *repair_buf = '\0'; } @@ -1127,7 +1127,7 @@ aligntyp g_align; pline("%s %s.", Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); iflags.last_msg = PLNMSG_OBJ_GLOWS; - otmp->bknown = TRUE; + otmp->bknown = 1; /* ok to bypass set_bknown() */ ++any; } uncurse(otmp); @@ -1234,7 +1234,7 @@ boolean bless_water; && (bless_water ? !otmp->blessed : !otmp->cursed)) { otmp->blessed = bless_water; otmp->cursed = !bless_water; - otmp->bknown = bc_known; + otmp->bknown = bc_known; /* ok to bypass set_bknown() */ changed += otmp->quan; } else if (otmp->oclass == POTION_CLASS) other = TRUE; diff --git a/src/sit.c b/src/sit.c index 09cbc9bf2..2c164c2fe 100644 --- a/src/sit.c +++ b/src/sit.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sit.c $NHDT-Date: 1544442714 2018/12/10 11:51:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */ +/* NetHack 3.6 sit.c $NHDT-Date: 1559670609 2019/06/04 17:50:09 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.61 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -392,7 +392,7 @@ rndcurse() if (!Blind) { pline("%s %s.", Yobjnam2(otmp, "glow"), hcolor(otmp->cursed ? NH_BLACK : (const char *) "brown")); - otmp->bknown = TRUE; + otmp->bknown = 1; /* ok to bypass set_bknown() here */ } } } diff --git a/src/steed.c b/src/steed.c index f82b09b3a..c7540a28a 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 steed.c $NHDT-Date: 1559422254 2019/06/01 20:50:54 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.64 $ */ +/* NetHack 3.6 steed.c $NHDT-Date: 1559670610 2019/06/04 17:50:10 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.66 $ */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -525,7 +525,7 @@ int reason; /* Player was thrown off etc. */ if (otmp && otmp->cursed) { You("can't. The saddle %s cursed.", otmp->bknown ? "is" : "seems to be"); - otmp->bknown = TRUE; + otmp->bknown = 1; /* ok to skip set_bknown() here */ return; } if (!have_spot) { diff --git a/src/wield.c b/src/wield.c index 701e2edcf..18c276a2e 100644 --- a/src/wield.c +++ b/src/wield.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wield.c $NHDT-Date: 1543492132 2018/11/29 11:48:52 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.58 $ */ +/* NetHack 3.6 wield.c $NHDT-Date: 1559670611 2019/06/04 17:50:11 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.59 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -171,7 +171,7 @@ struct obj *wep; (wep->quan == 1L) ? "itself" : "themselves", /* a3 */ bimanual(wep) ? (const char *) makeplural(body_part(HAND)) : body_part(HAND)); - wep->bknown = TRUE; + set_bknown(wep, 1); } else { /* The message must be printed before setuwep (since * you might die and be revived from changing weapons), @@ -628,7 +628,7 @@ can_twoweapon() ; /* must be life-saved to reach here; return FALSE */ } else if (Glib || uswapwep->cursed) { if (!Glib) - uswapwep->bknown = TRUE; + set_bknown(uswapwep, 1); drop_uswapwep(); } else return TRUE; @@ -736,7 +736,7 @@ register int amount; if (!Blind) { Sprintf(buf, "%s with %s aura.", Yobjnam2(uwep, "glow"), an(hcolor(NH_AMBER))); - uwep->bknown = !Hallucination; + uwep->bknown = !Hallucination; /* ok to bypass set_bknown() */ } else { /* cursed tin opener is wielded in right hand */ Sprintf(buf, "Your right %s tingles.", body_part(HAND)); @@ -859,7 +859,7 @@ welded(obj) register struct obj *obj; { if (obj && obj == uwep && will_weld(obj)) { - obj->bknown = TRUE; + set_bknown(obj, 1); return 1; } return 0; From 093e7c31e43da0c200be352bc27106ade87061ae Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 4 Jun 2019 12:13:46 -0700 Subject: [PATCH 09/16] container->{cknown,lknown) vs perm_invent Carried containers could have their contents-known state and/or lock-known state changed without persistent inventory window being updated to show the new information. This also changes the behavior when player has hero zap self with wand of locking or wizard lock spell. If it doesn't trigger a holding trap then the effect will hit inventory, similar to how opening/knock operates (releasing hero from holding trap or hiting inventory when that doesn't happen). --- doc/fixes36.3 | 4 +++- src/end.c | 11 +++++++---- src/pickup.c | 20 ++++++++++++++------ src/zap.c | 40 ++++++++++++++++++++++++++++++---------- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index d4800b4a2..a31768dc1 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.35 $ $NHDT-Date: 1559670600 2019/06/04 17:50:00 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.36 $ $NHDT-Date: 1559675614 2019/06/04 19:13:34 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -46,6 +46,8 @@ various cases where objects had their bless/curse state become known weren't updating persistent inventory window, when enabled, to reflect changes (cited case was trying to remove cursed armor and being told of the curse but there were lots of other situations with the same issue) +similar perm_invent issue when lock state known and/or contents known become + set for carried container Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/end.c b/src/end.c index e9b9d88ab..8aac191f7 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1559664950 2019/06/04 16:15:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.175 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1559675615 2019/06/04 19:13:35 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.176 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1621,9 +1621,12 @@ boolean identified, all_containers, reportempty; for (box = list; box; box = box->nobj) { if (Is_container(box) || box->otyp == STATUE) { - box->cknown = 1; /* we're looking at the contents now */ - if (identified) - box->lknown = 1; + if (!box->cknown || (identified && !box->lknown)) { + box->cknown = 1; /* we're looking at the contents now */ + if (identified) + box->lknown = 1; + update_inventory(); + } if (box->otyp == BAG_OF_TRICKS) { continue; /* wrong type of container */ } else if (box->cobj) { diff --git a/src/pickup.c b/src/pickup.c index 336719b0a..77356b1fe 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pickup.c $NHDT-Date: 1559670608 2019/06/04 17:50:08 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.227 $ */ +/* NetHack 3.6 pickup.c $NHDT-Date: 1559675617 2019/06/04 19:13:37 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.228 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1704,7 +1704,7 @@ int cindex, ccount; /* index of this container (1..N), number of them (N) */ cobj->lknown = 1; return 0; } - cobj->lknown = 1; + cobj->lknown = 1; /* floor container, so no need for update_inventory() */ if (cobj->otyp == BAG_OF_TRICKS) { int tmp; @@ -2493,16 +2493,19 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */ if (!u_handsy()) return 0; + if (!obj->lknown) { /* do this in advance */ + obj->lknown = 1; + if (held) + update_inventory(); + } if (obj->olocked) { pline("%s locked.", Tobjnam(obj, "are")); if (held) You("must put it down to unlock."); - obj->lknown = 1; return 0; } else if (obj->otrapped) { if (held) You("open %s...", the(xname(obj))); - obj->lknown = 1; (void) chest_trap(obj, HAND, FALSE); /* even if the trap fails, you've used up this turn */ if (multi >= 0) { /* in case we didn't become paralyzed */ @@ -2513,7 +2516,6 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */ abort_looting = TRUE; return 1; } - obj->lknown = 1; current_container = obj; /* for use by in/out_container */ /* @@ -3105,7 +3107,11 @@ struct obj *box; /* or bag */ /* caveat: this assumes that cknown, lknown, olocked, and otrapped fields haven't been overloaded to mean something special for the non-standard "container" horn of plenty */ - box->lknown = 1; + if (!box->lknown) { + box->lknown = 1; + if (carried(box)) + update_inventory(); /* jumping the gun slightly; hope that's ok */ + } if (box->olocked) { pline("It's locked."); } else if (box->otrapped) { @@ -3226,6 +3232,8 @@ struct obj *box; /* or bag */ if (held) (void) encumber_msg(); } + if (carried(box)) /* box is now empty with cknown set */ + update_inventory(); } /*pickup.c*/ diff --git a/src/zap.c b/src/zap.c index a9350eb4f..d054b2a14 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1551395521 2019/02/28 23:12:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.307 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1559675618 2019/06/04 19:13:38 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.309 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -126,6 +126,7 @@ struct obj *obj; if (obj->dknown) makeknown(obj->otyp); } + update_inventory(); } } @@ -1899,9 +1900,9 @@ struct obj *obj, *otmp; (void) boxlock(obj, otmp); if (obj_shudders(obj)) { - boolean cover = - ((obj == level.objects[u.ux][u.uy]) && u.uundetected - && hides_under(youmonst.data)); + boolean cover = ((obj == level.objects[u.ux][u.uy]) + && u.uundetected + && hides_under(youmonst.data)); if (cansee(obj->ox, obj->oy)) learn_it = TRUE; @@ -1934,6 +1935,7 @@ struct obj *obj, *otmp; obj->cknown = 0; } else { struct obj *o; + /* view contents (not recursively) */ for (o = obj->cobj; o; o = o->nobj) o->dknown = 1; /* "seen", even if blind */ @@ -2494,22 +2496,39 @@ boolean ordinary; learn_it = TRUE; unpunish(); } - if (u.utrap) { /* escape web or bear trap */ - (void) openholdingtrap(&youmonst, &learn_it); - } else { + /* invent is hit iff hero doesn't escape from a trap */ + if (!u.utrap || !openholdingtrap(&youmonst, &learn_it)) { struct obj *otmp; + boolean boxing = FALSE; + /* unlock carried boxes */ for (otmp = invent; otmp; otmp = otmp->nobj) - if (Is_box(otmp)) + if (Is_box(otmp)) { (void) boxlock(otmp, obj); + boxing = TRUE; + } + if (boxing) + update_inventory(); /* in case any box->lknown has changed */ + /* trigger previously escaped trapdoor */ (void) openfallingtrap(&youmonst, TRUE, &learn_it); } break; case WAN_LOCKING: case SPE_WIZARD_LOCK: - if (!u.utrap) { - (void) closeholdingtrap(&youmonst, &learn_it); + /* similar logic to opening; invent is hit iff no trap triggered */ + if (u.utrap || !closeholdingtrap(&youmonst, &learn_it)) { + struct obj *otmp; + boolean boxing = FALSE; + + /* lock carried boxes */ + for (otmp = invent; otmp; otmp = otmp->nobj) + if (Is_box(otmp)) { + (void) boxlock(otmp, obj); + boxing = TRUE; + } + if (boxing) + update_inventory(); /* in case any box->lknown has changed */ } break; case WAN_DIGGING: @@ -2528,6 +2547,7 @@ boolean ordinary; otmp->cknown = 1; } } + update_inventory(); learn_it = TRUE; ustatusline(); break; From 25f1cc38e9663e2f6d84288f55bb1d85ecb83757 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 4 Jun 2019 13:18:21 -0700 Subject: [PATCH 10/16] confused blessed scroll of remove curse on itself Noticed when testing the set_bknown patch earlier: something updated the persistent inventory window while scroll processing was in the midst of traversing invent and it showed the scroll I'd just read change from known blessed to bless/curse state not known. The scroll should really be removed from inventory because player is told that it has disappeared, but unlike charging (which does do that so that it is gone when selecting an item to charge), remove curse isn't auto-IDed and the code to ask the player to call an unIDed item something only kicks in when it's still in inventory. Preventing the scroll in use from having its bknown flag cleared should be good enough; it won't have disappeared yet but at least it won't be visibly changing. --- doc/fixes36.3 | 4 +++- src/read.c | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index a31768dc1..1c28ed086 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.36 $ $NHDT-Date: 1559675614 2019/06/04 19:13:34 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.37 $ $NHDT-Date: 1559679496 2019/06/04 20:18:16 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -48,6 +48,8 @@ various cases where objects had their bless/curse state become known weren't curse but there were lots of other situations with the same issue) similar perm_invent issue when lock state known and/or contents known become set for carried container +blessed scroll of remove curse read while confused might be shown to operate + on itself by perm_invent after player is told that it has disappeared Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/read.c b/src/read.c index 562b52bf1..063f73c13 100644 --- a/src/read.c +++ b/src/read.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 read.c $NHDT-Date: 1546465285 2019/01/02 21:41:25 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.164 $ */ +/* NetHack 3.6 read.c $NHDT-Date: 1559679496 2019/06/04 20:18:16 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.165 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1285,6 +1285,10 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ /* gold isn't subject to cursing and blessing */ if (obj->oclass == COIN_CLASS) continue; + /* hide current scroll from itself so that perm_invent won't + show known blessed scroll losing bknown when confused */ + if (obj == sobj && obj->quan == 1L) + continue; wornmask = (obj->owornmask & ~(W_BALL | W_ART | W_ARTI)); if (wornmask && !sblessed) { /* handle a couple of special cases; we don't From 05a0d10097ed76fa2b664beb8926a2054fe99389 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 4 Jun 2019 14:54:58 -0700 Subject: [PATCH 11/16] plug montraits() memory leek If a corpse with a revive timer included obj->oextra->omonst for remembering the original monster (I think all corpses do these days) and makemon() failed to create a new monster when the timer expired, the copy of the original wasn't freed. makemon() will fail if there is no room for the monster. --- doc/fixes36.3 | 3 ++- src/zap.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 1c28ed086..4df27bcc5 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.37 $ $NHDT-Date: 1559679496 2019/06/04 20:18:16 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.38 $ $NHDT-Date: 1559685281 2019/06/04 21:54:41 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -50,6 +50,7 @@ similar perm_invent issue when lock state known and/or contents known become set for carried container blessed scroll of remove curse read while confused might be shown to operate on itself by perm_invent after player is told that it has disappeared +fix memory leak if corpse auto-revival attempt failed ("you feel less hassled") Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/zap.c b/src/zap.c index d054b2a14..724dc3189 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1559675618 2019/06/04 19:13:38 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.309 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1559685281 2019/06/04 21:54:41 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.310 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -584,11 +584,8 @@ struct obj *obj; coord *cc; boolean adjacentok; /* False: at obj's spot only, True: nearby is allowed */ { - struct monst *mtmp = (struct monst *) 0; - struct monst *mtmp2 = (struct monst *) 0; + struct monst *mtmp, *mtmp2 = has_omonst(obj) ? get_mtraits(obj, TRUE) : 0; - if (has_omonst(obj)) - mtmp2 = get_mtraits(obj, TRUE); if (mtmp2) { /* save_mtraits() validated mtmp2->mnum */ mtmp2->data = &mons[mtmp2->mnum]; @@ -597,8 +594,12 @@ boolean adjacentok; /* False: at obj's spot only, True: nearby is allowed */ mtmp = makemon(mtmp2->data, cc->x, cc->y, (NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH | (adjacentok ? MM_ADJACENTOK : 0))); - if (!mtmp) - return mtmp; + if (!mtmp) { + /* mtmp2 is a copy of obj's object->oextra->omonst extension + and is not on the map or on any monst lists */ + dealloc_monst(mtmp2); + return (struct monst *) 0; + } /* heal the monster */ if (mtmp->mhpmax > mtmp2->mhpmax && is_rider(mtmp2->data)) From a65682f58e0df9622ed9b00c9f6d18dc043bc6ad Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 4 Jun 2019 21:18:46 -0400 Subject: [PATCH 12/16] allow a parent function to restrict use of placebc placebc was triggering an impossible sometimes on the plane of water It turned out to be because movebubbles issued an unplacebc(), but a downstream function called placebc(), so when movebubbles() issued its own placebc() there was a problem. The downstream function that beat movebubbles to the placebc() turned out to be unstuck(). There could be others. --- doc/fixes36.3 | 3 +- include/decl.h | 1 + include/extern.h | 8 ++ src/ball.c | 209 ++++++++++++++++++++++++++++++++++++++--------- src/mkmaze.c | 6 +- 5 files changed, 185 insertions(+), 42 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 4df27bcc5..392c7e196 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -51,7 +51,8 @@ similar perm_invent issue when lock state known and/or contents known become blessed scroll of remove curse read while confused might be shown to operate on itself by perm_invent after player is told that it has disappeared fix memory leak if corpse auto-revival attempt failed ("you feel less hassled") - +allow a parent function to issue an an unplacebc() call that restricts + subsequent placebc() calls to that parent only Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository ------------------------------------------------------------------ diff --git a/include/decl.h b/include/decl.h index 0b7a929a1..5ebaa326e 100644 --- a/include/decl.h +++ b/include/decl.h @@ -431,6 +431,7 @@ struct plinemsg_type { E struct plinemsg_type *plinemsg_types; +enum bcargs {override_restriction = -1}; struct breadcrumbs { const char *funcnm; int linenum; diff --git a/include/extern.h b/include/extern.h index f7e762bda..5f78cb5e7 100644 --- a/include/extern.h +++ b/include/extern.h @@ -130,11 +130,19 @@ E void NDECL(ballfall); #ifndef BREADCRUMBS E void NDECL(placebc); E void NDECL(unplacebc); +E int NDECL(unplacebc_and_covet_placebc); +E void FDECL(lift_covet_and_placebc, (int)); #else E void FDECL(Placebc, (const char *, int)); E void FDECL(Unplacebc, (const char *, int)); +E int FDECL(Unplacebc_and_covet_placebc, (const char *, int)); +E void FDECL(Lift_covet_and_placebc, (int, const char *, int)); #define placebc() Placebc(__FUNCTION__, __LINE__) #define unplacebc() Unplacebc(__FUNCTION__, __LINE__) +#define unplacebc_and_covet_placebc() \ + Unplacebc_and_covet_placebc(__FUNCTION__, __LINE__) +#define lift_covet_and_placebc(x) \ + Lift_covet_and_placebc(x, __FUNCTION__, __LINE__) #endif E void FDECL(set_bc, (int)); E void FDECL(move_bc, (int, int, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); diff --git a/src/ball.c b/src/ball.c index 00352e2b7..81e2d6dd2 100644 --- a/src/ball.c +++ b/src/ball.c @@ -12,10 +12,11 @@ STATIC_DCL int NDECL(bc_order); STATIC_DCL void NDECL(litter); STATIC_OVL void NDECL(placebc_core); STATIC_OVL void NDECL(unplacebc_core); +STATIC_DCL boolean FDECL(check_restriction, (int)); +static int bcrestriction = 0; #ifdef BREADCRUMBS -static struct breadcrumbs bcpbreadcrumbs = { (const char *) 0, 0, FALSE}, - bcubreadcrumbs = { (const char *) 0, 0, FALSE}; +static struct breadcrumbs bcpbreadcrumbs = {0}, bcubreadcrumbs = {0}; #endif void @@ -137,34 +138,9 @@ placebc_core() u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */ newsym(u.ux, u.uy); + bcrestriction = 0; } -#ifdef BREADCRUMBS -void -Placebc(funcnm, linenum) -const char *funcnm; -int linenum; -{ - if (uball && bcpbreadcrumbs.in_effect && uball->where == OBJ_FLOOR) { - impossible("placebc collision from %s:%d, already placed by %s:%d", - funcnm, linenum, - bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); - return; - } - bcpbreadcrumbs.in_effect = TRUE; - bcubreadcrumbs.in_effect = FALSE; - bcpbreadcrumbs.funcnm = funcnm; - bcpbreadcrumbs.linenum = linenum; - placebc_core(); -} -#else -void -placebc() -{ - placebc_core(); -} -#endif - STATIC_OVL void unplacebc_core() { @@ -197,33 +173,190 @@ unplacebc_core() u.bc_felt = 0; /* feel nothing */ } -#ifdef BREADCRUMBS +STATIC_OVL boolean +check_restriction(restriction) +int restriction; +{ + boolean ret = FALSE; + + if (!bcrestriction || (restriction == override_restriction)) + ret = TRUE; + else + ret = (bcrestriction == restriction) ? TRUE : FALSE; + return ret; +} + +#ifndef BREADCRUMBS +void +placebc() +{ + if (!check_restriction(0)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "placebc denied, restriction in effect"); + paniclog("placebc", panicbuf); +#endif + return; + } + if (uchain && uchain->where != OBJ_FREE) { + impossible("bc already placed?"); + return; + } + placebc_core(); +} + +void +unplacebc() +{ + if (bcrestriction) { + impossible("unplacebc denied, restriction in place"); + return; + } + unplacebc_core(); +} + +int +unplacebc_and_covet_placebc() +{ + int restriction = 0; + + if (bcrestriction) { + impossible("unplacebc_and_covet_placebc denied, already restricted"); + } else { + restriction = bcrestriction = rnd(400); + unplacebc_core(); + } + return restriction; +} + +void +lift_covet_and_placebc(pin) +int pin; +{ + if (!check_restriction(pin)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "lift_covet_and_placebc denied, %s", + (pin != bcrestriction) ? + "pin mismatch" : "restriction in effect"); + paniclog("placebc", panicbuf); +#endif + return; + } + if (uchain && uchain->where != OBJ_FREE) { + impossible("bc already placed?"); + return; + } + placebc_core(); +} + +#else /* BREADCRUMBS */ + +void +Placebc(funcnm, linenum) +const char *funcnm; +int linenum; +{ + if (!check_restriction(0)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "Placebc denied to %s:%d, restricted by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + paniclog("Placebc", panicbuf); +#endif + return; + } + if ((uchain && uchain->where != OBJ_FREE) + && bcpbreadcrumbs.in_effect) { + impossible("Placebc collision at %s:%d, already placed by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + return; + } + bcpbreadcrumbs.in_effect = TRUE; + bcubreadcrumbs.in_effect = FALSE; + bcpbreadcrumbs.funcnm = funcnm; + bcpbreadcrumbs.linenum = linenum; + placebc_core(); +} + void Unplacebc(funcnm, linenum) const char *funcnm; int linenum; { -#if 0 - if (uball && bcubreadcrumbs.in_effect && uball->where == OBJ_FREE) { - impossible("unplacebc collision from %s:%d, already placed by %s:%d", + + if (bcrestriction) { + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "Unplacebc from %s:%d, when restricted to %s:%d", funcnm, linenum, bcubreadcrumbs.funcnm, bcubreadcrumbs.linenum); - return; + paniclog("Unplacebc", panicbuf); } -#endif bcpbreadcrumbs.in_effect = FALSE; bcubreadcrumbs.in_effect = TRUE; bcubreadcrumbs.funcnm = funcnm; bcubreadcrumbs.linenum = linenum; unplacebc_core(); } -#else -void -unplacebc() + +int +Unplacebc_and_covet_placebc(funcnm, linenum) +const char *funcnm; +int linenum; { - unplacebc_core(); + int restriction = 0; + + if (bcrestriction) { + impossible( + "Unplacebc_and_covet_placebc denied to %s:%d, restricted by %s:%d", + funcnm, linenum, + bcubreadcrumbs.funcnm, bcubreadcrumbs.linenum); + } else { + restriction = bcrestriction = rnd(400); + bcpbreadcrumbs.in_effect = FALSE; + bcubreadcrumbs.in_effect = TRUE; + bcubreadcrumbs.funcnm = funcnm; + bcubreadcrumbs.linenum = linenum; + unplacebc_core(); + } + return restriction; } + +void +Lift_covet_and_placebc(pin, funcnm, linenum) +int pin; +char *funcnm; +int linenum; +{ + if (!check_restriction(pin)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "Lift_covet_and_placebc denied to %s:%d, restricted by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + paniclog("Lift_covet_and_placebc", panicbuf); #endif + return; + } + if (uchain && uchain->where != OBJ_FREE) { + impossible("bc already placed?"); + return; + } + placebc_core(); +} +#endif /* BREADCRUMBS */ /* * Return the stacking of the hero's ball & chain. This assumes that the diff --git a/src/mkmaze.c b/src/mkmaze.c index f516e6927..2a11ba4ed 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1400,7 +1400,7 @@ movebubbles() struct bubble *b; struct container *cons; struct trap *btrap; - int x, y, i, j; + int x, y, i, j, bcpin; /* set up the portal the first time bubbles are moved */ if (!wportal) @@ -1411,7 +1411,7 @@ movebubbles() if (Is_waterlevel(&u.uz)) { /* keep attached ball&chain separate from bubble objects */ if (Punished) - unplacebc(); + bcpin = unplacebc_and_covet_placebc(); /* * Pick up everything inside of a bubble then fill all bubble @@ -1528,7 +1528,7 @@ movebubbles() /* put attached ball&chain back */ if (Is_waterlevel(&u.uz) && Punished) - placebc(); + lift_covet_and_placebc(bcpin); vision_full_recalc = 1; } From cd862425026af7c11dfcd46da91e685e58d2960f Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 4 Jun 2019 21:46:08 -0400 Subject: [PATCH 13/16] make sure end.c can place the bc --- src/end.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/end.c b/src/end.c index 8aac191f7..0407f2828 100644 --- a/src/end.c +++ b/src/end.c @@ -1041,7 +1041,8 @@ done_object_cleanup() swallowed, uball and uchain will be in limbo; put them on floor so bones will have them and object list cleanup finds them */ if (uchain && uchain->where == OBJ_FREE) { - placebc(); + /* placebc(); */ + lift_covet_and_placebc(override_restriction); } return; } From 02898009a62184a31f438ffb36783928279e0e02 Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 4 Jun 2019 21:49:20 -0400 Subject: [PATCH 14/16] remove some trailing spaces from data.base --- dat/data.base | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dat/data.base b/dat/data.base index d62ce4788..4046259a2 100644 --- a/dat/data.base +++ b/dat/data.base @@ -4384,7 +4384,7 @@ dwarven root are greedy and thriftless, and would not spare till all the plants had perished; whereas now they pass them by as they go blundering in the wild. No more will you learn of me; but you - may have enough of my bounty, as long as you speak fair and + may have enough of my bounty, as long as you speak fair and do not spy or steal." Then again he laughed in his throat. "They are of great worth." he said. "More than gold in the @@ -5353,9 +5353,9 @@ vampire lord of this; but, from what we know, the distance he can make this mist is limited, and it can only be round himself. He come on moonlight rays as elemental dust--as again Jonathan saw those - sisters in the castle of Dracula. He become so small--we + sisters in the castle of Dracula. He become so small--we ourselves saw Miss Lucy, ere she was at peace, slip through a - hairbreadth space at the tomb door. + hairbreadth space at the tomb door. [ Dracula, by Bram Stoker ] The Oxford English Dictionary is quite unequivocal: @@ -5389,8 +5389,8 @@ vlad* *vortex vortices Swirling clouds of pure elemental energies, the vortices are - thought to be related to the larger elementals. They are - noted for being able to envelop unwary travellers. The + thought to be related to the larger elementals. They are + noted for being able to envelop unwary travellers. The hapless fool thus swallowed by a vortex will soon perish from exposure to the element the vortex is composed of. vrock From 43ae30443ded912bbe6fef301c071a86f7b4b5f2 Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 4 Jun 2019 21:58:44 -0400 Subject: [PATCH 15/16] fixes whitespace bit --- doc/fixes36.3 | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 392c7e196..f7c00f175 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -54,6 +54,7 @@ fix memory leak if corpse auto-revival attempt failed ("you feel less hassled") allow a parent function to issue an an unplacebc() call that restricts subsequent placebc() calls to that parent only + Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository ------------------------------------------------------------------ elemental_clog() loop needed to guard against obliteration of the monster From b982e6c52658eae8183c062c0cd6907412178f71 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 5 Jun 2019 04:16:34 -0700 Subject: [PATCH 16/16] location viability on Plane of Water While testing, I noticed that I could completely fill the Water level with air elementals. Hero can't fly or levitate or water walk into/onto water locations on Water level without drowning/crawling out the water, and monsters shouldn't have been able to but could, then they were hit by drowning since minliquid used different criteria than movement. But goodpos(), used for teleport destination and new monster creation among other things, consided water locations acceptable on that level for non-aquadic creatures with Fly/Lev/Wwalk ability. It explains why so many dragons and other 'nasty' monsters have been ending up on the vanquished monsters list when hero uses level teleport to go directly there from level 1. They've either been getting created in water and then they drown when it's their turn to move or moving into it to approach the hero and drowning (not sure whether that case is immediate or on next move). There's no message since hero doesn't see it, and air elementals didn't drown since thy don't breathe. --- doc/fixes36.3 | 6 +++++- src/makemon.c | 3 ++- src/mon.c | 19 +++++++++++++------ src/teleport.c | 22 ++++++++++++++++------ 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index f7c00f175..2bebd4e0f 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.38 $ $NHDT-Date: 1559685281 2019/06/04 21:54:41 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.41 $ $NHDT-Date: 1559733390 2019/06/05 11:16:30 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -53,6 +53,10 @@ blessed scroll of remove curse read while confused might be shown to operate fix memory leak if corpse auto-revival attempt failed ("you feel less hassled") allow a parent function to issue an an unplacebc() call that restricts subsequent placebc() calls to that parent only +flying monsters could enter water on the Plane of Water but then they'd drown + unless they could also swim or else didn't need to breathe +when finding a place to put a monster on the Plane of Water, don't pick a + water location for flyers or floaters (levitate) or clingers (ceiling) Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/makemon.c b/src/makemon.c index 94ee223dd..b2cb2c8a1 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 makemon.c $NHDT-Date: 1556150377 2019/04/24 23:59:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.134 $ */ +/* NetHack 3.6 makemon.c $NHDT-Date: 1559733390 2019/06/05 11:16:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.137 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1120,6 +1120,7 @@ int mmflags; struct monst fakemon; cc.x = cc.y = 0; /* lint suppression */ + fakemon = zeromonst; fakemon.data = ptr; /* set up for goodpos */ if (!makemon_rnd_goodpos(ptr ? &fakemon : (struct monst *)0, gpflags, &cc)) diff --git a/src/mon.c b/src/mon.c index a20592fc7..e281cb392 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1559596286 2019/06/03 21:11:26 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.291 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1559733390 2019/06/05 11:16:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.292 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -493,7 +493,7 @@ register struct monst *mtmp; { boolean inpool, inlava, infountain; - /* [what about ceiling clingers?] */ + /* [ceiling clingers are handled below] */ inpool = (is_pool(mtmp->mx, mtmp->my) && (!(is_flyer(mtmp->data) || is_floater(mtmp->data)) /* there's no "above the surface" on the plane of water */ @@ -1326,10 +1326,16 @@ long flag; nowtyp = levl[x][y].typ; nodiag = NODIAG(mdat - mons); - wantpool = mdat->mlet == S_EEL; - poolok = (is_flyer(mdat) || is_clinger(mdat) + wantpool = (mdat->mlet == S_EEL); + poolok = ((!Is_waterlevel(&u.uz) + && (is_flyer(mdat) || is_floater(mdat) || is_clinger(mdat))) || (is_swimmer(mdat) && !wantpool)); - lavaok = (is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat)); + /* note: floating eye is the only is_floater() so this could be + simplified, but then adding another floater would be error prone */ + lavaok = (is_flyer(mdat) || is_floater(mdat) || is_clinger(mdat) + || likes_lava(mdat)); + if (mdat == &mons[PM_FLOATING_EYE]) /* prefers to avoid heat */ + lavaok = FALSE; thrudoor = ((flag & (ALLOW_WALL | BUSTDOOR)) != 0L); poisongas_ok = ((nonliving(mdat) || is_vampshifter(mon) || breathless(mdat)) || resists_poison(mon)); @@ -2686,7 +2692,8 @@ struct monst *mon; rloc_to(mon, mx, my); /* note: mon, not mtmp */ } else { /* last resort - migrate mon to the next plane */ - if (Is_waterlevel(&u.uz) || Is_firelevel(&u.uz) || Is_earthlevel(&u.uz)) { + if (Is_waterlevel(&u.uz) || Is_firelevel(&u.uz) + || Is_earthlevel(&u.uz)) { /* try sending mon on to the next plane */ xchar target_lev = 0, xyloc = 0; struct trap *trap = ftrap; diff --git a/src/teleport.c b/src/teleport.c index fe5689aeb..61ca40fa7 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 teleport.c $NHDT-Date: 1559227830 2019/05/30 14:50:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.87 $ */ +/* NetHack 3.6 teleport.c $NHDT-Date: 1559733391 2019/06/05 11:16:31 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.88 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -62,16 +62,26 @@ unsigned gpflags; mdat = mtmp->data; if (is_pool(x, y) && !ignorewater) { + /* [what about Breathless?] */ if (mtmp == &youmonst) - return (Levitation || Flying || Wwalking || Swimming - || Amphibious); + return (Swimming || Amphibious + || (!Is_waterlevel(&u.uz) + /* water on the Plane of Water has no surface + so there's no way to be on or above that */ + && (Levitation || Flying || Wwalking))); else - return (is_floater(mdat) || is_flyer(mdat) || is_swimmer(mdat) - || is_clinger(mdat)); + return (is_swimmer(mdat) + || (!Is_waterlevel(&u.uz) + && (is_floater(mdat) || is_flyer(mdat) + || is_clinger(mdat)))); } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) { return FALSE; } else if (is_lava(x, y)) { - if (mtmp == &youmonst) + /* 3.6.3: floating eye can levitate over lava but it avoids + that due the effect of the heat causing it to dry out */ + if (mdat == &mons[PM_FLOATING_EYE]) + return FALSE; + else if (mtmp == &youmonst) return (Levitation || Flying || (Fire_resistance && Wwalking && uarmf && uarmf->oerodeproof)