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