/* returns 1 if save successful */ static int dosave0(int hu) { int fd, ofd; int tmp; /* not ! */ (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGINT, SIG_IGN); if ((fd = creat(SAVEF, FMASK)) < 0) { if (!hu) pline("Cannot open save file. (Continue or Quit)"); (void) unlink(SAVEF); /* ab@unido */ return (0); } if (flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ u.uluck--; /* and unido!ab */ savelev(fd, dlevel); saveobjchn(fd, invent); saveobjchn(fd, fcobj); savemonchn(fd, fallen_down); tmp = getuid(); bwrite(fd, &tmp, sizeof tmp); bwrite(fd, &flags, sizeof(struct flag)); bwrite(fd, &dlevel, sizeof dlevel); bwrite(fd, &maxdlevel, sizeof maxdlevel); bwrite(fd, &moves, sizeof moves); bwrite(fd, &u, sizeof(struct you)); if (u.ustuck) bwrite(fd, &(u.ustuck->m_id), sizeof u.ustuck->m_id); bwrite(fd, pl_character, sizeof pl_character); bwrite(fd, genocided, sizeof genocided); bwrite(fd, fut_geno, sizeof fut_geno); savenames(fd); for (tmp = 1; tmp <= maxdlevel; tmp++) { if (tmp == dlevel || !level_exists[tmp]) continue; glo(tmp); if ((ofd = open(lock, O_RDONLY)) < 0) { if (!hu) pline("Error while saving: cannot read %s.", lock); (void) close(fd); (void) unlink(SAVEF); if (!hu) done("tricked"); return (0); } getlev(ofd, hackpid, tmp); (void) close(ofd); bwrite(fd, &tmp, sizeof tmp); /* level number */ savelev(fd, tmp); /* actual level */ (void) unlink(lock); } (void) close(fd); glo(dlevel); (void) unlink(lock); /* get rid of current level --jgm */ glo(0); (void) unlink(lock); return (1); }
// returns 1 if save successful bool dosave0 (bool failok) { // Create the saved game directory first, if absent const char* homedir = getenv ("HOME"); if (!homedir) return false; char savefile [PATH_MAX]; snprintf (ArrayBlock(savefile), _PATH_SAVED_GAMES, homedir); if (0 != access (savefile, R_OK)) mkpath (savefile, S_IRWXU); snprintf (ArrayBlock(savefile), HACK_SAVEFILE, homedir); int fd = creat (savefile, S_IRUSR| S_IWUSR); if (fd < 0) { if (failok) pline("Cannot save game: %s (Continue or Quit)", strerror(errno)); return false; } bwrite (fd, &_u, sizeof(struct you)); saveobjchn (fd, invent); saveobjchn (fd, fcobj); savemonchn (fd, fallen_down); bwrite (fd, &_wflags, sizeof(struct worldflag)); bwrite (fd, pl_character, sizeof pl_character); savenames (fd); savegenocided (fd); for (unsigned i = 0; i < _u.maxdlevel; ++i) savelev (fd, &_levels[i]); close (fd); return true; }
void savegame(struct memfile *mf) { int count = 0; xchar ltmp; store_version(mf); /* Place flags, player info & moves at the beginning of the save. * This makes it possible to read them in nh_get_savegame_status without * parsing all the dungeon and level data */ save_flags(mf); save_you(mf, &u); mwrite32(mf, moves); save_mon(mf, &youmonst); /* store dungeon layout */ save_dungeon(mf); savelevchn(mf); /* store levels */ for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) if (levels[ltmp]) count++; mwrite32(mf, count); for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) { if (!levels[ltmp]) continue; mwrite8(mf, ltmp); /* level number*/ savelev(mf, ltmp); /* actual level*/ } savegamestate(mf); }
/* save bones and possessions of a deceased adventurer */ void savebones() { int fd; struct obj *otmp; struct trap *ttmp; struct monst *mtmp; if(dlevel <= 0 || dlevel > MAXLEVEL) return; if(!rn2(1 + dlevel/2)) return; /* not so many ghosts on low levels */ bones[6] = '0' + (dlevel/10); bones[7] = '0' + (dlevel%10); if((fd = open(bones, O_RDONLY)) >= 0){ (void) close(fd); return; } /* drop everything; the corpse's possessions are usually cursed */ otmp = invent; while(otmp){ otmp->ox = u.ux; otmp->oy = u.uy; otmp->age = 0; /* very long ago */ otmp->owornmask = 0; if(rn2(5)) otmp->cursed = 1; if(!otmp->nobj){ otmp->nobj = fobj; fobj = invent; invent = 0; /* superfluous */ break; } otmp = otmp->nobj; } if(!(mtmp = makemon(PM_GHOST, u.ux, u.uy))) return; mtmp->mx = u.ux; mtmp->my = u.uy; mtmp->msleep = 1; (void) strlcpy((char *) mtmp->mextra, plname, mtmp->mxlth); mkgold(somegold() + d(dlevel,30), u.ux, u.uy); for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ mtmp->m_id = 0; if(mtmp->mtame) { mtmp->mtame = 0; mtmp->mpeaceful = 0; } mtmp->mlstmv = 0; if(mtmp->mdispl) unpmon(mtmp); } for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) ttmp->tseen = 0; for(otmp = fobj; otmp; otmp = otmp->nobj) { otmp->o_id = 0; /* otmp->o_cnt_id = 0; - superfluous */ otmp->onamelth = 0; otmp->known = 0; otmp->invlet = 0; if(otmp->olet == AMULET_SYM && !otmp->spe) { otmp->spe = -1; /* no longer the actual amulet */ otmp->cursed = 1; /* flag as gotten from a ghost */ } } if((fd = open(bones, O_CREAT | O_TRUNC | O_WRONLY, FMASK)) < 0) return; savelev(fd,dlevel); (void) close(fd); }
int dosave() { #ifdef KEEP_SAVE /*WAC for reloading*/ register int fd; #endif clear_nhwindow(WIN_MESSAGE); if(yn("Really save?") == 'n') { clear_nhwindow(WIN_MESSAGE); if(multi > 0) nomul(0); } else { clear_nhwindow(WIN_MESSAGE); pline("Saving..."); #if defined(UNIX) || defined(VMS) || defined(__EMX__) program_state.done_hup = 0; #endif #ifdef KEEP_SAVE saverestore = FALSE; if (flags.keep_savefile) if(yn("Really quit?") == 'n') saverestore = TRUE; if(dosave0() && !saverestore) { #else if(dosave0()) { #endif program_state.something_worth_saving = 0; u.uhp = -1; /* universal game's over indicator */ /* make sure they see the Saving message */ display_nhwindow(WIN_MESSAGE, TRUE); exit_nhwindows("Be seeing you..."); terminate(EXIT_SUCCESS); } /*WAC redraw later else (void)doredraw();*/ } #ifdef KEEP_SAVE if (saverestore) { /*WAC pulled this from pcmain.c - restore game from the file just saved*/ fd = create_levelfile(0); if (fd < 0) { raw_print("Cannot create lock file"); } else { hackpid = 1; write(fd, (genericptr_t) &hackpid, sizeof(hackpid)); close(fd); } #ifdef MFLOPPY level_info[0].where = ACTIVE; #endif fd = restore_saved_game(); if (fd >= 0) dorecover(fd); check_special_room(FALSE); flags.move = 0; /*WAC correct these after restore*/ if(flags.moonphase == FULL_MOON) change_luck(1); if(flags.friday13) change_luck(-1); if(iflags.window_inited) clear_nhwindow(WIN_MESSAGE); } saverestore = FALSE; #endif (void)doredraw(); return 0; } #if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32) /*ARGSUSED*/ void hangup(sig_unused) /* called as signal() handler, so sent at least one arg */ int sig_unused; { # ifdef NOSAVEONHANGUP (void) signal(SIGINT, SIG_IGN); clearlocks(); # ifndef VMS terminate(EXIT_FAILURE); # endif # else /* SAVEONHANGUP */ if (!program_state.done_hup++) { if (program_state.something_worth_saving) (void) dosave0(); # ifdef VMS /* don't call exit when already within an exit handler; that would cancel any other pending user-mode handlers */ if (!program_state.exiting) # endif { clearlocks(); terminate(EXIT_FAILURE); } } # endif return; } #endif /* returns 1 if save successful */ int dosave0() { const char *fq_save; register int fd, ofd; xchar ltmp; d_level uz_save; char whynot[BUFSZ]; if (!SAVEF[0]) return 0; fq_save = fqname(SAVEF, SAVEPREFIX, 1); /* level files take 0 */ #if defined(UNIX) || defined(VMS) (void) signal(SIGHUP, SIG_IGN); #endif #ifndef NO_SIGNAL (void) signal(SIGINT, SIG_IGN); #endif #if defined(MICRO) && defined(MFLOPPY) if (!saveDiskPrompt(0)) return 0; #endif HUP if (iflags.window_inited) { uncompress_area(fq_save, SAVEF); fd = open_savefile(); if (fd > 0) { (void) close(fd); clear_nhwindow(WIN_MESSAGE); There("seems to be an old save file."); if (yn("Overwrite the old file?") == 'n') { compress_area(fq_save, SAVEF); #ifdef KEEP_SAVE /*WAC don't restore if you didn't save*/ saverestore = FALSE; #endif return 0; } } } HUP mark_synch(); /* flush any buffered screen output */ fd = create_savefile(); if(fd < 0) { HUP pline("Cannot open save file."); (void) delete_savefile(); /* ab@unido */ return(0); } vision_recalc(2); /* shut down vision to prevent problems in the event of an impossible() call */ /* undo date-dependent luck adjustments made at startup time */ if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ change_luck(-1); /* and unido!ab */ if(flags.friday13) change_luck(1); if(iflags.window_inited) HUP clear_nhwindow(WIN_MESSAGE); #if defined(MICRO) && defined(TTY_GRAPHICS) if (!strncmpi("tty", windowprocs.name, 3)) { dotcnt = 0; dotrow = 2; curs(WIN_MAP, 1, 1); putstr(WIN_MAP, 0, "Saving:"); } #endif #ifdef MFLOPPY /* make sure there is enough disk space */ if (iflags.checkspace) { long fds, needed; savelev(fd, ledger_no(&u.uz), COUNT_SAVE); savegamestate(fd, COUNT_SAVE); needed = bytes_counted; for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where) needed += level_info[ltmp].size + (sizeof ltmp); fds = freediskspace(fq_save); if (needed > fds) { HUP { There("is insufficient space on SAVE disk."); pline("Require %ld bytes but only have %ld.", needed, fds); } flushout(); (void) close(fd); (void) delete_savefile(); return 0; } co_false(); }
void goto_level(int newlevel, boolean at_stairs) { int fd; boolean up = (newlevel < dlevel); if(newlevel <= 0) done("escaped"); /* in fact < 0 is impossible */ if(newlevel > MAXLEVEL) newlevel = MAXLEVEL; /* strange ... */ if(newlevel == dlevel) return; /* this can happen */ glo(dlevel); fd = creat(lock, FMASK); if(fd < 0) { /* * This is not quite impossible: e.g., we may have * exceeded our quota. If that is the case then we * cannot leave this level, and cannot save either. * Another possibility is that the directory was not * writable. */ pline("A mysterious force prevents you from going %s.", up ? "up" : "down"); return; } if(Punished) unplacebc(); u.utrap = 0; /* needed in level_tele */ u.ustuck = 0; /* idem */ keepdogs(); seeoff(1); if(u.uswallow) /* idem */ u.uswldtim = u.uswallow = 0; flags.nscrinh = 1; u.ux = FAR; /* hack */ (void) inshop(); /* probably was a trapdoor */ savelev(fd,dlevel); (void) close(fd); dlevel = newlevel; if(maxdlevel < dlevel) maxdlevel = dlevel; glo(dlevel); if(!level_exists[(int)dlevel]) mklev(); else { extern int hackpid; if((fd = open(lock, O_RDONLY)) < 0) { pline("Cannot open %s .", lock); pline("Probably someone removed it."); done("tricked"); } getlev(fd, hackpid, dlevel); (void) close(fd); } if(at_stairs) { if(up) { u.ux = xdnstair; u.uy = ydnstair; if(!u.ux) { /* entering a maze from below? */ u.ux = xupstair; /* this will confuse the player! */ u.uy = yupstair; } if(Punished && !Levitation){ pline("With great effort you climb the stairs."); placebc(1); } } else { u.ux = xupstair; u.uy = yupstair; if(inv_weight() + 5 > 0 || Punished){ pline("You fall down the stairs."); /* %% */ losehp(rnd(3), "fall"); if(Punished) { if(uwep != uball && rn2(3)){ pline("... and are hit by the iron ball."); losehp(rnd(20), "iron ball"); } placebc(1); } selftouch("Falling, you"); } } { struct monst *mtmp = m_at(u.ux, u.uy); if(mtmp) mnexto(mtmp); } } else { /* trapdoor or level_tele */ do { u.ux = rnd(COLNO-1); u.uy = rn2(ROWNO); } while(levl[(int)u.ux][(int)u.uy].typ != ROOM || m_at(u.ux,u.uy)); if(Punished){ if(uwep != uball && !up /* %% */ && rn2(5)){ pline("The iron ball falls on your head."); losehp(rnd(25), "iron ball"); } placebc(1); } selftouch("Falling, you"); } (void) inshop(); initrack(); losedogs(); { struct monst *mtmp; if ((mtmp = m_at(u.ux, u.uy))) mnexto(mtmp); /* riv05!a3 */ } flags.nscrinh = 0; setsee(); seeobjs(); /* make old cadavers disappear - riv05!a3 */ docrt(); pickup(1); read_engr_at(u.ux,u.uy); }
/* returns 1 if save successful */ int dosave0(void) { const char *fq_save; register int fd, ofd; xchar ltmp; d_level uz_save; char whynot[BUFSZ]; #ifdef WHEREIS_FILE delete_whereis(); #endif if (!SAVEF[0]) return 0; fq_save = fqname(SAVEF, SAVEPREFIX, 1); /* level files take 0 */ #if defined(UNIX) || defined(VMS) (void) signal(SIGHUP, SIG_IGN); #endif #ifndef NO_SIGNAL (void) signal(SIGINT, SIG_IGN); #endif #if defined(MICRO) && defined(MFLOPPY) if (!saveDiskPrompt(0)) return 0; #endif HUP if (iflags.window_inited) { uncompress_area(fq_save, SAVEF); fd = open_savefile(); if (fd > 0) { (void) close(fd); clear_nhwindow(WIN_MESSAGE); There("seems to be an old save file."); if (yn("Overwrite the old file?") == 'n') { compress_area(fq_save, SAVEF); return 0; } } } HUP mark_synch(); /* flush any buffered screen output */ fd = create_savefile(); if(fd < 0) { HUP pline("Cannot open save file."); (void) delete_savefile(); /* ab@unido */ return(0); } vision_recalc(2); /* shut down vision to prevent problems in the event of an impossible() call */ /* undo date-dependent luck adjustments made at startup time */ if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ change_luck(-1); /* and unido!ab */ if(flags.friday13) change_luck(1); if(iflags.window_inited) HUP clear_nhwindow(WIN_MESSAGE); #ifdef MICRO dotcnt = 0; dotrow = 2; curs(WIN_MAP, 1, 1); if (strncmpi("X11", windowprocs.name, 3)) putstr(WIN_MAP, 0, "Saving:"); #endif #ifdef MFLOPPY /* make sure there is enough disk space */ if (iflags.checkspace) { long fds, needed; savelev(fd, ledger_no(&u.uz), COUNT_SAVE); savegamestate(fd, COUNT_SAVE); needed = bytes_counted; for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where) needed += level_info[ltmp].size + (sizeof ltmp); fds = freediskspace(fq_save); if (needed > fds) { HUP { There("is insufficient space on SAVE disk."); pline("Require %ld bytes but only have %ld.", needed, fds); } flushout(); (void) close(fd); (void) delete_savefile(); return 0; }
int dorecover(int fd) { int nfd; int tmp; /* not a ! */ unsigned mid; /* idem */ struct obj *otmp; restoring = TRUE; getlev(fd, 0, 0); invent = restobjchn(fd); for (otmp = invent; otmp; otmp = otmp->nobj) if (otmp->owornmask) setworn(otmp, otmp->owornmask); fcobj = restobjchn(fd); fallen_down = restmonchn(fd); mread(fd, &tmp, sizeof tmp); if (tmp != (int) getuid()) { /* strange ... */ (void) close(fd); (void) unlink(SAVEF); puts("Saved game was not yours."); restoring = FALSE; return (0); } mread(fd, &flags, sizeof(struct flag)); mread(fd, &dlevel, sizeof dlevel); mread(fd, &maxdlevel, sizeof maxdlevel); mread(fd, &moves, sizeof moves); mread(fd, &u, sizeof(struct you)); if (u.ustuck) mread(fd, &mid, sizeof mid); mread(fd, pl_character, sizeof pl_character); mread(fd, genocided, sizeof genocided); mread(fd, fut_geno, sizeof fut_geno); restnames(fd); while (1) { if (read(fd, &tmp, sizeof tmp) != sizeof tmp) break; getlev(fd, 0, tmp); glo(tmp); if ((nfd = creat(lock, FMASK)) < 0) panic("Cannot open temp file %s!\n", lock); savelev(nfd, tmp); (void) close(nfd); } (void) lseek(fd, (off_t) 0, SEEK_SET); getlev(fd, 0, 0); (void) close(fd); (void) unlink(SAVEF); if (Punished) { for (otmp = fobj; otmp; otmp = otmp->nobj) if (otmp->olet == CHAIN_SYM) goto chainfnd; panic("Cannot find the iron chain?"); chainfnd: uchain = otmp; if (!uball) { for (otmp = fobj; otmp; otmp = otmp->nobj) if (otmp->olet == BALL_SYM && otmp->spe) goto ballfnd; panic("Cannot find the iron ball?"); ballfnd: uball = otmp; } } if (u.ustuck) { struct monst *mtmp; for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) if (mtmp->m_id == mid) goto monfnd; panic("Cannot find the monster ustuck."); monfnd: u.ustuck = mtmp; } #ifndef QUEST setsee(); /* only to recompute seelx etc. - these * weren't saved */ #endif /* QUEST */ docrt(); restoring = FALSE; return (1); }