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