Mercurial > hg > early-roguelike
comparison rogue5/save.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
| author | elwin |
|---|---|
| date | Mon, 24 May 2010 20:10:59 +0000 |
| parents | |
| children | 655c317b6237 |
comparison
equal
deleted
inserted
replaced
| 32:2dcd75e6a736 | 33:f502bf60e6e4 |
|---|---|
| 1 /* | |
| 2 * save and restore routines | |
| 3 * | |
| 4 * @(#)save.c 4.33 (Berkeley) 06/01/83 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman | |
| 8 * All rights reserved. | |
| 9 * | |
| 10 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 11 */ | |
| 12 | |
| 13 #include <stdlib.h> | |
| 14 #include <sys/types.h> | |
| 15 #include <sys/stat.h> | |
| 16 #include <errno.h> | |
| 17 #include <signal.h> | |
| 18 #include <string.h> | |
| 19 #include <curses.h> | |
| 20 #include "rogue.h" | |
| 21 #include "score.h" | |
| 22 | |
| 23 /* | |
| 24 * save_game: | |
| 25 * Implement the "save game" command | |
| 26 */ | |
| 27 | |
| 28 void | |
| 29 save_game(void) | |
| 30 { | |
| 31 FILE *savef; | |
| 32 int c; | |
| 33 char buf[MAXSTR]; | |
| 34 struct stat sbuf; | |
| 35 /* | |
| 36 * get file name | |
| 37 */ | |
| 38 mpos = 0; | |
| 39 over: | |
| 40 if (file_name[0] != '\0') | |
| 41 { | |
| 42 for (;;) | |
| 43 { | |
| 44 msg("save file (%s)? ", file_name); | |
| 45 c = readchar(); | |
| 46 mpos = 0; | |
| 47 if (c == ESCAPE) | |
| 48 { | |
| 49 msg(""); | |
| 50 return; | |
| 51 } | |
| 52 else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y') | |
| 53 break; | |
| 54 else | |
| 55 msg("please answer Y or N"); | |
| 56 } | |
| 57 if (c == 'y' || c == 'Y') | |
| 58 { | |
| 59 addstr("Yes\n"); | |
| 60 refresh(); | |
| 61 strcpy(buf, file_name); | |
| 62 goto gotfile; | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 do | |
| 67 { | |
| 68 mpos = 0; | |
| 69 msg("file name: "); | |
| 70 buf[0] = '\0'; | |
| 71 if (get_str(buf, stdscr) == QUIT) | |
| 72 { | |
| 73 quit_it: | |
| 74 msg(""); | |
| 75 return; | |
| 76 } | |
| 77 mpos = 0; | |
| 78 gotfile: | |
| 79 /* | |
| 80 * test to see if the file exists | |
| 81 */ | |
| 82 if (stat(buf, &sbuf) >= 0) | |
| 83 { | |
| 84 for (;;) | |
| 85 { | |
| 86 msg("File exists. Do you wish to overwrite it?"); | |
| 87 mpos = 0; | |
| 88 if ((c = readchar()) == ESCAPE) | |
| 89 goto quit_it; | |
| 90 if (c == 'y' || c == 'Y') | |
| 91 break; | |
| 92 else if (c == 'n' || c == 'N') | |
| 93 goto over; | |
| 94 else | |
| 95 msg("Please answer Y or N"); | |
| 96 } | |
| 97 msg("file name: %s", buf); | |
| 98 md_unlink(file_name); | |
| 99 } | |
| 100 strcpy(file_name, buf); | |
| 101 if ((savef = fopen(file_name, "w")) == NULL) | |
| 102 msg(strerror(errno)); | |
| 103 } while (savef == NULL); | |
| 104 msg(""); | |
| 105 save_file(savef); | |
| 106 /* NOTREACHED */ | |
| 107 } | |
| 108 | |
| 109 /* | |
| 110 * auto_save: | |
| 111 * Automatically save a file. This is used if a HUP signal is | |
| 112 * recieved | |
| 113 */ | |
| 114 | |
| 115 void | |
| 116 auto_save(int sig) | |
| 117 { | |
| 118 FILE *savef; | |
| 119 NOOP(sig); | |
| 120 | |
| 121 md_ignoreallsignals(); | |
| 122 if (file_name[0] != '\0' && ((savef = fopen(file_name, "w")) != NULL || | |
| 123 (md_unlink_open_file(file_name, savef) >= 0 && (savef = fopen(file_name, "w")) != NULL))) | |
| 124 save_file(savef); | |
| 125 exit(0); | |
| 126 } | |
| 127 | |
| 128 /* | |
| 129 * save_file: | |
| 130 * Write the saved game on the file | |
| 131 */ | |
| 132 | |
| 133 void | |
| 134 save_file(FILE *savef) | |
| 135 { | |
| 136 char buf[80]; | |
| 137 mvcur(0, COLS - 1, LINES - 1, 0); | |
| 138 putchar('\n'); | |
| 139 endwin(); | |
| 140 resetltchars(); | |
| 141 md_chmod(file_name, 0400); | |
| 142 encwrite(version, strlen(version)+1, savef); | |
| 143 sprintf(buf,"%d x %d\n", LINES, COLS); | |
| 144 encwrite(buf,80,savef); | |
| 145 rs_save_file(savef); | |
| 146 fflush(savef); | |
| 147 fclose(savef); | |
| 148 exit(0); | |
| 149 } | |
| 150 | |
| 151 /* | |
| 152 * restore: | |
| 153 * Restore a saved game from a file with elaborate checks for file | |
| 154 * integrity from cheaters | |
| 155 */ | |
| 156 int | |
| 157 restore(const char *file) | |
| 158 { | |
| 159 FILE *inf; | |
| 160 int syml; | |
| 161 char buf[MAXSTR]; | |
| 162 struct stat sbuf2; | |
| 163 int lines, cols; | |
| 164 | |
| 165 if (strcmp(file, "-r") == 0) | |
| 166 file = file_name; | |
| 167 | |
| 168 md_tstphold(); | |
| 169 | |
| 170 if ((inf = fopen(file,"r")) == NULL) | |
| 171 { | |
| 172 perror(file); | |
| 173 return FALSE; | |
| 174 } | |
| 175 stat(file, &sbuf2); | |
| 176 syml = is_symlink(file); | |
| 177 | |
| 178 fflush(stdout); | |
| 179 encread(buf, strlen(version) + 1, inf); | |
| 180 if (strcmp(buf, version) != 0) | |
| 181 { | |
| 182 printf("Sorry, saved game is out of date.\n"); | |
| 183 return FALSE; | |
| 184 } | |
| 185 encread(buf,80,inf); | |
| 186 (void) sscanf(buf,"%d x %d\n", &lines, &cols); | |
| 187 | |
| 188 initscr(); /* Start up cursor package */ | |
| 189 keypad(stdscr, 1); | |
| 190 | |
| 191 if (lines > LINES) | |
| 192 { | |
| 193 endwin(); | |
| 194 printf("Sorry, original game was played on a screen with %d lines.\n",lines); | |
| 195 printf("Current screen only has %d lines. Unable to restore game\n",LINES); | |
| 196 return(FALSE); | |
| 197 } | |
| 198 if (cols > COLS) | |
| 199 { | |
| 200 endwin(); | |
| 201 printf("Sorry, original game was played on a screen with %d columns.\n",cols); | |
| 202 printf("Current screen only has %d columns. Unable to restore game\n",COLS); | |
| 203 return(FALSE); | |
| 204 } | |
| 205 | |
| 206 hw = newwin(LINES, COLS, 0, 0); | |
| 207 setup(); | |
| 208 | |
| 209 rs_restore_file(inf); | |
| 210 /* | |
| 211 * we do not close the file so that we will have a hold of the | |
| 212 * inode for as long as possible | |
| 213 */ | |
| 214 | |
| 215 if ( | |
| 216 #ifdef MASTER | |
| 217 !wizard && | |
| 218 #endif | |
| 219 md_unlink_open_file(file, inf) < 0) | |
| 220 { | |
| 221 printf("Cannot unlink file\n"); | |
| 222 return FALSE; | |
| 223 } | |
| 224 mpos = 0; | |
| 225 /* printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */ | |
| 226 /* | |
| 227 printw("%s: %s", file, ctime(&sbuf2.st_mtime)); | |
| 228 */ | |
| 229 clearok(stdscr,TRUE); | |
| 230 /* | |
| 231 * defeat multiple restarting from the same place | |
| 232 */ | |
| 233 #ifdef MASTER | |
| 234 if (!wizard) | |
| 235 #endif | |
| 236 if (sbuf2.st_nlink != 1 || syml) | |
| 237 { | |
| 238 endwin(); | |
| 239 printf("\nCannot restore from a linked file\n"); | |
| 240 return FALSE; | |
| 241 } | |
| 242 | |
| 243 if (pstats.s_hpt <= 0) | |
| 244 { | |
| 245 endwin(); | |
| 246 printf("\n\"He's dead, Jim\"\n"); | |
| 247 return FALSE; | |
| 248 } | |
| 249 | |
| 250 md_tstpresume(); | |
| 251 | |
| 252 strcpy(file_name, file); | |
| 253 clearok(curscr, TRUE); | |
| 254 srand(md_getpid()); | |
| 255 msg("file name: %s", file); | |
| 256 playit(); | |
| 257 /*NOTREACHED*/ | |
| 258 return(0); | |
| 259 } | |
| 260 | |
| 261 static int encerrno = 0; | |
| 262 | |
| 263 int | |
| 264 encerror() | |
| 265 { | |
| 266 return encerrno; | |
| 267 } | |
| 268 | |
| 269 void | |
| 270 encseterr(int err) | |
| 271 { | |
| 272 encerrno = err; | |
| 273 } | |
| 274 | |
| 275 int | |
| 276 encclearerr() | |
| 277 { | |
| 278 int n = encerrno; | |
| 279 | |
| 280 encerrno = 0; | |
| 281 | |
| 282 return(n); | |
| 283 } | |
| 284 | |
| 285 /* | |
| 286 * encwrite: | |
| 287 * Perform an encrypted write | |
| 288 */ | |
| 289 | |
| 290 size_t | |
| 291 encwrite(const char *start, size_t size, FILE *outf) | |
| 292 { | |
| 293 const char *e1, *e2; | |
| 294 char fb; | |
| 295 int temp; | |
| 296 size_t o_size = size; | |
| 297 e1 = encstr; | |
| 298 e2 = statlist; | |
| 299 fb = 0; | |
| 300 | |
| 301 if (encerrno) { | |
| 302 errno = encerrno; | |
| 303 return 0; | |
| 304 } | |
| 305 | |
| 306 while(size) | |
| 307 { | |
| 308 if (putc(*start++ ^ *e1 ^ *e2 ^ fb, outf) == EOF) | |
| 309 { | |
| 310 encerrno = errno; | |
| 311 break; | |
| 312 } | |
| 313 | |
| 314 temp = *e1++; | |
| 315 fb = fb + ((char) (temp * *e2++)); | |
| 316 if (*e1 == '\0') | |
| 317 e1 = encstr; | |
| 318 if (*e2 == '\0') | |
| 319 e2 = statlist; | |
| 320 size--; | |
| 321 } | |
| 322 | |
| 323 return(o_size - size); | |
| 324 } | |
| 325 | |
| 326 /* | |
| 327 * encread: | |
| 328 * Perform an encrypted read | |
| 329 */ | |
| 330 size_t | |
| 331 encread(char *start, size_t size, FILE *inf) | |
| 332 { | |
| 333 const char *e1, *e2; | |
| 334 char fb; | |
| 335 int temp; | |
| 336 size_t read_size; | |
| 337 size_t items; | |
| 338 fb = 0; | |
| 339 | |
| 340 if (encerrno) { | |
| 341 errno = encerrno; | |
| 342 return 0; | |
| 343 } | |
| 344 | |
| 345 items = read_size = fread(start,1,size,inf); | |
| 346 | |
| 347 e1 = encstr; | |
| 348 e2 = statlist; | |
| 349 | |
| 350 while (read_size--) | |
| 351 { | |
| 352 *start++ ^= *e1 ^ *e2 ^ fb; | |
| 353 temp = *e1++; | |
| 354 fb = fb + (char)(temp * *e2++); | |
| 355 if (*e1 == '\0') | |
| 356 e1 = encstr; | |
| 357 if (*e2 == '\0') | |
| 358 e2 = statlist; | |
| 359 } | |
| 360 | |
| 361 if (items != size) | |
| 362 encerrno = errno; | |
| 363 | |
| 364 return(items); | |
| 365 } | |
| 366 | |
| 367 /* | |
| 368 * read_scrore | |
| 369 * Read in the score file | |
| 370 */ | |
| 371 void | |
| 372 rd_score(SCORE *top_ten) | |
| 373 { | |
| 374 char scoreline[100]; | |
| 375 int i; | |
| 376 | |
| 377 if (scoreboard == NULL) | |
| 378 return; | |
| 379 | |
| 380 rewind(scoreboard); | |
| 381 | |
| 382 for(i = 0; i < numscores; i++) | |
| 383 { | |
| 384 encread(top_ten[i].sc_name, MAXSTR, scoreboard); | |
| 385 scoreline[0] = '\0'; | |
| 386 encread(scoreline, 100, scoreboard); | |
| 387 (void) sscanf(scoreline, " %u %d %u %d %d %x \n", | |
| 388 &top_ten[i].sc_uid, &top_ten[i].sc_score, | |
| 389 &top_ten[i].sc_flags, &top_ten[i].sc_monster, | |
| 390 &top_ten[i].sc_level, &top_ten[i].sc_time); | |
| 391 } | |
| 392 | |
| 393 rewind(scoreboard); | |
