1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* hack.save.c - version 1.0.3 */ 3 /* $FreeBSD: src/games/hack/hack.save.c,v 1.4 1999/11/16 10:26:37 marcel Exp $ */ 4 /* $DragonFly: src/games/hack/hack.save.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */ 5 6 #include "hack.h" 7 8 extern char SAVEF[], nul[]; 9 10 static bool dosave0(int); 11 12 int 13 dosave(void) 14 { 15 if(dosave0(0)) { 16 settty("Be seeing you ...\n"); 17 exit(0); 18 } 19 return(0); 20 } 21 22 #ifndef NOSAVEONHANGUP 23 void 24 hangup(__unused int unused) 25 { 26 dosave0(1); 27 exit(1); 28 } 29 #endif /* NOSAVEONHANGUP */ 30 31 /* returns 1 if save successful */ 32 static bool 33 dosave0(int hu) 34 { 35 int fd, ofd; 36 int tmp; /* not ! */ 37 38 signal(SIGHUP, SIG_IGN); 39 signal(SIGINT, SIG_IGN); 40 if((fd = creat(SAVEF, FMASK)) < 0) { 41 if(!hu) pline("Cannot open save file. (Continue or Quit)"); 42 unlink(SAVEF); /* ab@unido */ 43 return(0); 44 } 45 if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ 46 u.uluck--; /* and unido!ab */ 47 savelev(fd,dlevel); 48 saveobjchn(fd, invent); 49 saveobjchn(fd, fcobj); 50 savemonchn(fd, fallen_down); 51 tmp = getuid(); 52 bwrite(fd, (char *) &tmp, sizeof tmp); 53 bwrite(fd, (char *) &flags, sizeof(struct flag)); 54 bwrite(fd, (char *) &dlevel, sizeof dlevel); 55 bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel); 56 bwrite(fd, (char *) &moves, sizeof moves); 57 bwrite(fd, (char *) &u, sizeof(struct you)); 58 if(u.ustuck) 59 bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 60 bwrite(fd, (char *) pl_character, sizeof pl_character); 61 bwrite(fd, (char *) genocided, sizeof genocided); 62 bwrite(fd, (char *) fut_geno, sizeof fut_geno); 63 savenames(fd); 64 for(tmp = 1; tmp <= maxdlevel; tmp++) { 65 if(tmp == dlevel || !level_exists[tmp]) continue; 66 glo(tmp); 67 if((ofd = open(lock, 0)) < 0) { 68 if(!hu) pline("Error while saving: cannot read %s.", lock); 69 close(fd); 70 unlink(SAVEF); 71 if(!hu) done("tricked"); 72 return(0); 73 } 74 getlev(ofd, hackpid, tmp); 75 close(ofd); 76 bwrite(fd, (char *) &tmp, sizeof tmp); /* level number */ 77 savelev(fd,tmp); /* actual level */ 78 unlink(lock); 79 } 80 close(fd); 81 glo(dlevel); 82 unlink(lock); /* get rid of current level --jgm */ 83 glo(0); 84 unlink(lock); 85 return(1); 86 } 87 88 bool 89 dorecover(int fd) 90 { 91 int nfd; 92 int tmp; /* not a ! */ 93 unsigned mid; /* idem */ 94 struct obj *otmp; 95 96 restoring = TRUE; 97 getlev(fd, 0, 0); 98 invent = restobjchn(fd); 99 for(otmp = invent; otmp; otmp = otmp->nobj) 100 if(otmp->owornmask) 101 setworn(otmp, otmp->owornmask); 102 fcobj = restobjchn(fd); 103 fallen_down = restmonchn(fd); 104 mread(fd, (char *) &tmp, sizeof tmp); 105 if(tmp != (int)getuid()) { /* strange ... */ 106 close(fd); 107 unlink(SAVEF); 108 puts("Saved game was not yours."); 109 restoring = FALSE; 110 return(0); 111 } 112 mread(fd, (char *) &flags, sizeof(struct flag)); 113 mread(fd, (char *) &dlevel, sizeof dlevel); 114 mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 115 mread(fd, (char *) &moves, sizeof moves); 116 mread(fd, (char *) &u, sizeof(struct you)); 117 if(u.ustuck) 118 mread(fd, (char *) &mid, sizeof mid); 119 mread(fd, (char *) pl_character, sizeof pl_character); 120 mread(fd, (char *) genocided, sizeof genocided); 121 mread(fd, (char *) fut_geno, sizeof fut_geno); 122 restnames(fd); 123 while(1) { 124 if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 125 break; 126 getlev(fd, 0, tmp); 127 glo(tmp); 128 if((nfd = creat(lock, FMASK)) < 0) 129 panic("Cannot open temp file %s!\n", lock); 130 savelev(nfd,tmp); 131 close(nfd); 132 } 133 lseek(fd, (off_t)0, 0); 134 getlev(fd, 0, 0); 135 close(fd); 136 unlink(SAVEF); 137 if(Punished) { 138 for(otmp = fobj; otmp; otmp = otmp->nobj) 139 if(otmp->olet == CHAIN_SYM) goto chainfnd; 140 panic("Cannot find the iron chain?"); 141 chainfnd: 142 uchain = otmp; 143 if(!uball){ 144 for(otmp = fobj; otmp; otmp = otmp->nobj) 145 if(otmp->olet == BALL_SYM && otmp->spe) 146 goto ballfnd; 147 panic("Cannot find the iron ball?"); 148 ballfnd: 149 uball = otmp; 150 } 151 } 152 if(u.ustuck) { 153 struct monst *mtmp; 154 155 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 156 if(mtmp->m_id == mid) goto monfnd; 157 panic("Cannot find the monster ustuck."); 158 monfnd: 159 u.ustuck = mtmp; 160 } 161 #ifndef QUEST 162 setsee(); /* only to recompute seelx etc. - these weren't saved */ 163 #endif /* QUEST */ 164 docrt(); 165 restoring = FALSE; 166 return(1); 167 } 168 169 struct obj * 170 restobjchn(int fd) 171 { 172 struct obj *otmp, *otmp2; 173 struct obj *first = 0; 174 int xl; 175 /* suppress "used before set" warning from lint */ 176 otmp2 = 0; 177 while(1) { 178 mread(fd, (char *) &xl, sizeof(xl)); 179 if(xl == -1) break; 180 otmp = newobj(xl); 181 if(!first) first = otmp; 182 else otmp2->nobj = otmp; 183 mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 184 if(!otmp->o_id) otmp->o_id = flags.ident++; 185 otmp2 = otmp; 186 } 187 if(first && otmp2->nobj){ 188 impossible("Restobjchn: error reading objchn."); 189 otmp2->nobj = 0; 190 } 191 return(first); 192 } 193 194 struct monst * 195 restmonchn(int fd) 196 { 197 struct monst *mtmp, *mtmp2; 198 struct monst *first = 0; 199 int xl; 200 201 struct permonst *monbegin; 202 long differ; 203 204 mread(fd, (char *)&monbegin, sizeof(monbegin)); 205 differ = (char *)(&mons[0]) - (char *)(monbegin); 206 207 /* suppress "used before set" warning from lint */ 208 mtmp2 = 0; 209 while(1) { 210 mread(fd, (char *) &xl, sizeof(xl)); 211 if(xl == -1) break; 212 mtmp = newmonst(xl); 213 if(!first) first = mtmp; 214 else mtmp2->nmon = mtmp; 215 mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 216 if(!mtmp->m_id) 217 mtmp->m_id = flags.ident++; 218 mtmp->data = (struct permonst *) 219 ((char *) mtmp->data + differ); 220 if(mtmp->minvent) 221 mtmp->minvent = restobjchn(fd); 222 mtmp2 = mtmp; 223 } 224 if(first && mtmp2->nmon){ 225 impossible("Restmonchn: error reading monchn."); 226 mtmp2->nmon = 0; 227 } 228 return(first); 229 } 230