132689Sbostic /* 2*36704Sbostic * Copyright (c) 1988 The Regents of the University of California. 3*36704Sbostic * All rights reserved. 4*36704Sbostic * 5*36704Sbostic * This code is derived from software contributed to Berkeley by 6*36704Sbostic * Timothy C. Stoehr. 7*36704Sbostic * 8*36704Sbostic * Redistribution and use in source and binary forms are permitted 9*36704Sbostic * provided that the above copyright notice and this paragraph are 10*36704Sbostic * duplicated in all such forms and that any documentation, 11*36704Sbostic * advertising materials, and other materials related to such 12*36704Sbostic * distribution and use acknowledge that the software was developed 13*36704Sbostic * by the University of California, Berkeley. The name of the 14*36704Sbostic * University may not be used to endorse or promote products derived 15*36704Sbostic * from this software without specific prior written permission. 16*36704Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*36704Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*36704Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19*36704Sbostic */ 20*36704Sbostic 21*36704Sbostic #ifndef lint 22*36704Sbostic static char sccsid[] = "@(#)save.c 5.2 (Berkeley) 02/07/89"; 23*36704Sbostic #endif /* not lint */ 24*36704Sbostic 25*36704Sbostic /* 2632689Sbostic * save.c 2732689Sbostic * 2832689Sbostic * This source herein may be modified and/or distributed by anybody who 2932689Sbostic * so desires, with the following restrictions: 3032689Sbostic * 1.) No portion of this notice shall be removed. 3132689Sbostic * 2.) Credit shall not be taken for the creation of this source. 3232689Sbostic * 3.) This code is not to be traded, sold, or used for personal 3332689Sbostic * gain or profit. 3432689Sbostic * 3532689Sbostic */ 3632689Sbostic 3732689Sbostic #include <stdio.h> 3832689Sbostic #include "rogue.h" 3932689Sbostic 4032689Sbostic short write_failed = 0; 4132689Sbostic char *save_file = (char *) 0; 4232689Sbostic 4332689Sbostic extern boolean detect_monster; 4432689Sbostic extern short cur_level, max_level; 4532689Sbostic extern char hunger_str[]; 4632689Sbostic extern char login_name[]; 4732689Sbostic extern short party_room; 4832689Sbostic extern short foods; 4932689Sbostic extern boolean is_wood[]; 5032689Sbostic extern short cur_room; 5132689Sbostic extern boolean being_held; 5232689Sbostic extern short bear_trap; 5332689Sbostic extern short halluc; 5432689Sbostic extern short blind; 5532689Sbostic extern short confused; 5632689Sbostic extern short levitate; 5732689Sbostic extern short haste_self; 5832689Sbostic extern boolean see_invisible; 5932689Sbostic extern boolean detect_monster; 6032689Sbostic extern boolean wizard; 6132689Sbostic extern boolean score_only; 6232689Sbostic extern short m_moves; 6332689Sbostic 6432689Sbostic extern boolean msg_cleared; 6532689Sbostic 6632689Sbostic save_game() 6732689Sbostic { 6832689Sbostic char fname[64]; 6932689Sbostic 7032689Sbostic if (!get_input_line("file name?", save_file, fname, "game not saved", 7132689Sbostic 0, 1)) { 7232689Sbostic return; 7332689Sbostic } 7432689Sbostic check_message(); 7532689Sbostic message(fname, 0); 7632689Sbostic save_into_file(fname); 7732689Sbostic } 7832689Sbostic 7932689Sbostic save_into_file(sfile) 8032689Sbostic char *sfile; 8132689Sbostic { 8232689Sbostic FILE *fp; 8332689Sbostic int file_id; 8432689Sbostic char name_buffer[80]; 8532689Sbostic char *hptr; 8632689Sbostic struct rogue_time rt_buf; 8732689Sbostic 8832689Sbostic if (sfile[0] == '~') { 8932689Sbostic if (hptr = md_getenv("HOME")) { 9032689Sbostic (void) strcpy(name_buffer, hptr); 9132689Sbostic (void) strcat(name_buffer, sfile+1); 9232689Sbostic sfile = name_buffer; 9332689Sbostic } 9432689Sbostic } 9532689Sbostic if ( ((fp = fopen(sfile, "w")) == NULL) || 9632689Sbostic ((file_id = md_get_file_id(sfile)) == -1)) { 9732689Sbostic message("problem accessing the save file", 0); 9832689Sbostic return; 9932689Sbostic } 10032689Sbostic md_ignore_signals(); 10132689Sbostic write_failed = 0; 10232689Sbostic (void) xxx(1); 10332689Sbostic r_write(fp, (char *) &detect_monster, sizeof(detect_monster)); 10432689Sbostic r_write(fp, (char *) &cur_level, sizeof(cur_level)); 10532689Sbostic r_write(fp, (char *) &max_level, sizeof(max_level)); 10632689Sbostic write_string(hunger_str, fp); 10732689Sbostic write_string(login_name, fp); 10832689Sbostic r_write(fp, (char *) &party_room, sizeof(party_room)); 10932689Sbostic write_pack(&level_monsters, fp); 11032689Sbostic write_pack(&level_objects, fp); 11132689Sbostic r_write(fp, (char *) &file_id, sizeof(file_id)); 11232689Sbostic rw_dungeon(fp, 1); 11332689Sbostic r_write(fp, (char *) &foods, sizeof(foods)); 11432689Sbostic r_write(fp, (char *) &rogue, sizeof(fighter)); 11532689Sbostic write_pack(&rogue.pack, fp); 11632689Sbostic rw_id(id_potions, fp, POTIONS, 1); 11732689Sbostic rw_id(id_scrolls, fp, SCROLS, 1); 11832689Sbostic rw_id(id_wands, fp, WANDS, 1); 11932689Sbostic rw_id(id_rings, fp, RINGS, 1); 12032689Sbostic r_write(fp, (char *) traps, (MAX_TRAPS * sizeof(trap))); 12132689Sbostic r_write(fp, (char *) is_wood, (WANDS * sizeof(boolean))); 12232689Sbostic r_write(fp, (char *) &cur_room, sizeof(cur_room)); 12332689Sbostic rw_rooms(fp, 1); 12432689Sbostic r_write(fp, (char *) &being_held, sizeof(being_held)); 12532689Sbostic r_write(fp, (char *) &bear_trap, sizeof(bear_trap)); 12632689Sbostic r_write(fp, (char *) &halluc, sizeof(halluc)); 12732689Sbostic r_write(fp, (char *) &blind, sizeof(blind)); 12832689Sbostic r_write(fp, (char *) &confused, sizeof(confused)); 12932689Sbostic r_write(fp, (char *) &levitate, sizeof(levitate)); 13032689Sbostic r_write(fp, (char *) &haste_self, sizeof(haste_self)); 13132689Sbostic r_write(fp, (char *) &see_invisible, sizeof(see_invisible)); 13232689Sbostic r_write(fp, (char *) &detect_monster, sizeof(detect_monster)); 13332689Sbostic r_write(fp, (char *) &wizard, sizeof(wizard)); 13432689Sbostic r_write(fp, (char *) &score_only, sizeof(score_only)); 13532689Sbostic r_write(fp, (char *) &m_moves, sizeof(m_moves)); 13632689Sbostic md_gct(&rt_buf); 13732689Sbostic rt_buf.second += 10; /* allow for some processing time */ 13832689Sbostic r_write(fp, (char *) &rt_buf, sizeof(rt_buf)); 13932689Sbostic fclose(fp); 14032689Sbostic 14132689Sbostic if (write_failed) { 14232689Sbostic (void) md_df(sfile); /* delete file */ 14332689Sbostic } else { 14432689Sbostic clean_up(""); 14532689Sbostic } 14632689Sbostic } 14732689Sbostic 14832689Sbostic restore(fname) 14932689Sbostic char *fname; 15032689Sbostic { 15132689Sbostic FILE *fp; 15232689Sbostic struct rogue_time saved_time, mod_time; 15332689Sbostic char buf[4]; 15432689Sbostic char tbuf[40]; 15532689Sbostic int new_file_id, saved_file_id; 15632689Sbostic 15732689Sbostic if ( ((new_file_id = md_get_file_id(fname)) == -1) || 15832689Sbostic ((fp = fopen(fname, "r")) == NULL)) { 15932689Sbostic clean_up("cannot open file"); 16032689Sbostic } 16132689Sbostic if (md_link_count(fname) > 1) { 16232689Sbostic clean_up("file has link"); 16332689Sbostic } 16432689Sbostic (void) xxx(1); 16532689Sbostic r_read(fp, (char *) &detect_monster, sizeof(detect_monster)); 16632689Sbostic r_read(fp, (char *) &cur_level, sizeof(cur_level)); 16732689Sbostic r_read(fp, (char *) &max_level, sizeof(max_level)); 16832689Sbostic read_string(hunger_str, fp); 16932689Sbostic 17032689Sbostic (void) strcpy(tbuf, login_name); 17132689Sbostic read_string(login_name, fp); 17232689Sbostic if (strcmp(tbuf, login_name)) { 17332689Sbostic clean_up("you're not the original player"); 17432689Sbostic } 17532689Sbostic 17632689Sbostic r_read(fp, (char *) &party_room, sizeof(party_room)); 17732689Sbostic read_pack(&level_monsters, fp, 0); 17832689Sbostic read_pack(&level_objects, fp, 0); 17932689Sbostic r_read(fp, (char *) &saved_file_id, sizeof(saved_file_id)); 18032689Sbostic if (new_file_id != saved_file_id) { 18132689Sbostic clean_up("sorry, saved game is not in the same file"); 18232689Sbostic } 18332689Sbostic rw_dungeon(fp, 0); 18432689Sbostic r_read(fp, (char *) &foods, sizeof(foods)); 18532689Sbostic r_read(fp, (char *) &rogue, sizeof(fighter)); 18632689Sbostic read_pack(&rogue.pack, fp, 1); 18732689Sbostic rw_id(id_potions, fp, POTIONS, 0); 18832689Sbostic rw_id(id_scrolls, fp, SCROLS, 0); 18932689Sbostic rw_id(id_wands, fp, WANDS, 0); 19032689Sbostic rw_id(id_rings, fp, RINGS, 0); 19132689Sbostic r_read(fp, (char *) traps, (MAX_TRAPS * sizeof(trap))); 19232689Sbostic r_read(fp, (char *) is_wood, (WANDS * sizeof(boolean))); 19332689Sbostic r_read(fp, (char *) &cur_room, sizeof(cur_room)); 19432689Sbostic rw_rooms(fp, 0); 19532689Sbostic r_read(fp, (char *) &being_held, sizeof(being_held)); 19632689Sbostic r_read(fp, (char *) &bear_trap, sizeof(bear_trap)); 19732689Sbostic r_read(fp, (char *) &halluc, sizeof(halluc)); 19832689Sbostic r_read(fp, (char *) &blind, sizeof(blind)); 19932689Sbostic r_read(fp, (char *) &confused, sizeof(confused)); 20032689Sbostic r_read(fp, (char *) &levitate, sizeof(levitate)); 20132689Sbostic r_read(fp, (char *) &haste_self, sizeof(haste_self)); 20232689Sbostic r_read(fp, (char *) &see_invisible, sizeof(see_invisible)); 20332689Sbostic r_read(fp, (char *) &detect_monster, sizeof(detect_monster)); 20432689Sbostic r_read(fp, (char *) &wizard, sizeof(wizard)); 20532689Sbostic r_read(fp, (char *) &score_only, sizeof(score_only)); 20632689Sbostic r_read(fp, (char *) &m_moves, sizeof(m_moves)); 20732689Sbostic r_read(fp, (char *) &saved_time, sizeof(saved_time)); 20832689Sbostic 20932689Sbostic if (fread(buf, sizeof(char), 1, fp) > 0) { 21032689Sbostic clear(); 21132689Sbostic clean_up("extra characters in file"); 21232689Sbostic } 21332689Sbostic 21432689Sbostic md_gfmt(fname, &mod_time); /* get file modification time */ 21532689Sbostic 21632689Sbostic if (has_been_touched(&saved_time, &mod_time)) { 21732689Sbostic clear(); 21832689Sbostic clean_up("sorry, file has been touched"); 21932689Sbostic } 22032689Sbostic if ((!wizard) && !md_df(fname)) { 22132689Sbostic clean_up("cannot delete file"); 22232689Sbostic } 22332689Sbostic msg_cleared = 0; 22432689Sbostic ring_stats(0); 22532689Sbostic fclose(fp); 22632689Sbostic } 22732689Sbostic 22832689Sbostic write_pack(pack, fp) 22932689Sbostic object *pack; 23032689Sbostic FILE *fp; 23132689Sbostic { 23232689Sbostic object t; 23332689Sbostic 23432689Sbostic while (pack = pack->next_object) { 23532689Sbostic r_write(fp, (char *) pack, sizeof(object)); 23632689Sbostic } 23732689Sbostic t.ichar = t.what_is = 0; 23832689Sbostic r_write(fp, (char *) &t, sizeof(object)); 23932689Sbostic } 24032689Sbostic 24132689Sbostic read_pack(pack, fp, is_rogue) 24232689Sbostic object *pack; 24332689Sbostic FILE *fp; 24432689Sbostic boolean is_rogue; 24532689Sbostic { 24632689Sbostic object read_obj, *new_obj; 24732689Sbostic 24832689Sbostic for (;;) { 24932689Sbostic r_read(fp, (char *) &read_obj, sizeof(object)); 25032689Sbostic if (read_obj.ichar == 0) { 25132689Sbostic pack->next_object = (object *) 0; 25232689Sbostic break; 25332689Sbostic } 25432689Sbostic new_obj = alloc_object(); 25532689Sbostic *new_obj = read_obj; 25632689Sbostic if (is_rogue) { 25732689Sbostic if (new_obj->in_use_flags & BEING_WORN) { 25832689Sbostic do_wear(new_obj); 25932689Sbostic } else if (new_obj->in_use_flags & BEING_WIELDED) { 26032689Sbostic do_wield(new_obj); 26132689Sbostic } else if (new_obj->in_use_flags & (ON_EITHER_HAND)) { 26232689Sbostic do_put_on(new_obj, 26332689Sbostic ((new_obj->in_use_flags & ON_LEFT_HAND) ? 1 : 0)); 26432689Sbostic } 26532689Sbostic } 26632689Sbostic pack->next_object = new_obj; 26732689Sbostic pack = new_obj; 26832689Sbostic } 26932689Sbostic } 27032689Sbostic 27132689Sbostic rw_dungeon(fp, rw) 27232689Sbostic FILE *fp; 27332689Sbostic boolean rw; 27432689Sbostic { 27532689Sbostic short i, j; 27632689Sbostic char buf[DCOLS]; 27732689Sbostic 27832689Sbostic for (i = 0; i < DROWS; i++) { 27932689Sbostic if (rw) { 28032689Sbostic r_write(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0]))); 28132689Sbostic for (j = 0; j < DCOLS; j++) { 28232689Sbostic buf[j] = mvinch(i, j); 28332689Sbostic } 28432689Sbostic r_write(fp, buf, DCOLS); 28532689Sbostic } else { 28632689Sbostic r_read(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0]))); 28732689Sbostic r_read(fp, buf, DCOLS); 28832689Sbostic for (j = 0; j < DCOLS; j++) { 28932689Sbostic mvaddch(i, j, buf[j]); 29032689Sbostic } 29132689Sbostic } 29232689Sbostic } 29332689Sbostic } 29432689Sbostic 29532689Sbostic rw_id(id_table, fp, n, wr) 29632689Sbostic struct id id_table[]; 29732689Sbostic FILE *fp; 29832689Sbostic int n; 29932689Sbostic boolean wr; 30032689Sbostic { 30132689Sbostic short i; 30232689Sbostic 30332689Sbostic for (i = 0; i < n; i++) { 30432689Sbostic if (wr) { 30532689Sbostic r_write(fp, (char *) &(id_table[i].value), sizeof(short)); 30632689Sbostic r_write(fp, (char *) &(id_table[i].id_status), 30732689Sbostic sizeof(unsigned short)); 30832689Sbostic write_string(id_table[i].title, fp); 30932689Sbostic } else { 31032689Sbostic r_read(fp, (char *) &(id_table[i].value), sizeof(short)); 31132689Sbostic r_read(fp, (char *) &(id_table[i].id_status), 31232689Sbostic sizeof(unsigned short)); 31332689Sbostic read_string(id_table[i].title, fp); 31432689Sbostic } 31532689Sbostic } 31632689Sbostic } 31732689Sbostic 31832689Sbostic write_string(s, fp) 31932689Sbostic char *s; 32032689Sbostic FILE *fp; 32132689Sbostic { 32232689Sbostic short n; 32332689Sbostic 32432689Sbostic n = strlen(s) + 1; 32532689Sbostic xxxx(s, n); 32632689Sbostic r_write(fp, (char *) &n, sizeof(short)); 32732689Sbostic r_write(fp, s, n); 32832689Sbostic } 32932689Sbostic 33032689Sbostic read_string(s, fp) 33132689Sbostic char *s; 33232689Sbostic FILE *fp; 33332689Sbostic { 33432689Sbostic short n; 33532689Sbostic 33632689Sbostic r_read(fp, (char *) &n, sizeof(short)); 33732689Sbostic r_read(fp, s, n); 33832689Sbostic xxxx(s, n); 33932689Sbostic } 34032689Sbostic 34132689Sbostic rw_rooms(fp, rw) 34232689Sbostic FILE *fp; 34332689Sbostic boolean rw; 34432689Sbostic { 34532689Sbostic short i; 34632689Sbostic 34732689Sbostic for (i = 0; i < MAXROOMS; i++) { 34832689Sbostic rw ? r_write(fp, (char *) (rooms + i), sizeof(room)) : 34932689Sbostic r_read(fp, (char *) (rooms + i), sizeof(room)); 35032689Sbostic } 35132689Sbostic } 35232689Sbostic 35332689Sbostic r_read(fp, buf, n) 35432689Sbostic FILE *fp; 35532689Sbostic char *buf; 35632689Sbostic int n; 35732689Sbostic { 35832689Sbostic if (fread(buf, sizeof(char), n, fp) != n) { 35932689Sbostic clean_up("read() failed, don't know why"); 36032689Sbostic } 36132689Sbostic } 36232689Sbostic 36332689Sbostic r_write(fp, buf, n) 36432689Sbostic FILE *fp; 36532689Sbostic char *buf; 36632689Sbostic int n; 36732689Sbostic { 36832689Sbostic if (!write_failed) { 36932689Sbostic if (fwrite(buf, sizeof(char), n, fp) != n) { 37032689Sbostic message("write() failed, don't know why", 0); 37132689Sbostic sound_bell(); 37232689Sbostic write_failed = 1; 37332689Sbostic } 37432689Sbostic } 37532689Sbostic } 37632689Sbostic 37732689Sbostic boolean 37832689Sbostic has_been_touched(saved_time, mod_time) 37932689Sbostic struct rogue_time *saved_time, *mod_time; 38032689Sbostic { 38132689Sbostic if (saved_time->year < mod_time->year) { 38232689Sbostic return(1); 38332689Sbostic } else if (saved_time->year > mod_time->year) { 38432689Sbostic return(0); 38532689Sbostic } 38632689Sbostic if (saved_time->month < mod_time->month) { 38732689Sbostic return(1); 38832689Sbostic } else if (saved_time->month > mod_time->month) { 38932689Sbostic return(0); 39032689Sbostic } 39132689Sbostic if (saved_time->day < mod_time->day) { 39232689Sbostic return(1); 39332689Sbostic } else if (saved_time->day > mod_time->day) { 39432689Sbostic return(0); 39532689Sbostic } 39632689Sbostic if (saved_time->hour < mod_time->hour) { 39732689Sbostic return(1); 39832689Sbostic } else if (saved_time->hour > mod_time->hour) { 39932689Sbostic return(0); 40032689Sbostic } 40132689Sbostic if (saved_time->minute < mod_time->minute) { 40232689Sbostic return(1); 40332689Sbostic } else if (saved_time->minute > mod_time->minute) { 40432689Sbostic return(0); 40532689Sbostic } 40632689Sbostic if (saved_time->second < mod_time->second) { 40732689Sbostic return(1); 40832689Sbostic } 40932689Sbostic return(0); 41032689Sbostic } 411