comparison rogue3/state.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children 09db0cf536af
comparison
equal deleted inserted replaced
-1:000000000000 0:527e2150eaf0
1 /*
2 state.c - Portable Rogue Save State Code
3
4 Copyright (C) 1999, 2000, 2005, 2007, 2008 Nicholas J. Kisseberth
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name(s) of the author(s) nor the names of other contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <curses.h>
35 #include <errno.h>
36 #include "rogue.h"
37
38 /************************************************************************/
39 /* Save State Code */
40 /************************************************************************/
41
42 #define RSID_STATS 0xABCD0001
43 #define RSID_THING 0xABCD0002
44 #define RSID_THING_NULL 0xDEAD0002
45 #define RSID_OBJECT 0xABCD0003
46 #define RSID_MAGICITEMS 0xABCD0004
47 #define RSID_KNOWS 0xABCD0005
48 #define RSID_GUESSES 0xABCD0006
49 #define RSID_OBJECTLIST 0xABCD0007
50 #define RSID_BAGOBJECT 0xABCD0008
51 #define RSID_MONSTERLIST 0xABCD0009
52 #define RSID_MONSTERSTATS 0xABCD000A
53 #define RSID_MONSTERS 0xABCD000B
54 #define RSID_TRAP 0xABCD000C
55 #define RSID_WINDOW 0xABCD000D
56 #define RSID_DAEMONS 0xABCD000E
57 #define RSID_IWEAPS 0xABCD000F
58 #define RSID_IARMOR 0xABCD0010
59 #define RSID_SPELLS 0xABCD0011
60 #define RSID_ILIST 0xABCD0012
61 #define RSID_HLIST 0xABCD0013
62 #define RSID_DEATHTYPE 0xABCD0014
63 #define RSID_CTYPES 0XABCD0015
64 #define RSID_COORDLIST 0XABCD0016
65 #define RSID_ROOMS 0XABCD0017
66
67 #define READSTAT (format_error || read_error )
68 #define WRITESTAT (write_error)
69
70 static int read_error = FALSE;
71 static int write_error = FALSE;
72 static int format_error = FALSE;
73 static int endian = 0x01020304;
74 #define big_endian ( *((char *)&endian) == 0x01 )
75
76 void
77 rs_write(FILE *savef, const void *ptr, size_t size)
78 {
79 encwrite(ptr, size, savef);
80 }
81
82 void
83 rs_read(FILE *savef, void *ptr, size_t size)
84 {
85 encread(ptr, size, savef);
86 }
87
88 void
89 rs_write_int(FILE *savef, int c)
90 {
91 char bytes[4];
92 char *buf = (char *) &c;
93
94 if (big_endian)
95 {
96 bytes[3] = buf[0];
97 bytes[2] = buf[1];
98 bytes[1] = buf[2];
99 bytes[0] = buf[3];
100 buf = bytes;
101 }
102
103 rs_write(savef, buf, 4);
104 }
105
106 void
107 rs_read_int(FILE *savef, int *i)
108 {
109 char bytes[4];
110 int input = 0;
111 char *buf = (char *)&input;
112
113 rs_read(savef, &input, 4);
114
115 if (encerror())
116 return;
117
118 if (big_endian)
119 {
120 bytes[3] = buf[0];
121 bytes[2] = buf[1];
122 bytes[1] = buf[2];
123 bytes[0] = buf[3];
124 buf = bytes;
125 }
126
127 *i = *((int *) buf);
128 }
129
130 void
131 rs_write_uint(FILE *savef, unsigned int c)
132 {
133 char bytes[4];
134 char *buf = (char *) &c;
135
136 if (big_endian)
137 {
138 bytes[3] = buf[0];
139 bytes[2] = buf[1];
140 bytes[1] = buf[2];
141 bytes[0] = buf[3];
142 buf = bytes;
143 }
144
145 rs_write(savef, buf, 4);
146 }
147
148 void
149 rs_read_uint(FILE *savef, unsigned int *i)
150 {
151 char bytes[4];
152 int input = 0;
153 char *buf = (char *)&input;
154
155 rs_read(savef, &input, 4);
156
157 if (encerror())
158 return;
159
160 if (big_endian)
161 {
162 bytes[3] = buf[0];
163 bytes[2] = buf[1];
164 bytes[1] = buf[2];
165 bytes[0] = buf[3];
166 buf = bytes;
167 }
168
169 *i = *((unsigned int *) buf);
170 }
171
172 void
173 rs_write_chars(FILE *savef, const char *c, int cnt)
174 {
175 rs_write_int(savef, cnt);
176 rs_write(savef, c, cnt);
177 }
178
179 void
180 rs_read_chars(FILE *savef, char *i, int cnt)
181 {
182 int value = 0;
183
184 rs_read_int(savef, &value);
185
186 if (!encerror() && (value != cnt))
187 encseterr(EILSEQ);
188
189 rs_read(savef, i, cnt);
190 }
191
192 void
193 rs_write_ints(FILE *savef, int *c, int cnt)
194 {
195 int n = 0;
196
197 rs_write_int(savef, cnt);
198
199 for(n = 0; n < cnt; n++)
200 rs_write_int(savef,c[n]);
201 }
202
203 void
204 rs_read_ints(FILE *savef, int *i, int cnt)
205 {
206 int n, value;
207
208 rs_read_int(savef,&value);
209
210 if (!encerror() && (value != cnt))
211 encseterr(EILSEQ);
212
213 for(n = 0; n < cnt; n++)
214 rs_read_int(savef, &i[n]);
215 }
216
217 void
218 rs_write_marker(FILE *savef, int id)
219 {
220 rs_write_int(savef, id);
221 }
222
223 void
224 rs_read_marker(FILE *savef, int id)
225 {
226 int nid;
227
228 rs_read_int(savef, &nid);
229
230 if (!encerror() && (id != nid))
231 encseterr(EILSEQ);
232 }
233
234 /******************************************************************************/
235
236 void
237 rs_write_string(FILE *savef, const char *s)
238 {
239 int len = 0;
240
241 len = (s == NULL) ? 0 : (int) strlen(s) + 1;
242
243 rs_write_int(savef, len);
244 rs_write_chars(savef, s, len);
245 }
246
247 void
248 rs_read_string(FILE *savef, char *s, int max)
249 {
250 int len = 0;
251
252 rs_read_int(savef, &len);
253
254 if (!encerror() && (len > max))
255 encseterr(EILSEQ);
256
257 rs_read_chars(savef, s, len);
258 }
259
260 void
261 rs_read_new_string(FILE *savef, char **s)
262 {
263 int len=0;
264 char *buf=0;
265
266 rs_read_int(savef, &len);
267
268 if (encerror())
269 return;
270
271 if (len == 0)
272 buf = NULL;
273 else
274 {
275 buf = malloc(len);
276
277 if (buf == NULL)
278 encseterr(ENOMEM);
279 }
280
281 rs_read_chars(savef, buf, len);
282
283 *s = buf;
284 }
285
286 void
287 rs_write_string_index(FILE *savef, char *master[], int max, char *str)
288 {
289 int i;
290
291 for(i = 0; i < max; i++)
292 if (str == master[i])
293 {
294 rs_write_int(savef, i);
295 return;
296 }
297
298 rs_write_int(savef,-1);
299 }
300
301 void
302 rs_read_string_index(FILE *savef, char *master[], int maxindex, char **str)
303 {
304 int i;
305
306 rs_read_int(savef, &i);
307
308 if (!encerror() && (i > maxindex))
309 encseterr(EILSEQ);
310 else if (i >= 0)
311 *str = master[i];
312 else
313 *str = NULL;
314 }
315
316 void
317 rs_write_coord(FILE *savef, coord c)
318 {
319 rs_write_int(savef, c.x);
320 rs_write_int(savef, c.y);
321 }
322
323 void
324 rs_read_coord(FILE *savef, coord *c)
325 {
326 coord in;
327
328 rs_read_int(savef,&in.x);
329 rs_read_int(savef,&in.y);
330
331 if (!encerror())
332 {
333 c->x = in.x;
334 c->y = in.y;
335 }
336 }
337
338 void
339 rs_write_str_t(FILE *savef, str_t str)
340 {
341 rs_write_int(savef, str.st_str);
342 rs_write_int(savef, str.st_add);
343 }
344
345 void
346 rs_read_str_t(FILE *savef, str_t *str)
347 {
348 str_t in;
349
350 rs_read_int(savef,&in.st_str);
351 rs_read_int(savef,&in.st_add);
352
353 if (!encerror())
354 {
355 str->st_str = in.st_str;
356 str->st_add = in.st_add;
357 }
358 }
359
360 void
361 rs_write_window(FILE *savef, WINDOW *win)
362 {
363 int row,col,height,width;
364
365 width = getmaxx(win);
366 height = getmaxy(win);
367
368 rs_write_marker(savef,RSID_WINDOW);
369 rs_write_int(savef,height);
370 rs_write_int(savef,width);
371
372 for(row=0;row<height;row++)
373 for(col=0;col<width;col++)
374 rs_write_int(savef, mvwinch(win,row,col));
375 }
376
377 void
378 rs_read_window(FILE *savef, WINDOW *win)
379 {
380 int row,col,maxlines,maxcols,value,width,height;
381
382 width = getmaxx(win);
383 height = getmaxy(win);
384
385 rs_read_marker(savef, RSID_WINDOW);
386
387 rs_read_int(savef, &maxlines);
388 rs_read_int(savef, &maxcols);
389
390 if (encerror())
391 return;
392
393 for(row = 0; row < maxlines; row++)
394 for(col = 0; col < maxcols; col++)
395 {
396 rs_read_int(savef, &value);
397
398 if ((row < height) && (col < width))
399 mvwaddch(win,row,col,value);
400 }
401 }
402
403 /******************************************************************************/
404
405 void *
406 get_list_item(struct linked_list *l, int i)
407 {
408 int cnt;
409
410 for(cnt = 0; l != NULL; cnt++, l = l->l_next)
411 if (cnt == i)
412 return(l->l_data);
413
414 return(NULL);
415 }
416
417 int
418 find_list_ptr(struct linked_list *l, void *ptr)
419 {
420 int cnt;
421
422 for(cnt = 0; l != NULL; cnt++, l = l->l_next)
423 if (l->l_data == ptr)
424 return(cnt);
425
426 return(-1);
427 }
428
429 int
430 list_size(struct linked_list *l)
431 {
432 int cnt;
433
434 for(cnt = 0; l != NULL; cnt++, l = l->l_next)
435 if (l->l_data == NULL)
436 return(cnt);
437
438 return(cnt);
439 }
440
441 /******************************************************************************/
442
443 void
444 rs_write_stats(FILE *savef, struct stats *s)
445 {
446 rs_write_marker(savef, RSID_STATS);
447 rs_write_str_t(savef, s->s_str);
448 rs_write_int(savef, s->s_exp);
449 rs_write_int(savef, s->s_lvl);
450 rs_write_int(savef, s->s_arm);
451 rs_write_int(savef, s->s_hpt);
452 rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg));
453 }
454
455
456 void
457 rs_read_stats(FILE *savef, struct stats *s)
458 {
459 rs_read_marker(savef, RSID_STATS);
460 rs_read_str_t(savef,&s->s_str);
461 rs_read_int(savef,&s->s_exp);
462 rs_read_int(savef,&s->s_lvl);
463 rs_read_int(savef,&s->s_arm);
464 rs_read_int(savef,&s->s_hpt);
465 rs_read_chars(savef,s->s_dmg,sizeof(s->s_dmg));
466 }
467
468
469 void
470 rs_write_scrolls(FILE *savef)
471 {
472 int i;
473
474 for(i = 0; i < MAXSCROLLS; i++)
475 {
476 rs_write_string(savef,s_names[i]);
477 rs_write_int(savef,s_know[i]);
478 rs_write_string(savef,s_guess[i]);
479 }
480 }
481
482 void
483 rs_read_scrolls(FILE *savef)
484 {
485 int i;
486
487 for(i = 0; i < MAXSCROLLS; i++)
488 {
489 rs_read_new_string(savef,&s_names[i]);
490 rs_read_int(savef,&s_know[i]);
491 rs_read_new_string(savef,&s_guess[i]);
492 }
493 }
494
495 void
496 rs_write_potions(FILE *savef)
497 {
498 int i;
499
500 for(i = 0; i < MAXPOTIONS; i++)
501 {
502 rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]);
503 rs_write_int(savef,p_know[i]);
504 rs_write_string(savef,p_guess[i]);
505 }
506 }
507
508 void
509 rs_read_potions(FILE *savef)
510 {
511 int i;
512
513 for(i = 0; i < MAXPOTIONS; i++)
514 {
515 rs_read_string_index(savef, rainbow, cNCOLORS, &p_colors[i]);
516 rs_read_int(savef,&p_know[i]);
517 rs_read_new_string(savef,&p_guess[i]);
518 }
519 }
520
521 void
522 rs_write_rings(FILE *savef)
523 {
524 int i;
525
526 for(i = 0; i < MAXRINGS; i++)
527 {
528 rs_write_string_index(savef, stones, cNSTONES, r_stones[i]);
529 rs_write_int(savef,r_know[i]);
530 rs_write_string(savef,r_guess[i]);
531 }
532 }
533
534 void
535 rs_read_rings(FILE *savef)
536 {
537 int i;
538
539 for(i = 0; i < MAXRINGS; i++)
540 {
541 rs_read_string_index(savef, stones, cNSTONES, &r_stones[i]);
542 rs_read_int(savef,&r_know[i]);
543 rs_read_new_string(savef,&r_guess[i]);
544 }
545 }
546
547 void
548 rs_write_sticks(FILE *savef)
549 {
550 int i;
551
552 for (i = 0; i < MAXSTICKS; i++)
553 {
554 if (strcmp(ws_type[i],"staff") == 0)
555 {
556 rs_write_int(savef,0);
557 rs_write_string_index(savef, wood, cNWOOD, ws_made[i]);
558 }
559 else
560 {
561 rs_write_int(savef,1);
562 rs_write_string_index(savef, metal, cNMETAL, ws_made[i]);
563 }
564 rs_write_int(savef, ws_know[i]);
565 rs_write_string(savef, ws_guess[i]);
566 }
567 }
568
569 void
570 rs_read_sticks(FILE *savef)
571 {
572 int i = 0, list = 0;
573
574 for(i = 0; i < MAXSTICKS; i++)
575 {
576 rs_read_int(savef,&list);
577
578 if (list == 0)
579 {
580 rs_read_string_index(savef, wood, cNWOOD, &ws_made[i]);
581 ws_type[i] = "staff";
582 }
583 else
584 {
585 rs_read_string_index(savef, metal, cNMETAL, &ws_made[i]);
586 ws_type[i] = "wand";
587 }
588 rs_read_int(savef, &ws_know[i]);
589 rs_read_new_string(savef, &ws_guess[i]);
590 }
591 }
592
593 void
594 rs_write_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
595 {
596 int i = 0;
597 int func = 0;
598
599 rs_write_marker(savef, RSID_DAEMONS);
600 rs_write_int(savef, cnt);
601
602 for(i = 0; i < cnt; i++)
603 {
604 if (dlist[i].d_func == rollwand)
605 func = 1;
606 else if (dlist[i].d_func == doctor)
607 func = 2;
608 else if (dlist[i].d_func == stomach)
609 func = 3;
610 else if (dlist[i].d_func == runners)
611 func = 4;
612 else if (dlist[i].d_func == swander)
613 func = 5;
614 else if (dlist[i].d_func == nohaste)
615 func = 6;
616 else if (dlist[i].d_func == unconfuse)
617 func = 7;
618 else if (dlist[i].d_func == unsee)
619 func = 8;
620 else if (dlist[i].d_func == sight)
621 func = 9;
622 else if (dlist[i].d_func == NULL)
623 func = 0;
624 else
625 func = -1;
626
627 rs_write_int(savef, dlist[i].d_type);
628 rs_write_int(savef, func);
629 rs_write_int(savef, dlist[i].d_arg);
630 rs_write_int(savef, dlist[i].d_time);
631 }
632 }
633
634 void
635 rs_read_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
636 {
637 int i = 0;
638 int func = 0;
639 int value = 0;
640
641 rs_read_marker(savef, RSID_DAEMONS);
642 rs_read_int(savef, &value);
643
644 if (!encerror() && (value > cnt))
645 {
646 encseterr(EILSEQ);
647 return;
648 }
649
650 for(i=0; i < cnt; i++)
651 {
652 func = 0;
653 rs_read_int(savef, &dlist[i].d_type);
654 rs_read_int(savef, &func);
655 rs_read_int(savef, &dlist[i].d_arg);
656 rs_read_int(savef, &dlist[i].d_time);
657
658 if (encerror())
659 return;
660
661 switch(func)
662 {
663 case 1: dlist[i].d_func = rollwand;
664 break;
665 case 2: dlist[i].d_func = doctor;
666 break;
667 case 3: dlist[i].d_func = stomach;
668 break;
669 case 4: dlist[i].d_func = runners;
670 break;
671 case 5: dlist[i].d_func = swander;
672 break;
673 case 6: dlist[i].d_func = nohaste;
674 break;
675 case 7: dlist[i].d_func = unconfuse;
676 break;
677 case 8: dlist[i].d_func = unsee;
678 break;
679 case 9: dlist[i].d_func = sight;
680 break;
681 default:dlist[i].d_func = NULL;
682 break;
683 }
684 }
685
686 if (dlist[i].d_func == NULL)
687 {
688 dlist[i].d_type = 0;
689 dlist[i].d_arg = 0;
690 dlist[i].d_time = 0;
691 }
692 }
693
694 void
695 rs_write_room(FILE *savef, struct room *r)
696 {
697 rs_write_coord(savef, r->r_pos);
698 rs_write_coord(savef, r->r_max);
699 rs_write_coord(savef, r->r_gold);
700 rs_write_int(savef, r->r_goldval);
701 rs_write_int(savef, r->r_flags);
702 rs_write_int(savef, r->r_nexits);
703 rs_write_coord(savef, r->r_exit[0]);
704 rs_write_coord(savef, r->r_exit[1]);
705 rs_write_coord(savef, r->r_exit[2]);
706 rs_write_coord(savef, r->r_exit[3]);
707 }
708
709 void
710 rs_read_room(FILE *savef, struct room *r)
711 {
712 rs_read_coord(savef,&r->r_pos);
713 rs_read_coord(savef,&r->r_max);
714 rs_read_coord(savef,&r->r_gold);
715 rs_read_int(savef,&r->r_goldval);
716 rs_read_int(savef,&r->r_flags);
717 rs_read_int(savef,&r->r_nexits);
718 rs_read_coord(savef,&r->r_exit[0]);
719 rs_read_coord(savef,&r->r_exit[1]);
720 rs_read_coord(savef,&r->r_exit[2]);
721 rs_read_coord(savef,&r->r_exit[3]);
722 }
723
724 void
725 rs_write_rooms(FILE *savef, struct room r[], int cnt)
726 {
727 int n = 0;
728
729 rs_write_int(savef, cnt);
730
731 for(n = 0; n < cnt; n++)
732 rs_write_room(savef, &r[n]);
733 }
734
735 void
736 rs_read_rooms(FILE *savef, struct room *r, int cnt)
737 {
738 int value = 0, n = 0;
739
740 rs_read_int(savef,&value);
741
742 if (!encerror() && (value > cnt))
743 encseterr(EILSEQ);
744 else
745 for(n = 0; n < value; n++)
746 rs_read_room(savef,&r[n]);
747 }
748
749 void
750 rs_write_room_reference(FILE *savef, struct room *rp)
751 {
752 int i, room = -1;
753
754 for (i = 0; i < MAXROOMS; i++)
755 if (&rooms[i] == rp)
756 room = i;
757
758 rs_write_int(savef, room);
759 }
760
761 void
762 rs_read_room_reference(FILE *savef, struct room **rp)
763 {
764 int i;
765
766 rs_read_int(savef, &i);
767
768 if (!encerror())
769 *rp = &rooms[i];
770 }
771
772 void
773 rs_write_object(FILE *savef, struct object *o)
774 {
775 rs_write_marker(savef, RSID_OBJECT);
776 rs_write_int(savef, o->o_type);
777 rs_write_coord(savef, o->o_pos);
778 rs_write_int(savef, o->o_launch);
779 rs_write_chars(savef, o->o_damage, sizeof(o->o_damage));
780 rs_write_chars(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
781 rs_write_int(savef, o->o_count);
782 rs_write_int(savef, o->o_which);
783 rs_write_int(savef, o->o_hplus);
784 rs_write_int(savef, o->o_dplus);
785 rs_write_int(savef, o->o_ac);
786 rs_write_int(savef, o->o_flags);
787 rs_write_int(savef, o->o_group);
788 }
789
790 void
791 rs_read_object(FILE *savef, struct object *o)
792 {
793 rs_read_marker(savef, RSID_OBJECT);
794 rs_read_int(savef, &o->o_type);
795 rs_read_coord(savef, &o->o_pos);
796 rs_read_int(savef, &o->o_launch);
797 rs_read_chars(savef, o->o_damage, sizeof(o->o_damage));
798 rs_read_chars(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
799 rs_read_int(savef, &o->o_count);
800 rs_read_int(savef, &o->o_which);
801 rs_read_int(savef, &o->o_hplus);
802 rs_read_int(savef, &o->o_dplus);
803 rs_read_int(savef,&o->o_ac);
804 rs_read_int(savef,&o->o_flags);
805 rs_read_int(savef,&o->o_group);
806 }
807
808 void
809 rs_write_object_list(FILE *savef, struct linked_list *l)
810 {
811 rs_write_marker(savef, RSID_OBJECTLIST);
812 rs_write_int(savef, list_size(l));
813
814 for( ;l != NULL; l = l->l_next)
815 rs_write_object(savef, (struct object *) l->l_data);
816 }
817
818 void
819 rs_read_object_list(FILE *savef, struct linked_list **list)
820 {
821 int i, cnt;
822 struct linked_list *l = NULL, *previous = NULL, *head = NULL;
823
824 rs_read_marker(savef, RSID_OBJECTLIST);
825 rs_read_int(savef, &cnt);
826
827 if (encerror())
828 return;
829
830 for (i = 0; i < cnt; i++)
831 {
832 l = new_item(sizeof(struct object));
833
834 memset(l->l_data,0,sizeof(struct object));
835
836 l->l_prev = previous;
837
838 if (previous != NULL)
839 previous->l_next = l;
840
841 rs_read_object(savef,(struct object *) l->l_data);
842
843 if (previous == NULL)
844 head = l;
845
846 previous = l;
847 }
848
849 if (l != NULL)
850 l->l_next = NULL;
851
852 *list = head;
853 }
854
855 void
856 rs_write_object_reference(FILE *savef, struct linked_list *list, struct object *item)
857 {
858 int i;
859
860 i = find_list_ptr(list, item);
861
862 rs_write_int(savef, i);
863 }
864
865 void
866 rs_read_object_reference(FILE *savef, struct linked_list *list, struct object **item)
867 {
868 int i;
869
870 rs_read_int(savef, &i);
871
872 if (!encerror())
873 *item = get_list_item(list,i);
874 else
875 *item = NULL;
876 }
877
878 int
879 find_room_coord(const struct room *rmlist, const coord *c, int n)
880 {
881 int i = 0;
882
883 for(i = 0; i < n; i++)
884 if(&rmlist[i].r_gold == c)
885 return(i);
886
887 return(-1);
888 }
889
890 int
891 find_thing_coord(struct linked_list *monlist, coord *c)
892 {
893 struct linked_list *mitem;
894 struct thing *tp;
895 int i = 0;
896
897 for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
898 {
899 tp = THINGPTR(mitem);
900
901 if (c == &tp->t_pos)
902 return(i);
903
904 i++;
905 }
906
907 return(-1);
908 }
909
910 int
911 find_object_coord(struct linked_list *objlist, coord *c)
912 {
913 struct linked_list *oitem;
914 struct object *obj;
915 int i = 0;
916
917 for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
918 {
919 obj = OBJPTR(oitem);
920
921 if (c == &obj->o_pos)
922 return(i);
923
924 i++;
925 }
926
927 return(-1);
928 }
929
930 void
931 rs_write_thing(FILE *savef, struct thing *t)
932 {
933 int i = -1;
934
935 rs_write_marker(savef, RSID_THING);
936
937 if (t == NULL)
938 {
939 rs_write_int(savef, 0);
940 return;
941 }
942
943 rs_write_int(savef, 1);
944 rs_write_coord(savef, t->t_pos);
945 rs_write_int(savef, t->t_turn);
946 rs_write_int(savef, t->t_type);
947 rs_write_int(savef, t->t_disguise);
948 rs_write_int(savef, t->t_oldch);
949
950 /*
951 t_dest can be:
952 0,0: NULL
953 0,1: location of hero
954 1,i: location of a thing (monster)
955 2,i: location of an object
956 3,i: location of gold in a room
957
958 We need to remember what we are chasing rather than
959 the current location of what we are chasing.
960 */
961
962 if (t->t_dest == &hero)
963 {
964 rs_write_int(savef,0);
965 rs_write_int(savef,1);
966 }
967 else if (t->t_dest != NULL)
968 {
969 i = find_thing_coord(mlist, t->t_dest);
970
971 if (i >=0 )
972 {
973 rs_write_int(savef,1);
974 rs_write_int(savef,i);
975 }
976 else
977 {
978 i = find_object_coord(lvl_obj, t->t_dest);
979
980 if (i >= 0)
981 {
982 rs_write_int(savef,2);
983 rs_write_int(savef,i);
984 }
985 else
986 {
987 i = find_room_coord(rooms, t->t_dest, MAXROOMS);
988
989 if (i >= 0)
990 {
991 rs_write_int(savef,3);
992 rs_write_int(savef,i);
993 }
994 else
995 {
996 rs_write_int(savef, 0);
997 rs_write_int(savef,1); /* chase the hero anyway */
998 }
999 }
1000 }
1001 }
1002 else
1003 {
1004 rs_write_int(savef,0);
1005 rs_write_int(savef,0);
1006 }
1007
1008 rs_write_int(savef, t->t_flags);
1009 rs_write_stats(savef, &t->t_stats);
1010 rs_write_object_list(savef, t->t_pack);
1011 }
1012
1013 void
1014 rs_read_thing(FILE *savef, struct thing *t)
1015 {
1016 int listid = 0, index = -1;
1017 struct linked_list *item;
1018
1019 rs_read_marker(savef, RSID_THING);
1020 rs_read_int(savef, &index);
1021
1022 if (encerror())
1023 return;
1024
1025 if (index == 0)
1026 return;
1027
1028 rs_read_coord(savef,&t->t_pos);
1029 rs_read_int(savef,&t->t_turn);
1030 rs_read_int(savef,&t->t_type);
1031 rs_read_int(savef,&t->t_disguise);
1032 rs_read_int(savef,&t->t_oldch);
1033
1034 /*
1035 t_dest can be (listid,index):
1036 0,0: NULL
1037 0,1: location of hero
1038 1,i: location of a thing (monster)
1039 2,i: location of an object
1040 3,i: location of gold in a room
1041
1042 We need to remember what we are chasing rather than
1043 the current location of what we are chasing.
1044 */
1045
1046 rs_read_int(savef, &listid);
1047 rs_read_int(savef, &index);
1048 t->t_reserved = -1;
1049
1050 if (encerror())
1051 return;
1052
1053 if (listid == 0) /* hero or NULL */
1054 {
1055 if (index == 1)
1056 t->t_dest = &hero;
1057 else
1058 t->t_dest = NULL;
1059 }
1060 else if (listid == 1) /* monster/thing */
1061 {
1062 t->t_dest = NULL;
1063 t->t_reserved = index;
1064 }
1065 else if (listid == 2) /* object */
1066 {
1067 struct object *obj;
1068
1069 item = get_list_item(lvl_obj,index);
1070
1071 if (item != NULL)
1072 {
1073 obj = OBJPTR(item);
1074 t->t_dest = &obj->o_pos;
1075 }
1076 }
1077 else if (listid == 3) /* gold */
1078 {
1079 t->t_dest = &rooms[index].r_gold;
1080 }
1081 else
1082 t->t_dest = NULL;
1083
1084 rs_read_int(savef,&t->t_flags);
1085 rs_read_stats(savef,&t->t_stats);
1086 rs_read_object_list(savef,&t->t_pack);
1087 }
1088
1089 void
1090 rs_fix_thing(struct thing *t)
1091 {
1092 struct linked_list *item;
1093 struct thing *tp;
1094
1095 if (t->t_reserved < 0)
1096 return;
1097
1098 item = get_list_item(mlist,t->t_reserved);
1099
1100 if (item != NULL)
1101 {
1102 tp = THINGPTR(item);
1103 t->t_dest = &tp->t_pos;
1104 }
1105 }
1106
1107 void
1108 rs_write_thing_list(FILE *savef, struct linked_list *l)
1109 {
1110 int cnt = 0;
1111
1112 rs_write_marker(savef, RSID_MONSTERLIST);
1113
1114 cnt = list_size(l);
1115
1116 rs_write_int(savef, cnt);
1117
1118 if (cnt < 1)
1119 return;
1120
1121 while (l != NULL) {
1122 rs_write_thing(savef, (struct thing *)l->l_data);
1123 l = l->l_next;
1124 }
1125 }
1126
1127 void
1128 rs_read_thing_list(FILE *savef, struct linked_list **list)
1129 {
1130 int i, cnt;
1131 struct linked_list *l = NULL, *previous = NULL, *head = NULL;
1132
1133 rs_read_marker(savef, RSID_MONSTERLIST);
1134 rs_read_int(savef, &cnt);
1135
1136 if (encerror())
1137 return;
1138
1139 for (i = 0; i < cnt; i++)
1140 {
1141 l = new_item(sizeof(struct thing));
1142
1143 l->l_prev = previous;
1144
1145 if (previous != NULL)
1146 previous->l_next = l;
1147
1148 rs_read_thing(savef,(struct thing *)l->l_data);
1149
1150 if (previous == NULL)
1151 head = l;
1152
1153 previous = l;
1154 }
1155
1156 if (l != NULL)
1157 l->l_next = NULL;
1158
1159 *list = head;
1160 }
1161
1162 void
1163 rs_fix_thing_list(struct linked_list *list)
1164 {
1165 struct linked_list *item;
1166
1167 for(item = list; item != NULL; item = item->l_next)
1168 rs_fix_thing(THINGPTR(item));
1169 }
1170
1171 void
1172 rs_fix_magic_items(struct magic_item *mi, int cnt)
1173 {
1174 int i;
1175
1176 for (i = 0; i < cnt; i++)
1177 if (i > 0)
1178 mi[i].mi_prob += mi[i-1].mi_prob;
1179 }
1180
1181 void
1182 rs_fix_monsters(struct monster mons[26])
1183 {
1184 sprintf(mons['F'-'A'].m_stats.s_dmg,"%dd1",fung_hit);
1185 }
1186
1187 void
1188 rs_write_trap(FILE *savef, struct trap *trap)
1189 {
1190 rs_write_coord(savef, trap->tr_pos);
1191 rs_write_int(savef, trap->tr_type);
1192 rs_write_int(savef, trap->tr_flags);
1193 }
1194
1195 void
1196 rs_read_trap(FILE *savef, struct trap *trap)
1197 {
1198 rs_read_coord(savef,&trap->tr_pos);
1199 rs_read_int(savef,&trap->tr_type);
1200 rs_read_int(savef,&trap->tr_flags);
1201 }
1202
1203 void
1204 rs_write_traps(FILE *savef, struct trap t[], int cnt)
1205 {
1206 int n = 0;
1207
1208 rs_write_marker(savef, RSID_MONSTERS);
1209 rs_write_int(savef, cnt);
1210
1211 for(n = 0; n < cnt; n++)
1212 rs_write_trap(savef, &t[n]);
1213 }
1214
1215 void
1216 rs_read_traps(FILE *savef, struct trap *t, int cnt)
1217 {
1218 int value = 0, n = 0;
1219
1220 rs_read_marker(savef, RSID_MONSTERS);
1221
1222 rs_read_int(savef,&value);
1223
1224 if (!encerror() && (value > cnt))
1225 encseterr(EILSEQ);
1226
1227 for(n = 0; n < value; n++)
1228 rs_read_trap(savef,&t[n]);
1229 }
1230
1231 int
1232 rs_save_file(FILE *savef)
1233 {
1234 encclearerr();
1235
1236 rs_write_thing(savef, &player);
1237 rs_write_object_list(savef, lvl_obj);
1238 rs_write_thing_list(savef, mlist);
1239 rs_write_traps(savef, traps, MAXTRAPS);
1240 rs_write_rooms(savef, rooms, MAXROOMS);
1241 rs_write_room_reference(savef, oldrp);
1242 rs_write_stats(savef,&max_stats);
1243 rs_write_object_reference(savef, player.t_pack, cur_weapon);
1244 rs_write_object_reference(savef, player.t_pack, cur_armor);
1245 rs_write_object_reference(savef, player.t_pack, cur_ring[0]);
1246 rs_write_object_reference(savef, player.t_pack, cur_ring[1]);
1247 rs_write_int(savef, level);
1248 rs_write_int(savef, purse);
1249 rs_write_int(savef, mpos);
1250 rs_write_int(savef, ntraps);
1251 rs_write_int(savef, no_move);
1252 rs_write_int(savef, no_command);
1253 rs_write_int(savef, inpack);
1254 rs_write_int(savef, max_hp);
1255 rs_write_int(savef, total);
1256 rs_write_int(savef, lastscore);
1257 rs_write_int(savef, no_food);
1258 rs_write_int(savef, seed);
1259 rs_write_int(savef, count);
1260 rs_write_int(savef, dnum);
1261 rs_write_int(savef, fung_hit);
1262 rs_write_int(savef, quiet);
1263 rs_write_int(savef, max_level);
1264 rs_write_int(savef, food_left);
1265 rs_write_int(savef, group);
1266 rs_write_int(savef, hungry_state);
1267 rs_write_int(savef, take);
1268 rs_write_int(savef, runch);
1269 rs_write_scrolls(savef);
1270 rs_write_potions(savef);
1271 rs_write_rings(savef);
1272 rs_write_sticks(savef);
1273 rs_write_chars(savef,whoami,80);
1274 rs_write_chars(savef,fruit,80);
1275 rs_write_window(savef, cw);
1276 rs_write_window(savef, mw);
1277 rs_write_window(savef, stdscr);
1278 rs_write_int(savef, running);
1279 rs_write_int(savef, playing);
1280 rs_write_int(savef, wizard);
1281 rs_write_int(savef, after);
1282 rs_write_int(savef, notify);
1283 rs_write_int(savef, fight_flush);
1284 rs_write_int(savef, terse);
1285 rs_write_int(savef, door_stop);
1286 rs_write_int(savef, jump);
1287 rs_write_int(savef, slow_invent);
1288 rs_write_int(savef, firstmove);
1289 rs_write_int(savef, waswizard);
1290 rs_write_int(savef, askme);
1291 rs_write_int(savef, amulet);
1292 rs_write_int(savef, in_shell);
1293 rs_write_coord(savef, oldpos);
1294 rs_write_coord(savef, delta);
1295 rs_write_coord(savef, ch_ret); /* chase.c */
1296 rs_write_daemons(savef, &d_list[0], 20); /* daemon.c */
1297 rs_write_int(savef,between); /* daemons.c */
1298 rs_write_int(savef,num_checks); /* main.c */
1299 rs_write_chars(savef,lvl_mons,sizeof(lvl_mons)); /* monsters.c */
1300 rs_write_chars(savef,wand_mons,sizeof(wand_mons)); /* monsters.c */
1301
1302 return( encclearerr() );
1303 }
1304
1305 int
1306 rs_restore_file(FILE *savef)
1307 {
1308 encclearerr();
1309
1310 rs_read_thing(savef, &player);
1311 rs_read_object_list(savef, &lvl_obj);
1312 rs_read_thing_list(savef, &mlist);
1313 rs_fix_thing(&player);
1314 rs_fix_thing_list(mlist);
1315 rs_read_traps(savef, traps, MAXTRAPS);
1316 rs_read_rooms(savef, rooms, MAXROOMS);
1317 rs_read_room_reference(savef, &oldrp);
1318 rs_read_stats(savef,&max_stats);
1319 rs_read_object_reference(savef, player.t_pack, &cur_weapon);
1320 rs_read_object_reference(savef, player.t_pack, &cur_armor);
1321 rs_read_object_reference(savef, player.t_pack, &cur_ring[0]);
1322 rs_read_object_reference(savef, player.t_pack, &cur_ring[1]);
1323 rs_fix_magic_items(things,NUMTHINGS);
1324 rs_fix_magic_items(s_magic,MAXSCROLLS);
1325 rs_fix_magic_items(p_magic,MAXPOTIONS);
1326 rs_fix_magic_items(r_magic,MAXRINGS);
1327 rs_fix_magic_items(ws_magic,MAXSTICKS);
1328 rs_read_int(savef, &level);
1329 rs_read_int(savef, &purse);
1330 rs_read_int(savef, &mpos);
1331 rs_read_int(savef, &ntraps);
1332 rs_read_int(savef, &no_move);
1333 rs_read_int(savef, &no_command);
1334 rs_read_int(savef, &inpack);
1335 rs_read_int(savef, &max_hp);
1336 rs_read_int(savef, &total);
1337 rs_read_int(savef, &lastscore);
1338 rs_read_int(savef, &no_food);
1339 rs_read_int(savef, &seed);
1340 rs_read_int(savef, &count);
1341 rs_read_int(savef, &dnum);
1342 rs_read_int(savef, &fung_hit);
1343 rs_read_int(savef, &quiet);
1344 rs_read_int(savef, &max_level);
1345 rs_read_int(savef, &food_left);
1346 rs_read_int(savef, &group);
1347 rs_read_int(savef, &hungry_state);
1348 rs_read_int(savef, &take);
1349 rs_read_int(savef, &runch);
1350 rs_read_scrolls(savef);
1351 rs_read_potions(savef);
1352 rs_read_rings(savef);
1353 rs_read_sticks(savef);
1354 rs_read_chars(savef,whoami,80);
1355 rs_read_chars(savef,fruit,80);
1356 rs_read_window(savef, cw);
1357 rs_read_window(savef, mw);
1358 rs_read_window(savef, stdscr);
1359 rs_read_int(savef, &running);
1360 rs_read_int(savef, &playing);
1361 rs_read_int(savef, &wizard);
1362 rs_read_int(savef, &after);
1363 rs_read_int(savef, &notify);
1364 rs_read_int(savef, &fight_flush);
1365 rs_read_int(savef, &terse);
1366 rs_read_int(savef, &door_stop);
1367 rs_read_int(savef, &jump);
1368 rs_read_int(savef, &slow_invent);
1369 rs_read_int(savef, &firstmove);
1370 rs_read_int(savef, &waswizard);
1371 rs_read_int(savef, &askme);
1372 rs_read_int(savef, &amulet);
1373 rs_read_int(savef, &in_shell);
1374 rs_read_coord(savef,&oldpos);
1375 rs_read_coord(savef,&delta);
1376 rs_read_coord(savef, &ch_ret); /* chase.c */
1377 rs_read_daemons(savef, d_list, 20); /* daemon.c */
1378 rs_read_int(savef,&between); /* daemons.c */
1379 rs_read_int(savef,&num_checks); /* main.c */
1380 rs_read_chars(savef, lvl_mons, sizeof(lvl_mons)); /* monsters.c */
1381 rs_read_chars(savef, wand_mons, sizeof(wand_mons)); /* monsters.c */
1382 rs_fix_monsters(monsters);
1383
1384 return( encclearerr() );
1385 }