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