Home | History | Annotate | Line # | Download | only in rogue
save.c revision 1.1
      1 /*
      2  * Copyright (c) 1988 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Timothy C. Stoehr.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 #ifndef lint
     38 static char sccsid[] = "@(#)save.c	5.3 (Berkeley) 6/1/90";
     39 #endif /* not lint */
     40 
     41 /*
     42  * save.c
     43  *
     44  * This source herein may be modified and/or distributed by anybody who
     45  * so desires, with the following restrictions:
     46  *    1.)  No portion of this notice shall be removed.
     47  *    2.)  Credit shall not be taken for the creation of this source.
     48  *    3.)  This code is not to be traded, sold, or used for personal
     49  *         gain or profit.
     50  *
     51  */
     52 
     53 #include <stdio.h>
     54 #include "rogue.h"
     55 
     56 short write_failed = 0;
     57 char *save_file = (char *) 0;
     58 
     59 extern boolean detect_monster;
     60 extern short cur_level, max_level;
     61 extern char hunger_str[];
     62 extern char login_name[];
     63 extern short party_room;
     64 extern short foods;
     65 extern boolean is_wood[];
     66 extern short cur_room;
     67 extern boolean being_held;
     68 extern short bear_trap;
     69 extern short halluc;
     70 extern short blind;
     71 extern short confused;
     72 extern short levitate;
     73 extern short haste_self;
     74 extern boolean see_invisible;
     75 extern boolean detect_monster;
     76 extern boolean wizard;
     77 extern boolean score_only;
     78 extern short m_moves;
     79 
     80 extern boolean msg_cleared;
     81 
     82 save_game()
     83 {
     84 	char fname[64];
     85 
     86 	if (!get_input_line("file name?", save_file, fname, "game not saved",
     87 			0, 1)) {
     88 		return;
     89 	}
     90 	check_message();
     91 	message(fname, 0);
     92 	save_into_file(fname);
     93 }
     94 
     95 save_into_file(sfile)
     96 char *sfile;
     97 {
     98 	FILE *fp;
     99 	int file_id;
    100 	char name_buffer[80];
    101 	char *hptr;
    102 	struct rogue_time rt_buf;
    103 
    104 	if (sfile[0] == '~') {
    105 		if (hptr = md_getenv("HOME")) {
    106 			(void) strcpy(name_buffer, hptr);
    107 			(void) strcat(name_buffer, sfile+1);
    108 			sfile = name_buffer;
    109 		}
    110 	}
    111 	if (	((fp = fopen(sfile, "w")) == NULL) ||
    112 			((file_id = md_get_file_id(sfile)) == -1)) {
    113 		message("problem accessing the save file", 0);
    114 		return;
    115 	}
    116 	md_ignore_signals();
    117 	write_failed = 0;
    118 	(void) xxx(1);
    119 	r_write(fp, (char *) &detect_monster, sizeof(detect_monster));
    120 	r_write(fp, (char *) &cur_level, sizeof(cur_level));
    121 	r_write(fp, (char *) &max_level, sizeof(max_level));
    122 	write_string(hunger_str, fp);
    123 	write_string(login_name, fp);
    124 	r_write(fp, (char *) &party_room, sizeof(party_room));
    125 	write_pack(&level_monsters, fp);
    126 	write_pack(&level_objects, fp);
    127 	r_write(fp, (char *) &file_id, sizeof(file_id));
    128 	rw_dungeon(fp, 1);
    129 	r_write(fp, (char *) &foods, sizeof(foods));
    130 	r_write(fp, (char *) &rogue, sizeof(fighter));
    131 	write_pack(&rogue.pack, fp);
    132 	rw_id(id_potions, fp, POTIONS, 1);
    133 	rw_id(id_scrolls, fp, SCROLS, 1);
    134 	rw_id(id_wands, fp, WANDS, 1);
    135 	rw_id(id_rings, fp, RINGS, 1);
    136 	r_write(fp, (char *) traps, (MAX_TRAPS * sizeof(trap)));
    137 	r_write(fp, (char *) is_wood, (WANDS * sizeof(boolean)));
    138 	r_write(fp, (char *) &cur_room, sizeof(cur_room));
    139 	rw_rooms(fp, 1);
    140 	r_write(fp, (char *) &being_held, sizeof(being_held));
    141 	r_write(fp, (char *) &bear_trap, sizeof(bear_trap));
    142 	r_write(fp, (char *) &halluc, sizeof(halluc));
    143 	r_write(fp, (char *) &blind, sizeof(blind));
    144 	r_write(fp, (char *) &confused, sizeof(confused));
    145 	r_write(fp, (char *) &levitate, sizeof(levitate));
    146 	r_write(fp, (char *) &haste_self, sizeof(haste_self));
    147 	r_write(fp, (char *) &see_invisible, sizeof(see_invisible));
    148 	r_write(fp, (char *) &detect_monster, sizeof(detect_monster));
    149 	r_write(fp, (char *) &wizard, sizeof(wizard));
    150 	r_write(fp, (char *) &score_only, sizeof(score_only));
    151 	r_write(fp, (char *) &m_moves, sizeof(m_moves));
    152 	md_gct(&rt_buf);
    153 	rt_buf.second += 10;		/* allow for some processing time */
    154 	r_write(fp, (char *) &rt_buf, sizeof(rt_buf));
    155 	fclose(fp);
    156 
    157 	if (write_failed) {
    158 		(void) md_df(sfile);	/* delete file */
    159 	} else {
    160 		clean_up("");
    161 	}
    162 }
    163 
    164 restore(fname)
    165 char *fname;
    166 {
    167 	FILE *fp;
    168 	struct rogue_time saved_time, mod_time;
    169 	char buf[4];
    170 	char tbuf[40];
    171 	int new_file_id, saved_file_id;
    172 
    173 	if (	((new_file_id = md_get_file_id(fname)) == -1) ||
    174 			((fp = fopen(fname, "r")) == NULL)) {
    175 		clean_up("cannot open file");
    176 	}
    177 	if (md_link_count(fname) > 1) {
    178 		clean_up("file has link");
    179 	}
    180 	(void) xxx(1);
    181 	r_read(fp, (char *) &detect_monster, sizeof(detect_monster));
    182 	r_read(fp, (char *) &cur_level, sizeof(cur_level));
    183 	r_read(fp, (char *) &max_level, sizeof(max_level));
    184 	read_string(hunger_str, fp);
    185 
    186 	(void) strcpy(tbuf, login_name);
    187 	read_string(login_name, fp);
    188 	if (strcmp(tbuf, login_name)) {
    189 		clean_up("you're not the original player");
    190 	}
    191 
    192 	r_read(fp, (char *) &party_room, sizeof(party_room));
    193 	read_pack(&level_monsters, fp, 0);
    194 	read_pack(&level_objects, fp, 0);
    195 	r_read(fp, (char *) &saved_file_id, sizeof(saved_file_id));
    196 	if (new_file_id != saved_file_id) {
    197 		clean_up("sorry, saved game is not in the same file");
    198 	}
    199 	rw_dungeon(fp, 0);
    200 	r_read(fp, (char *) &foods, sizeof(foods));
    201 	r_read(fp, (char *) &rogue, sizeof(fighter));
    202 	read_pack(&rogue.pack, fp, 1);
    203 	rw_id(id_potions, fp, POTIONS, 0);
    204 	rw_id(id_scrolls, fp, SCROLS, 0);
    205 	rw_id(id_wands, fp, WANDS, 0);
    206 	rw_id(id_rings, fp, RINGS, 0);
    207 	r_read(fp, (char *) traps, (MAX_TRAPS * sizeof(trap)));
    208 	r_read(fp, (char *) is_wood, (WANDS * sizeof(boolean)));
    209 	r_read(fp, (char *) &cur_room, sizeof(cur_room));
    210 	rw_rooms(fp, 0);
    211 	r_read(fp, (char *) &being_held, sizeof(being_held));
    212 	r_read(fp, (char *) &bear_trap, sizeof(bear_trap));
    213 	r_read(fp, (char *) &halluc, sizeof(halluc));
    214 	r_read(fp, (char *) &blind, sizeof(blind));
    215 	r_read(fp, (char *) &confused, sizeof(confused));
    216 	r_read(fp, (char *) &levitate, sizeof(levitate));
    217 	r_read(fp, (char *) &haste_self, sizeof(haste_self));
    218 	r_read(fp, (char *) &see_invisible, sizeof(see_invisible));
    219 	r_read(fp, (char *) &detect_monster, sizeof(detect_monster));
    220 	r_read(fp, (char *) &wizard, sizeof(wizard));
    221 	r_read(fp, (char *) &score_only, sizeof(score_only));
    222 	r_read(fp, (char *) &m_moves, sizeof(m_moves));
    223 	r_read(fp, (char *) &saved_time, sizeof(saved_time));
    224 
    225 	if (fread(buf, sizeof(char), 1, fp) > 0) {
    226 		clear();
    227 		clean_up("extra characters in file");
    228 	}
    229 
    230 	md_gfmt(fname, &mod_time);	/* get file modification time */
    231 
    232 	if (has_been_touched(&saved_time, &mod_time)) {
    233 		clear();
    234 		clean_up("sorry, file has been touched");
    235 	}
    236 	if ((!wizard) && !md_df(fname)) {
    237 		clean_up("cannot delete file");
    238 	}
    239 	msg_cleared = 0;
    240 	ring_stats(0);
    241 	fclose(fp);
    242 }
    243 
    244 write_pack(pack, fp)
    245 object *pack;
    246 FILE *fp;
    247 {
    248 	object t;
    249 
    250 	while (pack = pack->next_object) {
    251 		r_write(fp, (char *) pack, sizeof(object));
    252 	}
    253 	t.ichar = t.what_is = 0;
    254 	r_write(fp, (char *) &t, sizeof(object));
    255 }
    256 
    257 read_pack(pack, fp, is_rogue)
    258 object *pack;
    259 FILE *fp;
    260 boolean is_rogue;
    261 {
    262 	object read_obj, *new_obj;
    263 
    264 	for (;;) {
    265 		r_read(fp, (char *) &read_obj, sizeof(object));
    266 		if (read_obj.ichar == 0) {
    267 			pack->next_object = (object *) 0;
    268 			break;
    269 		}
    270 		new_obj = alloc_object();
    271 		*new_obj = read_obj;
    272 		if (is_rogue) {
    273 			if (new_obj->in_use_flags & BEING_WORN) {
    274 					do_wear(new_obj);
    275 			} else if (new_obj->in_use_flags & BEING_WIELDED) {
    276 					do_wield(new_obj);
    277 			} else if (new_obj->in_use_flags & (ON_EITHER_HAND)) {
    278 				do_put_on(new_obj,
    279 					((new_obj->in_use_flags & ON_LEFT_HAND) ? 1 : 0));
    280 			}
    281 		}
    282 		pack->next_object = new_obj;
    283 		pack = new_obj;
    284 	}
    285 }
    286 
    287 rw_dungeon(fp, rw)
    288 FILE *fp;
    289 boolean rw;
    290 {
    291 	short i, j;
    292 	char buf[DCOLS];
    293 
    294 	for (i = 0; i < DROWS; i++) {
    295 		if (rw) {
    296 			r_write(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0])));
    297 			for (j = 0; j < DCOLS; j++) {
    298 				buf[j] = mvinch(i, j);
    299 			}
    300 			r_write(fp, buf, DCOLS);
    301 		} else {
    302 			r_read(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0])));
    303 			r_read(fp, buf, DCOLS);
    304 			for (j = 0; j < DCOLS; j++) {
    305 				mvaddch(i, j, buf[j]);
    306 			}
    307 		}
    308 	}
    309 }
    310 
    311 rw_id(id_table, fp, n, wr)
    312 struct id id_table[];
    313 FILE *fp;
    314 int n;
    315 boolean wr;
    316 {
    317 	short i;
    318 
    319 	for (i = 0; i < n; i++) {
    320 		if (wr) {
    321 			r_write(fp, (char *) &(id_table[i].value), sizeof(short));
    322 			r_write(fp, (char *) &(id_table[i].id_status),
    323 				sizeof(unsigned short));
    324 			write_string(id_table[i].title, fp);
    325 		} else {
    326 			r_read(fp, (char *) &(id_table[i].value), sizeof(short));
    327 			r_read(fp, (char *) &(id_table[i].id_status),
    328 				sizeof(unsigned short));
    329 			read_string(id_table[i].title, fp);
    330 		}
    331 	}
    332 }
    333 
    334 write_string(s, fp)
    335 char *s;
    336 FILE *fp;
    337 {
    338 	short n;
    339 
    340 	n = strlen(s) + 1;
    341 	xxxx(s, n);
    342 	r_write(fp, (char *) &n, sizeof(short));
    343 	r_write(fp, s, n);
    344 }
    345 
    346 read_string(s, fp)
    347 char *s;
    348 FILE *fp;
    349 {
    350 	short n;
    351 
    352 	r_read(fp, (char *) &n, sizeof(short));
    353 	r_read(fp, s, n);
    354 	xxxx(s, n);
    355 }
    356 
    357 rw_rooms(fp, rw)
    358 FILE *fp;
    359 boolean rw;
    360 {
    361 	short i;
    362 
    363 	for (i = 0; i < MAXROOMS; i++) {
    364 		rw ? r_write(fp, (char *) (rooms + i), sizeof(room)) :
    365 			r_read(fp, (char *) (rooms + i), sizeof(room));
    366 	}
    367 }
    368 
    369 r_read(fp, buf, n)
    370 FILE *fp;
    371 char *buf;
    372 int n;
    373 {
    374 	if (fread(buf, sizeof(char), n, fp) != n) {
    375 		clean_up("read() failed, don't know why");
    376 	}
    377 }
    378 
    379 r_write(fp, buf, n)
    380 FILE *fp;
    381 char *buf;
    382 int n;
    383 {
    384 	if (!write_failed) {
    385 		if (fwrite(buf, sizeof(char), n, fp) != n) {
    386 			message("write() failed, don't know why", 0);
    387 			sound_bell();
    388 			write_failed = 1;
    389 		}
    390 	}
    391 }
    392 
    393 boolean
    394 has_been_touched(saved_time, mod_time)
    395 struct rogue_time *saved_time, *mod_time;
    396 {
    397 	if (saved_time->year < mod_time->year) {
    398 		return(1);
    399 	} else if (saved_time->year > mod_time->year) {
    400 		return(0);
    401 	}
    402 	if (saved_time->month < mod_time->month) {
    403 		return(1);
    404 	} else if (saved_time->month > mod_time->month) {
    405 		return(0);
    406 	}
    407 	if (saved_time->day < mod_time->day) {
    408 		return(1);
    409 	} else if (saved_time->day > mod_time->day) {
    410 		return(0);
    411 	}
    412 	if (saved_time->hour < mod_time->hour) {
    413 		return(1);
    414 	} else if (saved_time->hour > mod_time->hour) {
    415 		return(0);
    416 	}
    417 	if (saved_time->minute < mod_time->minute) {
    418 		return(1);
    419 	} else if (saved_time->minute > mod_time->minute) {
    420 		return(0);
    421 	}
    422 	if (saved_time->second < mod_time->second) {
    423 		return(1);
    424 	}
    425 	return(0);
    426 }
    427