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