From fb0509a6b3ed83d526c1540b505479882f0880bf Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 14 Jun 2023 00:04:21 -0700 Subject: [PATCH] fix #3841 - steed and engulfer on same map spot Reported five months ago, a save was performed while a mounted hero was engulfed. Restore issued a warning about the engulfer being placed on top of the steed (who shouldn't have been on the map). The report arrived at about the same time as engulfing a riding hero was changed to force a dismount instead of engulfing both hero and steed so nothing further was done about it. This changes restore to not put a steed on the map and then take it off again. It also attempts to simplify usteed and ustuck handling during save and restore. Testing so far indicates that things are still working correctly. Keep makeplural(body_part(FINGER)) crossed. Existing save and bones files are invalidated. --- include/decl.h | 4 +-- include/patchlevel.h | 4 +-- include/you.h | 4 ++- src/decl.c | 4 +-- src/restore.c | 78 ++++++++++++++++++-------------------------- src/save.c | 24 ++++---------- 6 files changed, 46 insertions(+), 72 deletions(-) diff --git a/include/decl.h b/include/decl.h index c17583f52..1b3d1aae3 100644 --- a/include/decl.h +++ b/include/decl.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 decl.h $NHDT-Date: 1657918080 2022/07/15 20:48:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.303 $ */ +/* NetHack 3.7 decl.h $NHDT-Date: 1686726249 2023/06/14 07:04:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.333 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2007. */ /* NetHack may be freely redistributed. See license for details. */ @@ -968,8 +968,6 @@ struct instance_globals_u { struct Race urace; /* player's race. May be munged in role_init() */ /* save.c */ - unsigned ustuck_id; /* need to preserve during save */ - unsigned usteed_id; /* need to preserve during save */ d_level uz_save; /* new stuff */ diff --git a/include/patchlevel.h b/include/patchlevel.h index 85c96f87b..b882ce523 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 patchlevel.h $NHDT-Date: 1651297020 2022/04/30 05:37:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.207 $ */ +/* NetHack 3.7 patchlevel.h $NHDT-Date: 1686726254 2023/06/14 07:04:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.241 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 86 +#define EDITLEVEL 87 /* * Development status possibilities. diff --git a/include/you.h b/include/you.h index 08fe7cc0c..439f9aeda 100644 --- a/include/you.h +++ b/include/you.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 you.h $NHDT-Date: 1596498576 2020/08/03 23:49:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.48 $ */ +/* NetHack 3.7 you.h $NHDT-Date: 1686726254 2023/06/14 07:04:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.72 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2016. */ /* NetHack may be freely redistributed. See license for details. */ @@ -471,6 +471,8 @@ struct you { int uinvault; struct monst *ustuck; /* engulfer or grabber, maybe grabbee if Upolyd */ struct monst *usteed; /* mount when riding */ + unsigned ustuck_mid; /* u.ustuck->m_id, used during save/restore */ + unsigned usteed_mid; /* u.usteed->m_id, used during save/restore */ long ugallop; /* turns steed will run after being kicked */ int urideturns; /* time spent riding, for skill advancement */ int umortality; /* how many times you died */ diff --git a/src/decl.c b/src/decl.c index 1ad533490..e5a27440d 100644 --- a/src/decl.c +++ b/src/decl.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 decl.c $NHDT-Date: 1661896581 2022/08/30 21:56:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.266 $ */ +/* NetHack 3.7 decl.c $NHDT-Date: 1686726255 2023/06/14 07:04:15 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.286 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -807,8 +807,6 @@ const struct instance_globals_u g_init_u = { { UNDEFINED_VALUES }, /* urole */ UNDEFINED_VALUES, /* urace */ /* save.c */ - 0U, /* ustuck_id */ - 0U, /* usteed_id */ { 0, 0 }, /* uz_save */ TRUE, /* havestate*/ IVMAGIC /* u_magic to validate that structure layout has been preserved */ diff --git a/src/restore.c b/src/restore.c index bd5c9ef43..8a6f61ea6 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 restore.c $NHDT-Date: 1649530943 2022/04/09 19:02:23 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.194 $ */ +/* NetHack 3.7 restore.c $NHDT-Date: 1686726258 2023/06/14 07:04:18 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.211 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -27,8 +27,8 @@ static struct monst *restmonchn(NHFILE *); static struct fruit *loadfruitchn(NHFILE *); static void freefruitchn(struct fruit *); static void ghostfruit(struct obj *); -static boolean restgamestate(NHFILE *, unsigned int *, unsigned int *); -static void restlevelstate(unsigned int, unsigned int); +static boolean restgamestate(NHFILE *); +static void restlevelstate(void); static int restlevelfile(xint8); static void rest_bubbles(NHFILE *); static void restore_gamelog(NHFILE *); @@ -504,9 +504,7 @@ ghostfruit(register struct obj *otmp) static boolean -restgamestate( - NHFILE *nhfp, - unsigned *stuckid, unsigned *steedid) +restgamestate(NHFILE *nhfp) { struct flag newgameflags; struct context_info newgamecontext; /* all 0, but has some pointers */ @@ -670,14 +668,6 @@ restgamestate( } restore_artifacts(nhfp); restore_oracles(nhfp); - if (u.ustuck) { - if (nhfp->structlevel) - Mread(nhfp->fd, stuckid, sizeof *stuckid); - } - if (u.usteed) { - if (nhfp->structlevel) - Mread(nhfp->fd, steedid, sizeof *steedid); - } if (nhfp->structlevel) { Mread(nhfp->fd, gp.pl_character, sizeof gp.pl_character); Mread(nhfp->fd, gp.pl_fruit, sizeof gp.pl_fruit); @@ -698,30 +688,15 @@ restgamestate( } /* update game state pointers to those valid for the current level (so we - * don't dereference a wild u.ustuck when saving the game state, for instance) - */ + don't dereference a wild u.ustuck when saving game state, for instance) */ static void -restlevelstate(unsigned int stuckid, unsigned int steedid) +restlevelstate(void) { - register struct monst *mtmp; - - if (stuckid) { - for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) - if (mtmp->m_id == stuckid) - break; - if (!mtmp) - panic("Cannot find the monster ustuck."); - set_ustuck(mtmp); - } - if (steedid) { - for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) - if (mtmp->m_id == steedid) - break; - if (!mtmp) - panic("Cannot find the monster usteed."); - u.usteed = mtmp; - remove_monster(mtmp->mx, mtmp->my); - } + /* + * Note: restoring steed and engulfer/holder/holdee is now handled + * in getlev() and there's nothing left for restlevelstate() to do. + */ + return; } /*ARGSUSED*/ @@ -747,7 +722,6 @@ restlevelfile(xint8 ltmp) int dorecover(NHFILE *nhfp) { - unsigned int stuckid = 0, steedid = 0; /* not a register */ xint8 ltmp = 0; int rtmp; @@ -756,7 +730,7 @@ dorecover(NHFILE *nhfp) get_plname_from_file(nhfp, gp.plname); getlev(nhfp, 0, (xint8) 0); - if (!restgamestate(nhfp, &stuckid, &steedid)) { + if (!restgamestate(nhfp)) { NHFILE tnhfp; display_nhwindow(WIN_MESSAGE, TRUE); @@ -764,14 +738,15 @@ dorecover(NHFILE *nhfp) tnhfp.mode = FREEING; tnhfp.fd = -1; savelev(&tnhfp, 0); /* discard current level */ - /* no need tfor close_nhfile(&tnhfp), which + /* no need for close_nhfile(&tnhfp), which is not really affiliated with an open file */ close_nhfile(nhfp); (void) delete_savefile(); + u.usteed_mid = u.ustuck_mid = 0; gp.program_state.restoring = 0; return 0; } - restlevelstate(stuckid, steedid); + restlevelstate(); #ifdef INSURANCE savestateinlock(); #endif @@ -842,7 +817,7 @@ dorecover(NHFILE *nhfp) getlev(nhfp, 0, (xint8) 0); close_nhfile(nhfp); - restlevelstate(stuckid, steedid); + restlevelstate(); gp.program_state.something_worth_saving = 1; /* useful data now exists */ if (!wizard && !discover) @@ -884,6 +859,7 @@ dorecover(NHFILE *nhfp) ge.early_raw_messages = 0; wait_synch(); } + u.usteed_mid = u.ustuck_mid = 0; gp.program_state.beyond_savefile_load = 1; docrt(); @@ -1124,11 +1100,21 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (mtmp->isshk) set_residency(mtmp, FALSE); - place_monster(mtmp, mtmp->mx, mtmp->my); - if (mtmp->wormno) - place_wsegs(mtmp, NULL); - if (hides_under(mtmp->data) && mtmp->mundetected) - (void) hideunder(mtmp); + if (mtmp->m_id == u.usteed_mid) { + /* steed is kept on fmon list but off the map */ + u.usteed = mtmp; + u.usteed_mid = 0; + } else { + if (mtmp->m_id == u.ustuck_mid) { + set_ustuck(mtmp); + u.ustuck_mid = 0; + } + place_monster(mtmp, mtmp->mx, mtmp->my); + if (mtmp->wormno) + place_wsegs(mtmp, NULL); + if (hides_under(mtmp->data) && mtmp->mundetected) + (void) hideunder(mtmp); + } /* regenerate monsters while on another level */ if (!u.uz.dlevel) diff --git a/src/save.c b/src/save.c index aa8bfe02d..3dbe549ce 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 save.c $NHDT-Date: 1661240721 2022/08/23 07:45:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.195 $ */ +/* NetHack 3.7 save.c $NHDT-Date: 1686726259 2023/06/14 07:04:19 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.206 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -161,8 +161,6 @@ dosave0(void) if (nhfp && nhfp->fplog) (void) fprintf(nhfp->fplog, "# post-validation\n"); store_plname_in_file(nhfp); - gu.ustuck_id = (u.ustuck ? u.ustuck->m_id : 0); - gu.usteed_id = (u.usteed ? u.usteed->m_id : 0); /* savelev() might save uball and uchain, releasing their memory if FREEING, so we need to check their status now; if hero is swallowed, uball and uchain will persist beyond saving map floor and inventory @@ -328,16 +326,6 @@ savegamestate(NHFILE *nhfp) } save_artifacts(nhfp); save_oracles(nhfp); - if (gu.ustuck_id) { - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &gu.ustuck_id, - sizeof gu.ustuck_id); - } - if (gu.usteed_id) { - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &gu.usteed_id, - sizeof gu.usteed_id); - } if (nhfp->structlevel) { bwrite(nhfp->fd, (genericptr_t) gp.pl_character, sizeof gp.pl_character); @@ -437,8 +425,6 @@ savestateinlock(void) store_savefileinfo(nhfp); store_plname_in_file(nhfp); - gu.ustuck_id = (u.ustuck ? u.ustuck->m_id : 0); - gu.usteed_id = (u.usteed ? u.usteed->m_id : 0); /* if ball and/or chain aren't on floor or in invent, keep a copy of their pointers; not valid when on floor or in invent */ gl.looseball = BALL_IN_MON ? uball : 0; @@ -973,6 +959,10 @@ savemonchn(NHFILE* nhfp, register struct monst* mtmp) gc.context.polearm.m_id = mtmp->m_id; gc.context.polearm.hitmon = NULL; } + if (mtmp == u.ustuck) + u.ustuck_mid = u.ustuck->m_id; + if (mtmp == u.usteed) + u.usteed_mid = u.usteed->m_id; mtmp->nmon = NULL; /* nmon saved into mtmp2 */ dealloc_monst(mtmp); } @@ -1071,7 +1061,7 @@ savelevchn(NHFILE* nhfp) } void -store_plname_in_file(NHFILE* nhfp) +store_plname_in_file(NHFILE *nhfp) { int plsiztmp = PL_NSIZ; @@ -1086,7 +1076,7 @@ store_plname_in_file(NHFILE* nhfp) } static void -save_msghistory(NHFILE* nhfp) +save_msghistory(NHFILE *nhfp) { char *msg; int msgcount = 0, msglen;