save.c (8744B)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* 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 9 extern char nul[], pl_character[PL_CSIZ], SAVEF[]; 10 extern long lseek(); 11 extern struct obj *restobjchn(); 12 extern struct monst *restmonchn(); 13 14 dosave(){ 15 if(dosave0(0)) { 16 clear_screen(); 17 settty("Be seeing you ...\n"); 18 exit(0); 19 } 20 } 21 22 /* returns 1 if save successful */ 23 dosave0(hu) int hu; { 24 register fd, ofd; 25 int tmp; /* not register ! */ 26 #ifdef DGK 27 long fds, needed; 28 int mode; 29 extern long bytes_counted; 30 extern int saveprompt; 31 #endif 32 33 (void) signal(SIGINT, SIG_IGN); 34 #ifdef DGK 35 if (!saveDiskPrompt(0)) 36 return 0; 37 fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK); 38 #else 39 fd = creat(SAVEF, FMASK); 40 #endif 41 if(fd < 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 #ifdef DGK 49 home(); 50 cl_end(); 51 msmsg("Saving: "); 52 #endif 53 #ifdef DGK 54 mode = COUNT; 55 again: 56 savelev(fd, dlevel, mode); 57 /* count_only will be set properly by savelev */ 58 #else 59 savelev(fd,dlevel); 60 #endif 61 saveobjchn(fd, invent); 62 saveobjchn(fd, fcobj); 63 savemonchn(fd, fallen_down); 64 tmp = getuid(); 65 bwrite(fd, (char *) &tmp, sizeof tmp); 66 bwrite(fd, (char *) &flags, sizeof(struct flag)); 67 bwrite(fd, (char *) &dlevel, sizeof dlevel); 68 bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel); 69 bwrite(fd, (char *) &moves, sizeof moves); 70 bwrite(fd, (char *) &u, sizeof(struct you)); 71 if(u.ustuck) 72 bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 73 bwrite(fd, (char *) pl_character, sizeof pl_character); 74 bwrite(fd, (char *) genocided, sizeof genocided); 75 bwrite(fd, (char *) fut_geno, sizeof fut_geno); 76 savenames(fd); 77 #ifdef DGK 78 if (mode == COUNT) { 79 /* make sure there is enough disk space */ 80 needed = bytes_counted; 81 for (tmp = 1; tmp <= maxdlevel; tmp++) 82 if (tmp != dlevel && fileinfo[tmp].where) 83 needed += fileinfo[tmp].size + (sizeof tmp); 84 fds = freediskspace(SAVEF); 85 if (needed > fds) { 86 pline("There is insufficient space on SAVE disk."); 87 pline("Require %ld bytes but only have %ld.", needed, 88 fds); 89 flushout(); 90 (void) close(fd); 91 (void) unlink(SAVEF); 92 saveprompt = 0; /* allow a disk change */ 93 return 0; 94 } 95 mode = WRITE; 96 goto again; 97 } 98 #endif 99 for(tmp = 1; tmp <= maxdlevel; tmp++) { 100 extern int hackpid; 101 #ifdef DGK 102 if (tmp == dlevel || !fileinfo[tmp].where) continue; 103 if (fileinfo[tmp].where != ACTIVE) 104 swapin_file(tmp); 105 #else 106 extern boolean level_exists[]; 107 if(tmp == dlevel || !level_exists[tmp]) continue; 108 #endif 109 glo(tmp); 110 #ifdef DGK 111 msmsg("."); 112 #endif 113 if((ofd = open(lock, 0)) < 0) { 114 if(!hu) pline("Error while saving: cannot read %s.", lock); 115 (void) close(fd); 116 (void) unlink(SAVEF); 117 if(!hu) done("tricked"); 118 return(0); 119 } 120 getlev(ofd, hackpid, tmp); 121 (void) close(ofd); 122 bwrite(fd, (char *) &tmp, sizeof tmp); /* level number */ 123 #ifdef DGK 124 savelev(fd,tmp,WRITE); /* actual level */ 125 #else 126 savelev(fd,tmp); /* actual level */ 127 #endif 128 (void) unlink(lock); 129 } 130 (void) close(fd); 131 glo(dlevel); 132 (void) unlink(lock); /* get rid of current level --jgm */ 133 glo(0); 134 (void) unlink(lock); 135 return(1); 136 } 137 138 dorecover(fd) 139 register fd; 140 { 141 register nfd; 142 int tmp; /* not a register ! */ 143 unsigned mid; /* idem */ 144 struct obj *otmp; 145 extern boolean restoring; 146 #ifdef DGK 147 struct flag oldflags; 148 149 oldflags = flags; /* Save flags set in the config file */ 150 #endif 151 restoring = TRUE; 152 getlev(fd, 0, 0); 153 invent = restobjchn(fd); 154 for(otmp = invent; otmp; otmp = otmp->nobj) 155 if(otmp->owornmask) 156 setworn(otmp, otmp->owornmask); 157 fcobj = restobjchn(fd); 158 fallen_down = restmonchn(fd); 159 mread(fd, (char *) &tmp, sizeof tmp); 160 if(tmp != getuid()) { /* strange ... */ 161 (void) close(fd); 162 (void) unlink(SAVEF); 163 puts("Saved game was not yours."); 164 restoring = FALSE; 165 return(0); 166 } 167 mread(fd, (char *) &flags, sizeof(struct flag)); 168 #ifdef DGK 169 /* Some config file OPTIONS take precedence over those in save file. 170 */ 171 flags.rawio = oldflags.rawio; 172 flags.DECRainbow = oldflags.DECRainbow; 173 flags.IBMBIOS = oldflags.IBMBIOS; 174 #endif 175 mread(fd, (char *) &dlevel, sizeof dlevel); 176 mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 177 mread(fd, (char *) &moves, sizeof moves); 178 mread(fd, (char *) &u, sizeof(struct you)); 179 if(u.ustuck) 180 mread(fd, (char *) &mid, sizeof mid); 181 mread(fd, (char *) pl_character, sizeof pl_character); 182 mread(fd, (char *) genocided, sizeof genocided); 183 mread(fd, (char *) fut_geno, sizeof fut_geno); 184 restnames(fd); 185 #ifdef DGK 186 msmsg("\n"); 187 cl_end(); 188 msmsg("You got as far as level %d%s.\n", maxdlevel, 189 flags.debug ? " in WIZARD mode" : ""); 190 cl_end(); 191 msmsg("Restoring: "); 192 #endif 193 while(1) { 194 if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 195 break; 196 getlev(fd, 0, tmp); 197 glo(tmp); 198 #ifdef DGK 199 msmsg("."); 200 nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); 201 #else 202 nfd = creat(lock, FMASK); 203 #endif 204 if (nfd < 0) 205 panic("Cannot open level file %s!\n", lock); 206 #ifdef DGK 207 if (!savelev(nfd, tmp, COUNT | WRITE)) { 208 209 /* The savelev can't proceed because the size required 210 * is greater than the available disk space. 211 */ 212 msmsg("\nNot enough space on `%s' to restore your game.\n", 213 levels); 214 215 /* Remove levels and bones that may have been created. 216 */ 217 (void) close(nfd); 218 eraseall(levels, alllevels); 219 eraseall(levels, allbones); 220 221 /* Perhaps the person would like to play without a 222 * RAMdisk. 223 */ 224 if (ramdisk) { 225 /* PlaywoRAMdisk may not return, but if it does 226 * it is certain that ramdisk will be 0. 227 */ 228 playwoRAMdisk(); 229 (void) lseek(fd, 0L, 0); /* Rewind save file */ 230 return dorecover(fd); /* and try again */ 231 } else { 232 msmsg("Be seeing you ...\n"); 233 exit(0); 234 } 235 } 236 #else 237 savelev(nfd,tmp); 238 #endif 239 (void) close(nfd); 240 } 241 (void) lseek(fd, 0L, 0); 242 getlev(fd, 0, 0); 243 (void) close(fd); 244 (void) unlink(SAVEF); 245 if(Punished) { 246 for(otmp = fobj; otmp; otmp = otmp->nobj) 247 if(otmp->olet == CHAIN_SYM) goto chainfnd; 248 panic("Cannot find the iron chain?"); 249 chainfnd: 250 uchain = otmp; 251 if(!uball){ 252 for(otmp = fobj; otmp; otmp = otmp->nobj) 253 if(otmp->olet == BALL_SYM && otmp->spe) 254 goto ballfnd; 255 panic("Cannot find the iron ball?"); 256 ballfnd: 257 uball = otmp; 258 } 259 } 260 if(u.ustuck) { 261 register struct monst *mtmp; 262 263 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 264 if(mtmp->m_id == mid) goto monfnd; 265 panic("Cannot find the monster ustuck."); 266 monfnd: 267 u.ustuck = mtmp; 268 } 269 setsee(); /* only to recompute seelx etc. - these weren't saved */ 270 #ifdef DGK 271 gameDiskPrompt(); 272 #endif 273 docrt(); 274 restoring = FALSE; 275 return(1); 276 } 277 278 struct obj * 279 restobjchn(fd) 280 register fd; 281 { 282 register struct obj *otmp, *otmp2; 283 register struct obj *first = 0; 284 int xl; 285 #ifdef lint 286 /* suppress "used before set" warning from lint */ 287 otmp2 = 0; 288 #endif /* lint /**/ 289 while(1) { 290 mread(fd, (char *) &xl, sizeof(xl)); 291 if(xl == -1) break; 292 otmp = newobj(xl); 293 if(!first) first = otmp; 294 else otmp2->nobj = otmp; 295 mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 296 if(!otmp->o_id) otmp->o_id = flags.ident++; 297 otmp2 = otmp; 298 } 299 if(first && otmp2->nobj){ 300 impossible("Restobjchn: error reading objchn."); 301 otmp2->nobj = 0; 302 } 303 return(first); 304 } 305 306 struct monst * 307 restmonchn(fd) 308 register fd; 309 { 310 register struct monst *mtmp, *mtmp2; 311 register struct monst *first = 0; 312 int xl; 313 int monsindex; 314 extern struct permonst li_dog, dog, la_dog, hell_hound, pm_guard; 315 316 #ifdef lint 317 /* suppress "used before set" warning from lint */ 318 mtmp2 = 0; 319 #endif /* lint /**/ 320 while(1) { 321 mread(fd, (char *) &xl, sizeof(xl)); 322 if(xl == -1) break; 323 mtmp = newmonst(xl); 324 if(!first) first = mtmp; 325 else mtmp2->nmon = mtmp; 326 mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 327 if(!mtmp->m_id) 328 mtmp->m_id = flags.ident++; 329 monsindex = *((int *)&mtmp->data); 330 if (monsindex == INDEX_LITTLEDOG) 331 mtmp->data = &li_dog; 332 else if (monsindex == INDEX_DOG) 333 mtmp->data = &dog; 334 else if (monsindex == INDEX_LARGEDOG) 335 mtmp->data = &la_dog; 336 else if (monsindex == INDEX_HELLHOUND) 337 mtmp->data = &hell_hound; 338 else if (monsindex == INDEX_GUARD) 339 mtmp->data = &pm_guard; 340 else if (monsindex < 0) { 341 msmsg("Monster index %d in restmonchn\n", monsindex); 342 goto next; 343 } else 344 mtmp->data = &mons[monsindex]; 345 if(mtmp->minvent) 346 mtmp->minvent = restobjchn(fd); 347 next: 348 mtmp2 = mtmp; 349 } 350 if(first && mtmp2->nmon){ 351 impossible("Restmonchn: error reading monchn."); 352 mtmp2->nmon = 0; 353 } 354 return(first); 355 }