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