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