1: /* 2: * save.c 3: * 4: * This source herein may be modified and/or distributed by anybody who 5: * so desires, with the following restrictions: 6: * 1.) No portion of this notice shall be removed. 7: * 2.) Credit shall not be taken for the creation of this source. 8: * 3.) This code is not to be traded, sold, or used for personal 9: * gain or profit. 10: * 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)save.c 5.1 (Berkeley) 11/25/87"; 15: #endif /* not lint */ 16: 17: #include <stdio.h> 18: #include "rogue.h" 19: 20: short write_failed = 0; 21: char *save_file = (char *) 0; 22: 23: extern boolean detect_monster; 24: extern short cur_level, max_level; 25: extern char hunger_str[]; 26: extern char login_name[]; 27: extern short party_room; 28: extern short foods; 29: extern boolean is_wood[]; 30: extern short cur_room; 31: extern boolean being_held; 32: extern short bear_trap; 33: extern short halluc; 34: extern short blind; 35: extern short confused; 36: extern short levitate; 37: extern short haste_self; 38: extern boolean see_invisible; 39: extern boolean detect_monster; 40: extern boolean wizard; 41: extern boolean score_only; 42: extern short m_moves; 43: 44: extern boolean msg_cleared; 45: 46: save_game() 47: { 48: char fname[64]; 49: 50: if (!get_input_line("file name?", save_file, fname, "game not saved", 51: 0, 1)) { 52: return; 53: } 54: check_message(); 55: message(fname, 0); 56: save_into_file(fname); 57: } 58: 59: save_into_file(sfile) 60: char *sfile; 61: { 62: FILE *fp; 63: int file_id; 64: char name_buffer[80]; 65: char *hptr; 66: struct rogue_time rt_buf; 67: 68: if (sfile[0] == '~') { 69: if (hptr = md_getenv("HOME")) { 70: (void) strcpy(name_buffer, hptr); 71: (void) strcat(name_buffer, sfile+1); 72: sfile = name_buffer; 73: } 74: } 75: if ( ((fp = fopen(sfile, "w")) == NULL) || 76: ((file_id = md_get_file_id(sfile)) == -1)) { 77: message("problem accessing the save file", 0); 78: return; 79: } 80: md_ignore_signals(); 81: write_failed = 0; 82: (void) xxx(1); 83: r_write(fp, (char *) &detect_monster, sizeof(detect_monster)); 84: r_write(fp, (char *) &cur_level, sizeof(cur_level)); 85: r_write(fp, (char *) &max_level, sizeof(max_level)); 86: write_string(hunger_str, fp); 87: write_string(login_name, fp); 88: r_write(fp, (char *) &party_room, sizeof(party_room)); 89: write_pack(&level_monsters, fp); 90: write_pack(&level_objects, fp); 91: r_write(fp, (char *) &file_id, sizeof(file_id)); 92: rw_dungeon(fp, 1); 93: r_write(fp, (char *) &foods, sizeof(foods)); 94: r_write(fp, (char *) &rogue, sizeof(fighter)); 95: write_pack(&rogue.pack, fp); 96: rw_id(id_potions, fp, POTIONS, 1); 97: rw_id(id_scrolls, fp, SCROLS, 1); 98: rw_id(id_wands, fp, WANDS, 1); 99: rw_id(id_rings, fp, RINGS, 1); 100: r_write(fp, (char *) traps, (MAX_TRAPS * sizeof(trap))); 101: r_write(fp, (char *) is_wood, (WANDS * sizeof(boolean))); 102: r_write(fp, (char *) &cur_room, sizeof(cur_room)); 103: rw_rooms(fp, 1); 104: r_write(fp, (char *) &being_held, sizeof(being_held)); 105: r_write(fp, (char *) &bear_trap, sizeof(bear_trap)); 106: r_write(fp, (char *) &halluc, sizeof(halluc)); 107: r_write(fp, (char *) &blind, sizeof(blind)); 108: r_write(fp, (char *) &confused, sizeof(confused)); 109: r_write(fp, (char *) &levitate, sizeof(levitate)); 110: r_write(fp, (char *) &haste_self, sizeof(haste_self)); 111: r_write(fp, (char *) &see_invisible, sizeof(see_invisible)); 112: r_write(fp, (char *) &detect_monster, sizeof(detect_monster)); 113: r_write(fp, (char *) &wizard, sizeof(wizard)); 114: r_write(fp, (char *) &score_only, sizeof(score_only)); 115: r_write(fp, (char *) &m_moves, sizeof(m_moves)); 116: md_gct(&rt_buf); 117: rt_buf.second += 10; /* allow for some processing time */ 118: r_write(fp, (char *) &rt_buf, sizeof(rt_buf)); 119: fclose(fp); 120: 121: if (write_failed) { 122: (void) md_df(sfile); /* delete file */ 123: } else { 124: clean_up(""); 125: } 126: } 127: 128: restore(fname) 129: char *fname; 130: { 131: FILE *fp; 132: struct rogue_time saved_time, mod_time; 133: char buf[4]; 134: char tbuf[40]; 135: int new_file_id, saved_file_id; 136: 137: if ( ((new_file_id = md_get_file_id(fname)) == -1) || 138: ((fp = fopen(fname, "r")) == NULL)) { 139: clean_up("cannot open file"); 140: } 141: if (md_link_count(fname) > 1) { 142: clean_up("file has link"); 143: } 144: (void) xxx(1); 145: r_read(fp, (char *) &detect_monster, sizeof(detect_monster)); 146: r_read(fp, (char *) &cur_level, sizeof(cur_level)); 147: r_read(fp, (char *) &max_level, sizeof(max_level)); 148: read_string(hunger_str, fp); 149: 150: (void) strcpy(tbuf, login_name); 151: read_string(login_name, fp); 152: if (strcmp(tbuf, login_name)) { 153: clean_up("you're not the original player"); 154: } 155: 156: r_read(fp, (char *) &party_room, sizeof(party_room)); 157: read_pack(&level_monsters, fp, 0); 158: read_pack(&level_objects, fp, 0); 159: r_read(fp, (char *) &saved_file_id, sizeof(saved_file_id)); 160: if (new_file_id != saved_file_id) { 161: clean_up("sorry, saved game is not in the same file"); 162: } 163: rw_dungeon(fp, 0); 164: r_read(fp, (char *) &foods, sizeof(foods)); 165: r_read(fp, (char *) &rogue, sizeof(fighter)); 166: read_pack(&rogue.pack, fp, 1); 167: rw_id(id_potions, fp, POTIONS, 0); 168: rw_id(id_scrolls, fp, SCROLS, 0); 169: rw_id(id_wands, fp, WANDS, 0); 170: rw_id(id_rings, fp, RINGS, 0); 171: r_read(fp, (char *) traps, (MAX_TRAPS * sizeof(trap))); 172: r_read(fp, (char *) is_wood, (WANDS * sizeof(boolean))); 173: r_read(fp, (char *) &cur_room, sizeof(cur_room)); 174: rw_rooms(fp, 0); 175: r_read(fp, (char *) &being_held, sizeof(being_held)); 176: r_read(fp, (char *) &bear_trap, sizeof(bear_trap)); 177: r_read(fp, (char *) &halluc, sizeof(halluc)); 178: r_read(fp, (char *) &blind, sizeof(blind)); 179: r_read(fp, (char *) &confused, sizeof(confused)); 180: r_read(fp, (char *) &levitate, sizeof(levitate)); 181: r_read(fp, (char *) &haste_self, sizeof(haste_self)); 182: r_read(fp, (char *) &see_invisible, sizeof(see_invisible)); 183: r_read(fp, (char *) &detect_monster, sizeof(detect_monster)); 184: r_read(fp, (char *) &wizard, sizeof(wizard)); 185: r_read(fp, (char *) &score_only, sizeof(score_only)); 186: r_read(fp, (char *) &m_moves, sizeof(m_moves)); 187: r_read(fp, (char *) &saved_time, sizeof(saved_time)); 188: 189: if (fread(buf, sizeof(char), 1, fp) > 0) { 190: clear(); 191: clean_up("extra characters in file"); 192: } 193: 194: md_gfmt(fname, &mod_time); /* get file modification time */ 195: 196: if (has_been_touched(&saved_time, &mod_time)) { 197: clear(); 198: clean_up("sorry, file has been touched"); 199: } 200: if ((!wizard) && !md_df(fname)) { 201: clean_up("cannot delete file"); 202: } 203: msg_cleared = 0; 204: ring_stats(0); 205: fclose(fp); 206: } 207: 208: write_pack(pack, fp) 209: object *pack; 210: FILE *fp; 211: { 212: object t; 213: 214: while (pack = pack->next_object) { 215: r_write(fp, (char *) pack, sizeof(object)); 216: } 217: t.ichar = t.what_is = 0; 218: r_write(fp, (char *) &t, sizeof(object)); 219: } 220: 221: read_pack(pack, fp, is_rogue) 222: object *pack; 223: FILE *fp; 224: boolean is_rogue; 225: { 226: object read_obj, *new_obj; 227: 228: for (;;) { 229: r_read(fp, (char *) &read_obj, sizeof(object)); 230: if (read_obj.ichar == 0) { 231: pack->next_object = (object *) 0; 232: break; 233: } 234: new_obj = alloc_object(); 235: *new_obj = read_obj; 236: if (is_rogue) { 237: if (new_obj->in_use_flags & BEING_WORN) { 238: do_wear(new_obj); 239: } else if (new_obj->in_use_flags & BEING_WIELDED) { 240: do_wield(new_obj); 241: } else if (new_obj->in_use_flags & (ON_EITHER_HAND)) { 242: do_put_on(new_obj, 243: ((new_obj->in_use_flags & ON_LEFT_HAND) ? 1 : 0)); 244: } 245: } 246: pack->next_object = new_obj; 247: pack = new_obj; 248: } 249: } 250: 251: rw_dungeon(fp, rw) 252: FILE *fp; 253: boolean rw; 254: { 255: short i, j; 256: char buf[DCOLS]; 257: 258: for (i = 0; i < DROWS; i++) { 259: if (rw) { 260: r_write(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0]))); 261: for (j = 0; j < DCOLS; j++) { 262: buf[j] = mvinch(i, j); 263: } 264: r_write(fp, buf, DCOLS); 265: } else { 266: r_read(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0]))); 267: r_read(fp, buf, DCOLS); 268: for (j = 0; j < DCOLS; j++) { 269: mvaddch(i, j, buf[j]); 270: } 271: } 272: } 273: } 274: 275: rw_id(id_table, fp, n, wr) 276: struct id id_table[]; 277: FILE *fp; 278: int n; 279: boolean wr; 280: { 281: short i; 282: 283: for (i = 0; i < n; i++) { 284: if (wr) { 285: r_write(fp, (char *) &(id_table[i].value), sizeof(short)); 286: r_write(fp, (char *) &(id_table[i].id_status), 287: sizeof(unsigned short)); 288: write_string(id_table[i].title, fp); 289: } else { 290: r_read(fp, (char *) &(id_table[i].value), sizeof(short)); 291: r_read(fp, (char *) &(id_table[i].id_status), 292: sizeof(unsigned short)); 293: read_string(id_table[i].title, fp); 294: } 295: } 296: } 297: 298: write_string(s, fp) 299: char *s; 300: FILE *fp; 301: { 302: short n; 303: 304: n = strlen(s) + 1; 305: xxxx(s, n); 306: r_write(fp, (char *) &n, sizeof(short)); 307: r_write(fp, s, n); 308: } 309: 310: read_string(s, fp) 311: char *s; 312: FILE *fp; 313: { 314: short n; 315: 316: r_read(fp, (char *) &n, sizeof(short)); 317: r_read(fp, s, n); 318: xxxx(s, n); 319: } 320: 321: rw_rooms(fp, rw) 322: FILE *fp; 323: boolean rw; 324: { 325: short i; 326: 327: for (i = 0; i < MAXROOMS; i++) { 328: rw ? r_write(fp, (char *) (rooms + i), sizeof(room)) : 329: r_read(fp, (char *) (rooms + i), sizeof(room)); 330: } 331: } 332: 333: r_read(fp, buf, n) 334: FILE *fp; 335: char *buf; 336: int n; 337: { 338: if (fread(buf, sizeof(char), n, fp) != n) { 339: clean_up("read() failed, don't know why"); 340: } 341: } 342: 343: r_write(fp, buf, n) 344: FILE *fp; 345: char *buf; 346: int n; 347: { 348: if (!write_failed) { 349: if (fwrite(buf, sizeof(char), n, fp) != n) { 350: message("write() failed, don't know why", 0); 351: sound_bell(); 352: write_failed = 1; 353: } 354: } 355: } 356: 357: boolean 358: has_been_touched(saved_time, mod_time) 359: struct rogue_time *saved_time, *mod_time; 360: { 361: if (saved_time->year < mod_time->year) { 362: return(1); 363: } else if (saved_time->year > mod_time->year) { 364: return(0); 365: } 366: if (saved_time->month < mod_time->month) { 367: return(1); 368: } else if (saved_time->month > mod_time->month) { 369: return(0); 370: } 371: if (saved_time->day < mod_time->day) { 372: return(1); 373: } else if (saved_time->day > mod_time->day) { 374: return(0); 375: } 376: if (saved_time->hour < mod_time->hour) { 377: return(1); 378: } else if (saved_time->hour > mod_time->hour) { 379: return(0); 380: } 381: if (saved_time->minute < mod_time->minute) { 382: return(1); 383: } else if (saved_time->minute > mod_time->minute) { 384: return(0); 385: } 386: if (saved_time->second < mod_time->second) { 387: return(1); 388: } 389: return(0); 390: }