mwp@munmurra.mu.oz (Michael Paddon) (08/25/88)
I tried installing the anticrash patches recently posted to the net, but they didn't seem to work properly at our installation. The problems may have been caused by the fact that the save code is *extremely* destructive. The idea was very good, however. Who hasn't been frustrated by losing a really good mega-game once in a while due to a program or system crash? So I hacked up my own solution to the problem. The following patch causes NetHack to save the game every time the player goes to a new level in any fashion (stairs, traps, teleport etc.). No attempt at efficency has been made -- but the mechanism should be reliable as very little code has been changed or added, and the game is always saved in a reasonable state. Of course, the saved game is removed whenever the players wins, quits or dies (unless the death is due to a panic). The patch must be enabled by #defining CHECKPOINTS in the config.h file. Michael Paddon ============== ------------------------------------------------------------------------ *** end.c.orig Wed Aug 24 21:53:31 1988 --- end.c Wed Aug 24 21:40:18 1988 *************** *** 89,94 /* was exit(1) */ home(); cls(); puts(" Suddenly, the dungeon collapses."); #ifdef WIZARD pline("Report error to %s and it may be possible to rebuild.",WIZARD); more(); --- 89,95 ----- /* was exit(1) */ home(); cls(); puts(" Suddenly, the dungeon collapses."); + #ifndef CHECKPOINTS #ifdef WIZARD pline("Report error to %s and it may be possible to rebuild.",WIZARD); more(); *************** *** 95,100 (void) sprintf (SAVEF, "%s.e", SAVEF); dosave0(0); #endif fputs(" ERROR: ", stdout); printf(str,a1,a2,a3,a4,a5,a6); more(); /* contains a fflush() */ --- 96,102 ----- (void) sprintf (SAVEF, "%s.e", SAVEF); dosave0(0); #endif + #endif fputs(" ERROR: ", stdout); printf(str,a1,a2,a3,a4,a5,a6); more(); /* contains a fflush() */ *************** *** 117,122 #endif #ifdef WIZARD extern char *nomovemsg; if(wizard && index("bcds", *st1)){ char buf[BUFSZ]; --- 119,129 ----- #endif #ifdef WIZARD extern char *nomovemsg; + + #ifdef CHECKPOINTS + if (strcmp (st1,"panicked") != 0) + (void) unlink (SAVEF); + #endif if(wizard && index("bcds", *st1)){ char buf[BUFSZ]; *** save.c.orig Wed Aug 24 21:52:46 1988 --- save.c Wed Aug 24 22:38:31 1988 *************** *** 18,23 dosave(){ clear_screen(); fflush(stdout); if(dosave0(0)) { settty("Be seeing you ...\n"); exit(0); --- 18,26 ----- dosave(){ clear_screen(); fflush(stdout); + #ifdef CHECKPOINTS + if(dosave0(0,0)) { + #else if(dosave0(0)) { #endif settty("Be seeing you ...\n"); *************** *** 19,24 clear_screen(); fflush(stdout); if(dosave0(0)) { settty("Be seeing you ...\n"); exit(0); } --- 22,28 ----- if(dosave0(0,0)) { #else if(dosave0(0)) { + #endif settty("Be seeing you ...\n"); exit(0); } *************** *** 29,34 #ifndef NOSAVEONHANGUP hangup(){ (void) dosave0(1); exit(1); } --- 33,41 ----- #ifndef NOSAVEONHANGUP hangup(){ + #ifdef CHECKPOINTS + (void) dosave0(1,0); + #else (void) dosave0(1); #endif exit(1); *************** *** 30,35 #ifndef NOSAVEONHANGUP hangup(){ (void) dosave0(1); exit(1); } #endif --- 37,43 ----- (void) dosave0(1,0); #else (void) dosave0(1); + #endif exit(1); } #endif *************** *** 35,40 #endif /* returns 1 if save successful */ dosave0(hu) int hu; { register fd, ofd; int tmp; /* not register ! */ --- 43,51 ----- #endif /* returns 1 if save successful */ + #ifdef CHECKPOINTS + dosave0(hu,checkpoint) int hu,checkpoint; { + #else dosave0(hu) int hu; { #endif register fd, ofd; *************** *** 36,41 /* returns 1 if save successful */ dosave0(hu) int hu; { register fd, ofd; int tmp; /* not register ! */ #ifdef DGK --- 47,53 ----- dosave0(hu,checkpoint) int hu,checkpoint; { #else dosave0(hu) int hu; { + #endif register fd, ofd; int tmp; /* not register ! */ #ifdef DGK *************** *** 149,154 #else savelev(fd,tmp); /* actual level */ #endif (void) unlink(lock); } (void) close(fd); --- 161,169 ----- #else savelev(fd,tmp); /* actual level */ #endif + #ifdef CHECKPOINTS + if (!checkpoint) + #endif (void) unlink(lock); } (void) close(fd); *************** *** 153,158 } (void) close(fd); glo(dlevel); (void) unlink(lock); /* get rid of current level --jgm */ glo(0); (void) unlink(lock); --- 168,176 ----- } (void) close(fd); glo(dlevel); + #ifdef CHECKPOINTS + if (!checkpoint) + #endif (void) unlink(lock); /* get rid of current level --jgm */ glo(0); #ifdef CHECKPOINTS *************** *** 155,160 glo(dlevel); (void) unlink(lock); /* get rid of current level --jgm */ glo(0); (void) unlink(lock); return(1); } --- 173,181 ----- #endif (void) unlink(lock); /* get rid of current level --jgm */ glo(0); + #ifdef CHECKPOINTS + if (!checkpoint) + #endif (void) unlink(lock); return(1); } *************** *** 278,283 (void) lseek(fd, 0L, 0); getlev(fd, 0, 0); (void) close(fd); if(Punished) { for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp->olet == CHAIN_SYM) goto chainfnd; --- 299,307 ----- (void) lseek(fd, 0L, 0); getlev(fd, 0, 0); (void) close(fd); + #ifndef CHECKPOINTS + (void) unlink(SAVEF); + #endif if(Punished) { for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp->olet == CHAIN_SYM) goto chainfnd; *** unixmain.c.orig Wed Aug 24 21:48:40 1988 --- unixmain.c Wed Aug 24 23:01:47 1988 *************** *** 10,15 #include <stdio.h> #include <signal.h> #include "hack.h" #ifdef QUEST --- 10,18 ----- #include <stdio.h> #include <signal.h> #include "hack.h" + #ifdef CHECKPOINTS + #include <sys/wait.h> + #endif #ifdef QUEST *************** *** 47,52 #ifdef CHDIR register char *dir; #endif hname = argv[0]; hackpid = getpid(); --- 48,56 ----- #ifdef CHDIR register char *dir; #endif + #ifdef CHECKPOINTS + xchar oldlevel; + #endif hname = argv[0]; hackpid = getpid(); *************** *** 309,314 initrack(); for(;;) { if(flags.move) { /* actual time passed */ --- 313,321 ----- initrack(); + #ifdef CHECKPOINTS + oldlevel = dlevel; + #endif for(;;) { if(flags.move) { /* actual time passed */ *************** *** 472,477 } if(multi && multi%7 == 0) (void) fflush(stdout); } } --- 479,509 ----- } if(multi && multi%7 == 0) (void) fflush(stdout); + + #ifdef CHECKPOINTS + if (oldlevel != dlevel){ + union wait status; + /* have to fork as save code is very destructive! */ + switch (fork ()){ + case -1: + pline ("Warning: game backup failed."); + more (); + break; + case 0: + if (dosave0(1,1)) + _exit (0); + _exit (1); + default: + if (wait (&status) != -1) + if (status.w_termsig != 0 || status.w_retcode != 0){ + pline ("Warning: game backup failed."); + more (); + } + break; + } + oldlevel = dlevel; + } + #endif } } ------------------------------------------------------------------------