From ed08938ada65849e58592cf660c6222e074d6c3a Mon Sep 17 00:00:00 2001 From: Bart House Date: Sun, 23 Jun 2019 21:39:22 -0700 Subject: [PATCH 1/2] Fix dangling chain bug. If a punished player picks up the iron ball, gets engulfed and saves, then the saved game will have missed saving the dangling chain since it was not on the floor or in the inventory. Upon restoring the saved game, the game will be in a bad state since the ball will be worn but the chain will be missing. --- include/hack.h | 1 + src/restore.c | 27 +++++++++++++++------------ src/save.c | 19 ++++++++++++------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/include/hack.h b/include/hack.h index 0b8a780a4..5ba3bb9a0 100644 --- a/include/hack.h +++ b/include/hack.h @@ -436,6 +436,7 @@ enum bodypart_types { #define POTION_OCCUPANT_CHANCE(n) (13 + 2 * (n)) #define WAND_BACKFIRE_CHANCE 100 #define BALL_IN_MON (u.uswallow && uball && uball->where == OBJ_FREE) +#define CHAIN_IN_MON (u.uswallow && uchain && uchain->where == OBJ_FREE) #define NODIAG(monnum) ((monnum) == PM_GRID_BUG) /* Flags to control menus */ diff --git a/src/restore.c b/src/restore.c index 4f19ed878..010ef75c8 100644 --- a/src/restore.c +++ b/src/restore.c @@ -540,7 +540,8 @@ unsigned int *stuckid, *steedid; struct sysflag newgamesysflags; #endif struct context_info newgamecontext; /* all 0, but has some pointers */ - struct obj *otmp, *tmp_bc; + struct obj *otmp; + struct obj *bc_obj; char timebuf[15]; unsigned long uid; boolean defer_perm_invent; @@ -643,17 +644,15 @@ unsigned int *stuckid, *steedid; restore_timers(fd, RANGE_GLOBAL, FALSE, 0L); restore_light_sources(fd); invent = restobjchn(fd, FALSE, FALSE); - /* tmp_bc only gets set here if the ball & chain were orphaned - because you were swallowed; otherwise they will be on the floor - or in your inventory */ - tmp_bc = restobjchn(fd, FALSE, FALSE); - if (tmp_bc) { - for (otmp = tmp_bc; otmp; otmp = otmp->nobj) { - if (otmp->owornmask) - setworn(otmp, otmp->owornmask); - } - if (!uball || !uchain) - impossible("restgamestate: lost ball & chain"); + + /* restore dangling (not on floor or in inventory) ball and/or chain */ + bc_obj = restobjchn(fd, FALSE, FALSE); + while(bc_obj) { + struct obj * nobj = bc_obj->nobj; + if (bc_obj->owornmask) + setworn(bc_obj, bc_obj->owornmask); + bc_obj->nobj = (struct obj *)0; + bc_obj = nobj; } migrating_objs = restobjchn(fd, FALSE, FALSE); @@ -671,6 +670,10 @@ unsigned int *stuckid, *steedid; for (otmp = invent; otmp; otmp = otmp->nobj) if (otmp->owornmask) setworn(otmp, otmp->owornmask); + + if ((uball && !uchain) || (uchain && !uball)) + impossible("restgamestate: lost ball & chain"); + /* reset weapon so that player will get a reminder about "bashing" during next fight when bare-handed or wielding an unconventional item; for pick-axe, we aren't able to distinguish between having diff --git a/src/save.c b/src/save.c index 8bca5964a..e0af4b8d2 100644 --- a/src/save.c +++ b/src/save.c @@ -280,6 +280,7 @@ savegamestate(fd, mode) register int fd, mode; { unsigned long uid; + struct obj * bc_objs = (struct obj *)0; #ifdef MFLOPPY count_only = (mode & COUNT_SAVE); @@ -307,14 +308,18 @@ register int fd, mode; save_light_sources(fd, mode, RANGE_GLOBAL); saveobjchn(fd, invent, mode); - if (BALL_IN_MON) { - /* prevent loss of ball & chain when swallowed */ - uball->nobj = uchain; - uchain->nobj = (struct obj *) 0; - saveobjchn(fd, uball, mode); - } else { - saveobjchn(fd, (struct obj *) 0, mode); + + /* save ball and chain if they are currently dangling free (i.e. not on + floor or in inventory) */ + if (CHAIN_IN_MON) { + uchain->nobj = bc_objs; + bc_objs = uchain; } + if (BALL_IN_MON) { + uball->nobj = bc_objs; + bc_objs = uball; + } + saveobjchn(fd, bc_objs, mode); saveobjchn(fd, migrating_objs, mode); savemonchn(fd, migrating_mons, mode); From cfc8599e69884f81ca13ae81f61f675b4d2c6ead Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 24 Jun 2019 15:11:51 -0700 Subject: [PATCH 2/2] fix "Bad fruit #N" warnings when saving bones savebones() sets all the fruit indices negative, then resets to the normal positive value for each fruit it actually writes into the bones file. But if 'perm_invent' is enabled and something triggers an update_inventory() while bones saving is in progress, object formatting for the inventory display won't be able to find any fruits, resulting in impossible "Bad fruit #N". Fix is to turn off 'perm_invent' when the game ends, so it won't be On when bones are written. Disclosure uses a popup for inventory so persistent window is obsolete by then anyway. [I don't know what is triggering update_inventory() while savebones() is executing. Also, I don't see where the fruits whose index stayed negative--because there aren't any on level being saved--get purged. Maybe when those bones are loaded by another game?] --- doc/fixes36.3 | 3 ++- src/end.c | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index c71dc5bb6..98a1c79f3 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.65 $ $NHDT-Date: 1561314651 2019/06/23 18:30:51 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.66 $ $NHDT-Date: 1561414302 2019/06/24 22:11:42 $ 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, @@ -87,6 +87,7 @@ partly eaten food with one bite left had message anomalies when eaten; the wizard mode ^I menu could list "Not carrying anything" after inventory items if perm_invent option was On (even on tty where that's not supported) change #adjust to treat carrying only gold as not having anything to adjust +saving bones with 'perm_invent' On could result in "Bad fruit #N" warnings Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/end.c b/src/end.c index 0407f2828..8ffcd5c66 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1559675615 2019/06/04 19:13:35 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.176 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1561414303 2019/06/24 22:11:43 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.178 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1044,6 +1044,12 @@ done_object_cleanup() /* placebc(); */ lift_covet_and_placebc(override_restriction); } + /* persistent inventory window now obsolete since disclosure uses + a normal popup one; avoids "Bad fruit #n" when saving bones */ + if (iflags.perm_invent) { + iflags.perm_invent = FALSE; + update_inventory(); /* make interface notice the change */ + } return; } @@ -1223,6 +1229,8 @@ int how; deal with ball and chain possibly being temporarily off the map */ if (!program_state.panicking) done_object_cleanup(); + /* in case we're panicking; normally cleared by done_object_cleanup() */ + iflags.perm_invent = FALSE; /* remember time of death here instead of having bones, rip, and topten figure it out separately and possibly getting different