From ef17c7ac2b8e13b3d9ab329e3409a4264b1a124a Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 23 Mar 2024 10:11:35 -0700 Subject: [PATCH] unix check_panic_save Inspired by self-recover, sort of. Enabled for unix by default; can be disabled by commenting out '#define CHECK_PANIC_SAVE' in unixconf.h. When starting the game, if there is no save file to restore and no lock/level files to recover, check whether a panic save file exists. If there is one, tell the player that it's there and that it might be viable, then ask whether to start a new game. It doesn't convert the panic save into a reconverable one (rename by nethack, then continue trying to restore) or tell the player how to make it viable (rename to remove ".e" by game admin), just whether it is present. If player opts to start a new game, the panic save is left alone and will trigger the "there's a panic save file" situation again once the new game finishes and player starts another. --- include/extern.h | 14 +++++++----- include/unixconf.h | 17 +++++++++++++- src/files.c | 56 +++++++++++++++++++++++++++++++++++++++++---- sys/unix/unixmain.c | 12 +++++++++- sys/unix/unixunix.c | 46 ++++++++++++++++++++++++++++++++++--- 5 files changed, 129 insertions(+), 16 deletions(-) diff --git a/include/extern.h b/include/extern.h index 070dc9886..73d61975b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1710792423 2024/03/18 20:07:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1398 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1711213872 2024/03/23 17:11:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1400 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1010,6 +1010,12 @@ extern NHFILE *create_savefile(void); extern NHFILE *open_savefile(void); extern int delete_savefile(void); extern NHFILE *restore_saved_game(void); +extern int check_panic_save(void); +#ifdef SELECTSAVED +extern char *plname_from_file(const char *, boolean) NONNULLARG1; +#endif +extern char **get_saved_games(void); +extern void free_saved_games(char **); extern void nh_compress(const char *); extern void nh_uncompress(const char *); extern boolean lock_file(const char *, int, int) NONNULLARG1; @@ -1032,11 +1038,6 @@ extern int read_sym_file(int); extern void paniclog(const char *, const char *) NONNULLPTRS; extern void testinglog(const char *, const char *, const char *); extern int validate_prefix_locations(char *); -#ifdef SELECTSAVED -extern char *plname_from_file(const char *, boolean) NONNULLARG1; -#endif -extern char **get_saved_games(void); -extern void free_saved_games(char **); #ifdef SELF_RECOVER extern boolean recover_savefile(void); extern void assure_syscf_file(void); @@ -3325,6 +3326,7 @@ extern void tty_utf8graphics_fixup(void); #ifdef UNIX extern void getlock(void); +extern void ask_about_panic_save(void); extern void regularize(char *) NONNULLARG1; #if defined(TIMED_DELAY) && !defined(msleep) && defined(SYSV) extern void msleep(unsigned); diff --git a/include/unixconf.h b/include/unixconf.h index 2c0d133e2..e27f542d2 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 unixconf.h $NHDT-Date: 1607461111 2020/12/08 20:58:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.49 $ */ +/* NetHack 3.7 unixconf.h $NHDT-Date: 1711213886 2024/03/23 17:11:26 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.57 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -118,6 +118,21 @@ #define TIMED_DELAY #endif +/* + * At start of game, if there are lock and level files for current + * character in the playground directory, ask whether to recover them + * (into a save file). + */ +/* #define SELF_RECOVER */ + +/* + * At start of game, if there is no save file to restore or lock and + * level files to recover but there is a panic save file for the current + * character, tell the player that it exists and ask whether to start a + * new game. Does not attempt to rename and restore the panic save file. + */ +#define CHECK_PANIC_SAVE + /* #define AVOID_WIN_IOCTL */ /* ensure USE_WIN_IOCTL remains undefined */ /* diff --git a/src/files.c b/src/files.c index 1fddb59d5..b44b2d737 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 files.c $NHDT-Date: 1693083234 2023/08/26 20:53:54 $ $NHDT-Branch: keni-crashweb2 $:$NHDT-Revision: 1.378 $ */ +/* NetHack 3.7 files.c $NHDT-Date: 1711213887 2024/03/23 17:11:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.397 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1205,6 +1205,50 @@ restore_saved_game(void) return nhfp; } +/* called if there is no save file for current character */ +int +check_panic_save(void) +{ + int result = 0; +#ifdef CHECK_PANIC_SAVE + FILE *cf; + const char *savef; + + set_error_savefile(); + savef = fqname(gs.SAVEF, SAVEPREFIX, 0); + + /* + * This duplicates part of docompress_file(). + * We don't want to start by uncompressing just to check for the + * file's existence and then have to recompress it. + */ + +#ifdef COMPRESS_EXTENSION + unsigned ln = (unsigned) (strlen(savef) + strlen(COMPRESS_EXTENSION)); + char *cfn = (char *) alloc(ln + 1); + + Strcpy(cfn, savef); + Strcat(cfn, COMPRESS_EXTENSION); + if ((cf = fopen(cfn, RDBMODE)) != NULL) { + (void) fclose(cf); + result = 1; + } + free((genericptr_t) cfn); +#endif /* COMPRESS_EXTENSION */ + + if (!result) { + /* maybe it has already been manually uncompressed */ + if ((cf = fopen(savef, RDBMODE)) != NULL) { + (void) fclose(cf); + result = 1; + } + } + + set_savefile_name(TRUE); /* reset to normal */ +#endif /* CHECK_PANIC_SAVE */ + return result; +} + #if defined(SELECTSAVED) char * @@ -1252,11 +1296,11 @@ plname_from_file(const char *filename, boolean without_wait_synch_per_file) #define EXTSTR "" #endif - if ( sscanf( filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name ) == 2 ) { + if (sscanf(filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name) == 2) { #undef EXTSTR /* "_" most likely means " ", which certainly looks nicer */ - for (k=0; name[k]; k++) - if ( name[k] == '_' ) + for (k = 0; name[k]; k++) + if (name[k] == '_') name[k] = ' '; return dupstr(name); } else @@ -1376,7 +1420,8 @@ get_saved_games(void) char *r; Sprintf(filename, "save/%d%s", uid, name); - r = plname_from_file(filename, ALLOW_WAITSYNCH_PERFILE); + r = plname_from_file(filename, + ALLOW_WAITSYNCH_PERFILE); if (r) result[j++] = r; } @@ -1629,6 +1674,7 @@ docompress_file(const char *filename, boolean uncomp) } free((genericptr_t) cfn); + return; } #endif /* COMPRESS : external compression */ diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 940b28619..1a22fd96a 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 unixmain.c $NHDT-Date: 1708737183 2024/02/24 01:13:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.126 $ */ +/* NetHack 3.7 unixmain.c $NHDT-Date: 1711213891 2024/03/23 17:11:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.127 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -305,6 +305,16 @@ main(int argc, char *argv[]) goto attempt_restore; } } + +#ifdef CHECK_PANIC_SAVE + /* no save file; check for a panic save; if the check finds one, + ask the player whether to proceed with a new game; it will + quit instead of returning if the answer isn't yes */ + if (check_panic_save()) + ask_about_panic_save(); +#endif + + /* no save file; start a new game */ newgame(); wd_message(); } diff --git a/sys/unix/unixunix.c b/sys/unix/unixunix.c index 7c21580d4..de465f9b1 100644 --- a/sys/unix/unixunix.c +++ b/sys/unix/unixunix.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 unixunix.c $NHDT-Date: 1687124609 2023/06/18 21:43:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.39 $ */ +/* NetHack 3.7 unixunix.c $NHDT-Date: 1711213894 2024/03/23 17:11:34 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.43 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -182,14 +182,17 @@ getlock(void) unlock_file(HLOCK); if (iflags.window_inited) { #ifdef SELF_RECOVER - c = yn_function("Old game in progress. Destroy [y], Recover [r], or Cancel [n]?", "ynr", 'n', FALSE); + c = yn_function( + "Old game in progress. Destroy [y], Recover [r], or Cancel [n]?", + "ynr", 'n', FALSE); #else /* this is a candidate for paranoid_confirmation */ c = y_n(destroy_old_game_prompt); #endif } else { #ifdef SELF_RECOVER - (void) raw_printf("\nThere is already a game in progress under your name. Do what?\n"); + (void) raw_printf( + "\nThere is already a game in progress under your name. Do what?\n"); (void) raw_printf("\n y - Destroy old game"); (void) raw_printf("\n r - Try to recover it"); (void) raw_printf("\n n - Cancel"); @@ -241,17 +244,54 @@ getlock(void) unlock_file(HLOCK); if (fd == -1) { error("cannot creat lock file (%s).", fq_lock); + /*NOTREACHED*/ } else { if (write(fd, (genericptr_t) &gh.hackpid, sizeof gh.hackpid) != sizeof gh.hackpid) { error("cannot write lock (%s)", fq_lock); + /*NOTREACHED*/ } if (close(fd) == -1) { error("cannot close lock (%s)", fq_lock); + /*NOTREACHED*/ } } } +/* caller couldn't find a regular save file but did find a panic one */ +void +ask_about_panic_save(void) +{ +#ifdef CHECK_PANIC_SAVE + static const char Instead_prompt[] = "Start a new game instead?"; + int c = '\0'; + + pline("There is no regular save file but there is a panic one."); + pline("It might be recoverable with demi-divine intervention."); + if (iflags.window_inited) { + c = yn_function(Instead_prompt, "yn\033q", 'n', FALSE); + } else { + raw_printf("%s [yn] (n) ", Instead_prompt); + (void) fflush(stdout); + do { + c = getchar(); + if (c == EOF || c == '\033' || c == '\0') + break; + c = lowc(c); + } while (!strchr("ynq\n", c)); + } + if (c != 'y') { + /* caller successfully called getlock() and made .0 */ + delete_levelfile(0); + unlock_file(HLOCK); /* just in case, release 'perm' */ + if (iflags.window_inited) + exit_nhwindows((char *) 0); + nh_terminate(EXIT_SUCCESS); + } +#endif + return; /* proceed with new game */ +} + /* normalize file name - we don't like .'s, /'s, spaces */ void regularize(char *s)