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