comparison rogue5/state.c @ 33:f502bf60e6e4

Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author elwin
date Mon, 24 May 2010 20:10:59 +0000
parents
children 09db0cf536af
comparison
equal deleted inserted replaced
32:2dcd75e6a736 33:f502bf60e6e4
1 /*
2 state.c - Portable Rogue Save State Code
3
4 Copyright (C) 1999, 2000, 2005 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, const char *master[], int max, const 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, const char *master[], int maxindex, const 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_window(FILE *savef, WINDOW *win)
340 {
341 int row,col,height,width;
342
343 width = getmaxx(win);
344 height = getmaxy(win);
345
346 rs_write_marker(savef,RSID_WINDOW);
347 rs_write_int(savef,height);
348 rs_write_int(savef,width);
349
350 for(row=0;row<height;row++)
351 for(col=0;col<width;col++)
352 rs_write_int(savef, mvwinch(win,row,col));
353 }
354
355 void
356 rs_read_window(FILE *savef, WINDOW *win)
357 {
358 int row,col,maxlines,maxcols,value,width,height;
359
360 width = getmaxx(win);
361 height = getmaxy(win);
362
363 rs_read_marker(savef, RSID_WINDOW);
364
365 rs_read_int(savef, &maxlines);
366 rs_read_int(savef, &maxcols);
367
368 if (encerror())
369 return;
370
371 for(row = 0; row < maxlines; row++)
372 for(col = 0; col < maxcols; col++)
373 {
374 rs_read_int(savef, &value);
375
376 if ((row < height) && (col < width))
377 mvwaddch(win,row,col,value);
378 }
379 }
380
381 /******************************************************************************/
382
383 void *
384 get_list_item(THING *l, int i)
385 {
386 int cnt;
387
388 for(cnt = 0; l != NULL; cnt++, l = l->l_next)
389 if (cnt == i)
390 return(l);
391
392 return(NULL);
393 }
394
395 int
396 find_list_ptr(THING *l, void *ptr)
397 {
398 int cnt;
399
400 for(cnt = 0; l != NULL; cnt++, l = l->l_next)
401 if (l == ptr)
402 return(cnt);
403
404 return(-1);
405 }
406
407 int
408 list_size(THING *l)
409 {
410 int cnt;
411
412 for(cnt = 0; l != NULL; cnt++, l = l->l_next)
413 ;
414
415 return(cnt);
416 }
417
418 /******************************************************************************/
419
420 void
421 rs_write_stats(FILE *savef, struct stats *s)
422 {
423 rs_write_marker(savef, RSID_STATS);
424 rs_write_int(savef, s->s_str);
425 rs_write_int(savef, s->s_exp);
426 rs_write_int(savef, s->s_lvl);
427 rs_write_int(savef, s->s_arm);
428 rs_write_int(savef, s->s_hpt);
429 rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg));
430 rs_write_int(savef,s->s_maxhp);
431 }
432
433 void
434 rs_read_stats(FILE *savef, struct stats *s)
435 {
436 rs_read_marker(savef, RSID_STATS);
437 rs_read_int(savef,&s->s_str);
438 rs_read_int(savef,&s->s_exp);
439 rs_read_int(savef,&s->s_lvl);
440 rs_read_int(savef,&s->s_arm);
441 rs_read_int(savef,&s->s_hpt);
442 rs_read_chars(savef,s->s_dmg,sizeof(s->s_dmg));
443 rs_read_int(savef,&s->s_maxhp);
444 }
445
446 void
447 rs_write_stone_index(FILE *savef, const STONE master[], int max, const char *str)
448 {
449 int i;
450
451 for(i = 0; i < max; i++)
452 if (str == master[i].st_name)
453 {
454 rs_write_int(savef,i);
455 return;
456 }
457
458 rs_write_int(savef,-1);
459 }
460
461 void
462 rs_read_stone_index(FILE *savef, const STONE master[], int maxindex, const char **str)
463 {
464 int i = 0;
465
466 rs_read_int(savef,&i);
467
468 if (!encerror() && (i > maxindex))
469 encseterr(EILSEQ);
470 else if (i >= 0)
471 *str = master[i].st_name;
472 else
473 *str = NULL;
474 }
475
476 void
477 rs_write_scrolls(FILE *savef)
478 {
479 int i;
480
481 for(i = 0; i < MAXSCROLLS; i++)
482 rs_write_string(savef, s_names[i]);
483 }
484
485 void
486 rs_read_scrolls(FILE *savef)
487 {
488 int i;
489
490 for(i = 0; i < MAXSCROLLS; i++)
491 rs_read_new_string(savef, &s_names[i]);
492 }
493
494 void
495 rs_write_potions(FILE *savef)
496 {
497 int i;
498
499 for(i = 0; i < MAXPOTIONS; i++)
500 rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]);
501 }
502
503 void
504 rs_read_potions(FILE *savef)
505 {
506 int i;
507
508 for(i = 0; i < MAXPOTIONS; i++)
509 rs_read_string_index(savef, rainbow, cNCOLORS, &p_colors[i]);
510 }
511
512 void
513 rs_write_rings(FILE *savef)
514 {
515 int i;
516
517 for(i = 0; i < MAXRINGS; i++)
518 rs_write_stone_index(savef, stones, cNSTONES, r_stones[i]);
519 }
520
521 void
522 rs_read_rings(FILE *savef)
523 {
524 int i;
525
526 for(i = 0; i < MAXRINGS; i++)
527 rs_read_stone_index(savef, stones, cNSTONES, &r_stones[i]);
528 }
529
530 void
531 rs_write_sticks(FILE *savef)
532 {
533 int i;
534
535 for (i = 0; i < MAXSTICKS; i++)
536 {
537 if (strcmp(ws_type[i],"staff") == 0)
538 {
539 rs_write_int(savef,0);
540 rs_write_string_index(savef, wood, cNWOOD, ws_made[i]);
541 }
542 else
543 {
544 rs_write_int(savef,1);
545 rs_write_string_index(savef, metal, cNMETAL, ws_made[i]);
546 }
547 }
548 }
549
550 void
551 rs_read_sticks(FILE *savef)
552 {
553 int i = 0, list = 0;
554
555 for(i = 0; i < MAXSTICKS; i++)
556 {
557 rs_read_int(savef,&list);
558
559 if (list == 0)
560 {
561 rs_read_string_index(savef, wood, cNWOOD, &ws_made[i]);
562 ws_type[i] = "staff";
563 }
564 else
565 {
566 rs_read_string_index(savef, metal, cNMETAL, &ws_made[i]);
567 ws_type[i] = "wand";
568 }
569 }
570 }
571
572 void
573 rs_write_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
574 {
575 int i = 0;
576 int func = 0;
577
578 rs_write_marker(savef, RSID_DAEMONS);
579 rs_write_int(savef, cnt);
580
581 for(i = 0; i < cnt; i++)
582 {
583 if (dlist[i].d_func == rollwand)
584 func = 1;
585 else if (dlist[i].d_func == doctor)
586 func = 2;
587 else if (dlist[i].d_func == stomach)
588 func = 3;
589 else if (dlist[i].d_func == runners)
590 func = 4;
591 else if (dlist[i].d_func == swander)
592 func = 5;
593 else if (dlist[i].d_func == nohaste)
594 func = 6;
595 else if (dlist[i].d_func == unconfuse)
596 func = 7;
597 else if (dlist[i].d_func == unsee)
598 func = 8;
599 else if (dlist[i].d_func == sight)
600 func = 9;
601 else if (dlist[i].d_func == NULL)
602 func = 0;
603 else
604 func = -1;
605
606 rs_write_int(savef, dlist[i].d_type);
607 rs_write_int(savef, func);
608 rs_write_int(savef, dlist[i].d_arg);
609 rs_write_int(savef, dlist[i].d_time);
610 }
611 }
612
613 void
614 rs_read_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
615 {
616 int i = 0;
617 int func = 0;
618 int value = 0;
619
620 rs_read_marker(savef, RSID_DAEMONS);
621 rs_read_int(savef, &value);
622
623 if (!encerror() && (value > cnt))
624 {
625 encseterr(EILSEQ);
626 return;
627 }
628
629 for(i=0; i < cnt; i++)
630 {
631 func = 0;
632 rs_read_int(savef, &dlist[i].d_type);
633 rs_read_int(savef, &func);
634 rs_read_int(savef, &dlist[i].d_arg);
635 rs_read_int(savef, &dlist[i].d_time);
636
637 if (encerror())
638 return;
639
640 switch(func)
641 {
642 case 1: dlist[i].d_func = rollwand;
643 break;
644 case 2: dlist[i].d_func = doctor;
645 break;
646 case 3: dlist[i].d_func = stomach;
647 break;
648 case 4: dlist[i].d_func = runners;
649 break;
650 case 5: dlist[i].d_func = swander;
651 break;
652 case 6: dlist[i].d_func = nohaste;
653 break;
654 case 7: dlist[i].d_func = unconfuse;
655 break;
656 case 8: dlist[i].d_func = unsee;
657 break;
658 case 9: dlist[i].d_func = sight;
659 break;
660 default:dlist[i].d_func = NULL;
661 break;
662 }
663 }
664
665 if (dlist[i].d_func == NULL)
666 {
667 dlist[i].d_type = 0;
668 dlist[i].d_arg = 0;
669 dlist[i].d_time = 0;
670 }
671 }
672
673 void
674 rs_write_obj_info(FILE *savef, struct obj_info *i, int cnt)
675 {
676 int n;
677
678 rs_write_marker(savef, RSID_MAGICITEMS);
679 rs_write_int(savef, cnt);
680
681 for(n = 0; n < cnt; n++)
682 {
683 /* oi_name is constant, defined at compile time in all cases */
684 rs_write_int(savef,i[n].oi_prob);
685 rs_write_int(savef,i[n].oi_worth);
686 rs_write_string(savef,i[n].oi_guess);
687 rs_write_int(savef,i[n].oi_know);
688 }
689 }
690
691 void
692 rs_read_obj_info(FILE *savef, struct obj_info *mi, int cnt)
693 {
694 int n;
695 int value;
696
697 rs_read_marker(savef, RSID_MAGICITEMS);
698
699 rs_read_int(savef, &value);
700
701 if (!encerror() && (value > cnt))
702 {
703 encseterr(EILSEQ);
704 return;
705 }
706
707 for(n = 0; n < value; n++)
708 {
709 /* mi_name is const, defined at compile time in all cases */
710 rs_read_int(savef,&mi[n].oi_prob);
711 rs_read_int(savef,&mi[n].oi_worth);
712 rs_read_new_string(savef,&mi[n].oi_guess);
713 rs_read_int(savef,&mi[n].oi_know);
714 }
715 }
716
717 void
718 rs_write_room(FILE *savef, struct room *r)
719 {
720 rs_write_coord(savef, r->r_pos);
721 rs_write_coord(savef, r->r_max);
722 rs_write_coord(savef, r->r_gold);
723 rs_write_int(savef, r->r_goldval);
724 rs_write_int(savef, r->r_flags);
725 rs_write_int(savef, r->r_nexits);
726 rs_write_coord(savef, r->r_exit[0]);
727 rs_write_coord(savef, r->r_exit[1]);
728 rs_write_coord(savef, r->r_exit[2]);
729 rs_write_coord(savef, r->r_exit[3]);
730 rs_write_coord(savef, r->r_exit[4]);
731 rs_write_coord(savef, r->r_exit[5]);
732 rs_write_coord(savef, r->r_exit[6]);
733 rs_write_coord(savef, r->r_exit[7]);
734 rs_write_coord(savef, r->r_exit[8]);
735 rs_write_coord(savef, r->r_exit[9]);
736 rs_write_coord(savef, r->r_exit[10]);
737 rs_write_coord(savef, r->r_exit[11]);
738 }
739
740 void
741 rs_read_room(FILE *savef, struct room *r)
742 {
743 rs_read_coord(savef,&r->r_pos);
744 rs_read_coord(savef,&r->r_max);
745 rs_read_coord(savef,&r->r_gold);
746 rs_read_int(savef,&r->r_goldval);
747 rs_read_int(savef,&r->r_flags);
748 rs_read_int(savef,&r->r_nexits);
749 rs_read_coord(savef,&r->r_exit[0]);
750 rs_read_coord(savef,&r->r_exit[1]);
751 rs_read_coord(savef,&r->r_exit[2]);
752 rs_read_coord(savef,&r->r_exit[3]);
753 rs_read_coord(savef,&r->r_exit[4]);
754 rs_read_coord(savef,&r->r_exit[5]);
755 rs_read_coord(savef,&r->r_exit[6]);
756 rs_read_coord(savef,&r->r_exit[7]);
757 rs_read_coord(savef,&r->r_exit[8]);
758 rs_read_coord(savef,&r->r_exit[9]);
759 rs_read_coord(savef,&r->r_exit[10]);
760 rs_read_coord(savef,&r->r_exit[11]);
761 }
762
763 void
764 rs_write_rooms(FILE *savef, struct room r[], int cnt)
765 {
766 int n = 0;
767
768 rs_write_int(savef, cnt);
769
770 for(n = 0; n < cnt; n++)
771 rs_write_room(savef, &r[n]);
772 }
773
774 void
775 rs_read_rooms(FILE *savef, struct room *r, int cnt)
776 {
777 int value = 0, n = 0;
778
779 rs_read_int(savef,&value);
780
781 if (!encerror() && (value > cnt))
782 encseterr(EILSEQ);
783 else
784 for(n = 0; n < value; n++)
785 rs_read_room(savef,&r[n]);
786 }
787
788 void
789 rs_write_room_reference(FILE *savef, struct room *rp)
790 {
791 int i, room = -1;
792
793 for (i = 0; i < MAXROOMS; i++)
794 if (&rooms[i] == rp)
795 room = i;
796
797 rs_write_int(savef, room);
798 }
799
800 void
801 rs_read_room_reference(FILE *savef, struct room **rp)
802 {
803 int i;
804
805 rs_read_int(savef, &i);
806
807 if (!encerror())
808 *rp = &rooms[i];
809 }
810
811 void
812 rs_write_monsters(FILE *savef, struct monster *m, int cnt)
813 {
814 int n;
815
816 rs_write_marker(savef, RSID_MONSTERS);
817 rs_write_int(savef, cnt);
818
819 for(n=0;n<cnt;n++)
820 rs_write_stats(savef, &m[n].m_stats);
821 }
822
823 void
824 rs_read_monsters(FILE *savef, struct monster *m, int cnt)
825 {
826 int value = 0, n = 0;
827
828 rs_read_marker(savef, RSID_MONSTERS);
829
830 rs_read_int(savef, &value);
831
832 if (!encerror() && (value != cnt))
833 encseterr(EILSEQ);
834 else
835 for(n = 0; n < cnt; n++)
836 rs_read_stats(savef, &m[n].m_stats);
837 }
838
839 void
840 rs_write_object(FILE *savef, THING *o)
841 {
842 rs_write_marker(savef, RSID_OBJECT);
843 rs_write_int(savef, o->_o._o_type);
844 rs_write_coord(savef, o->_o._o_pos);
845 rs_write_int(savef, o->_o._o_launch);
846 rs_write_int(savef, o->_o._o_packch);
847 rs_write_chars(savef, o->_o._o_damage, sizeof(o->_o._o_damage));
848 rs_write_chars(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg));
849 rs_write_int(savef, o->_o._o_count);
850 rs_write_int(savef, o->_o._o_which);
851 rs_write_int(savef, o->_o._o_hplus);
852 rs_write_int(savef, o->_o._o_dplus);
853 rs_write_int(savef, o->_o._o_arm);
854 rs_write_int(savef, o->_o._o_flags);
855 rs_write_int(savef, o->_o._o_group);
856 rs_write_string(savef, o->_o._o_label);
857 }
858
859 void
860 rs_read_object(FILE *savef, THING *o)
861 {
862 rs_read_marker(savef, RSID_OBJECT);
863 rs_read_int(savef, &o->_o._o_type);
864 rs_read_coord(savef, &o->_o._o_pos);
865 rs_read_int(savef, &o->_o._o_launch);
866 rs_read_int(savef, &o->_o._o_packch);
867 rs_read_chars(savef, o->_o._o_damage, sizeof(o->_o._o_damage));
868 rs_read_chars(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg));
869 rs_read_int(savef, &o->_o._o_count);
870 rs_read_int(savef, &o->_o._o_which);
871 rs_read_int(savef, &o->_o._o_hplus);
872 rs_read_int(savef, &o->_o._o_dplus);
873 rs_read_int(savef, &o->_o._o_arm);
874 rs_read_int(savef, &o->_o._o_flags);
875 rs_read_int(savef, &o->_o._o_group);
876 rs_read_new_string(savef, &o->_o._o_label);
877 }
878
879 void
880 rs_write_object_list(FILE *savef, THING *l)
881 {
882 rs_write_marker(savef, RSID_OBJECTLIST);
883 rs_write_int(savef, list_size(l));
884
885 for( ;l != NULL; l = l->l_next)
886 rs_write_object(savef, l);
887 }
888
889 void
890 rs_read_object_list(FILE *savef, THING **list)
891 {
892 int i, cnt;
893 THING *l = NULL, *previous = NULL, *head = NULL;
894
895 rs_read_marker(savef, RSID_OBJECTLIST);
896 rs_read_int(savef, &cnt);
897
898 if (encerror())
899 return;
900
901 for (i = 0; i < cnt; i++)
902 {
903 l = new_item();
904
905 l->l_prev = previous;
906
907 if (previous != NULL)
908 previous->l_next = l;
909
910 rs_read_object(savef,l);
911
912 if (previous == NULL)
913 head = l;
914
915 previous = l;
916 }
917
918 if (l != NULL)
919 l->l_next = NULL;
920
921 *list = head;
922 }
923
924 void
925 rs_write_object_reference(FILE *savef, THING *list, THING *item)
926 {
927 int i;
928
929 i = find_list_ptr(list, item);
930
931 rs_write_int(savef, i);
932 }
933
934 void
935 rs_read_object_reference(FILE *savef, THING *list, THING **item)
936 {
937 int i;
938
939 rs_read_int(savef, &i);
940
941 if (!encerror())
942 *item = get_list_item(list,i);
943 else
944 *item = NULL;
945 }
946
947 int
948 find_room_coord(const struct room *rmlist,const coord *c, int n)
949 {
950 int i = 0;
951
952 for(i = 0; i < n; i++)
953 if(&rmlist[i].r_gold == c)
954 return(i);
955
956 return(-1);
957 }
958
959 int
960 find_thing_coord(THING *monlist, const coord *c)
961 {
962 THING *mitem;
963 THING *tp;
964 int i = 0;
965
966 for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
967 {
968 tp = mitem;
969
970 if (c == &tp->t_pos)
971 return(i);
972
973 i++;
974 }
975
976 return(-1);
977 }
978
979 int
980 find_object_coord(THING *objlist, const coord *c)
981 {
982 THING *oitem;
983 THING *obj;
984 int i = 0;
985
986 for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
987 {
988 obj = oitem;
989
990 if (c == &obj->o_pos)
991 return(i);
992
993 i++;
994 }
995
996 return(-1);
997 }
998
999 void
1000 rs_write_thing(FILE *savef, THING *t)
1001 {
1002 int i = -1;
1003
1004 rs_write_marker(savef, RSID_THING);
1005
1006 if (t == NULL)
1007 {
1008 rs_write_int(savef, 0);
1009 return;
1010 }
1011
1012 rs_write_int(savef, 1);
1013 rs_write_coord(savef, t->_t._t_pos);
1014 rs_write_int(savef, t->_t._t_turn);
1015 rs_write_int(savef, t->_t._t_type);
1016 rs_write_int(savef, t->_t._t_disguise);
1017 rs_write_int(savef, t->_t._t_oldch);
1018
1019 /*
1020 t_dest can be:
1021 0,0: NULL
1022 0,1: location of hero
1023 1,i: location of a thing (monster)
1024 2,i: location of an object
1025 3,i: location of gold in a room
1026
1027 We need to remember what we are chasing rather than
1028 the current location of what we are chasing.
1029 */
1030
1031 if (t->t_dest == &hero)
1032 {
1033 rs_write_int(savef,0);
1034 rs_write_int(savef,1);
1035 }
1036 else if (t->t_dest != NULL)
1037 {
1038 i = find_thing_coord(mlist, t->t_dest);
1039
1040 if (i >=0 )
1041 {
1042 rs_write_int(savef,1);
1043 rs_write_int(savef,i);
1044 }
1045 else
1046 {
1047 i = find_object_coord(lvl_obj, t->t_dest);
1048
1049 if (i >= 0)
1050 {
1051 rs_write_int(savef,2);
1052 rs_write_int(savef,i);
1053 }
1054 else
1055 {
1056 i = find_room_coord(rooms, t->t_dest, MAXROOMS);
1057
1058 if (i >= 0)
1059 {
1060 rs_write_int(savef,3);
1061 rs_write_int(savef,i);
1062 }
1063 else
1064 {
1065 rs_write_int(savef, 0);
1066 rs_write_int(savef,1); /* chase the hero anyway */
1067 }
1068 }
1069 }
1070 }
1071 else
1072 {
1073 rs_write_int(savef,0);
1074 rs_write_int(savef,0);
1075 }
1076
1077 rs_write_int(savef, t->_t._t_flags);
1078 rs_write_stats(savef, &t->_t._t_stats);
1079 rs_write_room_reference(savef, t->_t._t_room);
1080 rs_write_object_list(savef, t->_t._t_pack);
1081 }
1082
1083 void
1084 rs_read_thing(FILE *savef, THING *t)
1085 {
1086 int listid = 0, index = -1;
1087 THING *item;
1088
1089 rs_read_marker(savef, RSID_THING);
1090 rs_read_int(savef, &index);
1091
1092 if (encerror())
1093 return;
1094
1095 if (index == 0)
1096 return;
1097
1098 rs_read_coord(savef,&t->_t._t_pos);
1099 rs_read_int(savef,&t->_t._t_turn);
1100 rs_read_int(savef,&t->_t._t_type);
1101 rs_read_int(savef,&t->_t._t_disguise);
1102 rs_read_int(savef,&t->_t._t_oldch);
1103
1104 /*
1105 t_dest can be (listid,index):
1106 0,0: NULL
1107 0,1: location of hero
1108 1,i: location of a thing (monster)
1109 2,i: location of an object
1110 3,i: location of gold in a room
1111
1112 We need to remember what we are chasing rather than
1113 the current location of what we are chasing.
1114 */
1115
1116 rs_read_int(savef, &listid);
1117 rs_read_int(savef, &index);
1118 t->_t._t_reserved = -1;
1119
1120 if (encerror())
1121 return;
1122
1123 if (listid == 0) /* hero or NULL */
1124 {
1125 if (index == 1)
1126 t->_t._t_dest = &hero;
1127 else
1128 t->_t._t_dest = NULL;
1129 }
1130 else if (listid == 1) /* monster/thing */
1131 {
1132 t->_t._t_dest = NULL;
1133 t->_t._t_reserved = index;
1134 }
1135 else if (listid == 2) /* object */
1136 {
1137 THING *obj;
1138
1139 item = get_list_item(lvl_obj, index);
1140
1141 if (item != NULL)
1142 {
1143 obj = item;
1144 t->_t._t_dest = &obj->o_pos;
1145 }
1146 }
1147 else if (listid == 3) /* gold */
1148 {
1149 t->_t._t_dest = &rooms[index].r_gold;
1150 }
1151 else
1152 t->_t._t_dest = NULL;
1153
1154 rs_read_int(savef,&t->_t._t_flags);
1155 rs_read_stats(savef,&t->_t._t_stats);
1156 rs_read_room_reference(savef, &t->_t._t_room);
1157 rs_read_object_list(savef,&t->_t._t_pack);
1158 }
1159
1160 void
1161 rs_fix_thing(THING *t)
1162 {
1163 THING *item;
1164 THING *tp;
1165
1166 if (t->t_reserved < 0)
1167 return;
1168
1169 item = get_list_item(mlist,t->t_reserved);
1170
1171 if (item != NULL)
1172 {
1173 tp = item;
1174 t->t_dest = &tp->t_pos;
1175 }
1176 }
1177
1178 void
1179 rs_write_thing_list(FILE *savef, THING *l)
1180 {
1181 int cnt = 0;
1182
1183 rs_write_marker(savef, RSID_MONSTERLIST);
1184
1185 cnt = list_size(l);
1186
1187 rs_write_int(savef, cnt);
1188
1189 if (cnt < 1)
1190 return;
1191
1192 while (l != NULL) {
1193 rs_write_thing(savef, l);
1194 l = l->l_next;
1195 }
1196 }
1197
1198 void
1199 rs_read_thing_list(FILE *savef, THING **list)
1200 {
1201 int i, cnt;
1202 THING *l = NULL, *previous = NULL, *head = NULL;
1203
1204 rs_read_marker(savef, RSID_MONSTERLIST);
1205 rs_read_int(savef, &cnt);
1206
1207 if (encerror())
1208 return;
1209
1210 for (i = 0; i < cnt; i++)
1211 {
1212 l = new_item();
1213
1214 l->l_prev = previous;
1215
1216 if (previous != NULL)
1217 previous->l_next = l;
1218
1219 rs_read_thing(savef,l);
1220
1221 if (previous == NULL)
1222 head = l;
1223
1224 previous = l;
1225 }
1226
1227 if (l != NULL)
1228 l->l_next = NULL;
1229
1230 *list = head;
1231 }
1232
1233 void
1234 rs_fix_thing_list(THING *list)
1235 {
1236 THING *item;
1237
1238 for(item = list; item != NULL; item = item->l_next)
1239 rs_fix_thing(item);
1240 }
1241
1242 void
1243 rs_write_thing_reference(FILE *savef, THING *list, THING *item)
1244 {
1245 int i;
1246
1247 if (item == NULL)
1248 rs_write_int(savef,-1);
1249 else
1250 {
1251 i = find_list_ptr(list, item);
1252
1253 rs_write_int(savef, i);
1254 }
1255 }
1256
1257 void
1258 rs_read_thing_reference(FILE *savef, THING *list, THING **item)
1259 {
1260 int i;
1261
1262 rs_read_int(savef, &i);
1263
1264 if (encerror())
1265 return;
1266
1267 if (i == -1)
1268 *item = NULL;
1269 else
1270 *item = get_list_item(list,i);
1271
1272 }
1273
1274 void
1275 rs_write_thing_references(FILE *savef, THING *list, THING *items[], int cnt)
1276 {
1277 int i;
1278
1279 for(i = 0; i < cnt; i++)
1280 rs_write_thing_reference(savef,list,items[i]);
1281 }
1282
1283 void
1284 rs_read_thing_references(FILE *savef, THING *list, THING *items[], int cnt)
1285 {
1286 int i;
1287
1288 for(i = 0; i < cnt; i++)
1289 rs_read_thing_reference(savef,list,&items[i]);
1290 }
1291
1292 void
1293 rs_write_places(FILE *savef, PLACE *p, int cnt)
1294 {
1295 int i = 0;
1296
1297 for(i = 0; i < cnt; i++)
1298 {
1299 rs_write_int(savef, p[i].p_ch);
1300 rs_write_int(savef, p[i].p_flags);
1301 rs_write_thing_reference(savef, mlist, p[i].p_monst);
1302 }
1303 }
1304
1305 void
1306 rs_read_places(FILE *savef, PLACE *p, int cnt)
1307 {
1308 int i = 0;
1309
1310 for(i = 0; i < cnt; i++)
1311 {
1312 rs_read_int(savef,&p[i].p_ch);
1313 rs_read_int(savef,&p[i].p_flags);
1314 rs_read_thing_reference(savef, mlist, &p[i].p_monst);
1315 }
1316 }
1317
1318 int
1319 rs_save_file(FILE *savef)
1320 {
1321 encclearerr();
1322
1323 rs_write_int(savef, noscore);
1324 rs_write_int(savef, seenstairs);
1325 rs_write_int(savef, amulet);
1326 rs_write_int(savef, fight_flush);
1327 rs_write_int(savef, jump);
1328 rs_write_int(savef, passgo);
1329 rs_write_int(savef, see_floor);
1330 rs_write_int(savef, terse);
1331 rs_write_int(savef, tombstone);
1332 rs_write_ints(savef, pack_used, 26);
1333 rs_write_chars(savef, file_name, MAXSTR);
1334 rs_write_chars(savef, huh, MAXSTR);
1335 rs_write_potions(savef);
1336 rs_write_rings(savef);
1337 rs_write_scrolls(savef);
1338 rs_write_chars(savef, whoami, MAXSTR);
1339 rs_write_sticks(savef);
1340 rs_write_chars(savef, fruit, MAXSTR);
1341 rs_write_int(savef,n_objs);
1342 rs_write_int(savef, ntraps);
1343 rs_write_int(savef, hungry_state);
1344 rs_write_int(savef, inpack);
1345 rs_write_int(savef, inv_type);
1346 rs_write_int(savef, level);
1347 rs_write_int(savef, max_level);
1348 rs_write_int(savef, no_food);
1349 rs_write_int(savef, food_left);
1350 rs_write_int(savef, lastscore);
1351 rs_write_int(savef, no_move);
1352 rs_write_int(savef, purse);
1353 rs_write_int(savef, quiet);
1354 rs_write_int(savef, vf_hit);
1355 rs_write_uint(savef, seed);
1356 rs_write_coord(savef, stairs);
1357 rs_write_thing(savef, &player);
1358 rs_write_object_reference(savef, player.t_pack, cur_armor);
1359 rs_write_object_reference(savef, player.t_pack, cur_ring[0]);
1360 rs_write_object_reference(savef, player.t_pack, cur_ring[1]);
1361 rs_write_object_reference(savef, player.t_pack, cur_weapon);
1362 rs_write_object_list(savef, lvl_obj);
1363 rs_write_thing_list(savef, mlist);
1364 rs_write_places(savef,places,MAXLINES*MAXCOLS);
1365 rs_write_stats(savef,&max_stats);
1366 rs_write_rooms(savef, rooms, MAXROOMS);
1367 rs_write_rooms(savef, passages, MAXPASS);
1368 rs_write_monsters(savef,monsters,26);
1369 rs_write_obj_info(savef, things, NUMTHINGS);
1370 rs_write_obj_info(savef, arm_info, MAXARMORS);
1371 rs_write_obj_info(savef, pot_info, MAXPOTIONS);
1372 rs_write_obj_info(savef, ring_info, MAXRINGS);
1373 rs_write_obj_info(savef, scr_info, MAXSCROLLS);
1374 rs_write_obj_info(savef, weap_info, MAXWEAPONS+1);
1375 rs_write_obj_info(savef, ws_info, MAXSTICKS);
1376 rs_write_daemons(savef, &d_list[0], 20);
1377 rs_write_int(savef,between);
1378 rs_write_int(savef, group);
1379 rs_write_window(savef,stdscr);
1380
1381 return( encclearerr() );
1382 }
1383
1384 int
1385 rs_restore_file(FILE *savef)
1386 {
1387 encclearerr();
1388
1389 rs_read_int(savef, &noscore);
1390 rs_read_int(savef, &seenstairs);
1391 rs_read_int(savef, &amulet);
1392 rs_read_int(savef, &fight_flush);
1393 rs_read_int(savef, &jump);
1394 rs_read_int(savef, &passgo);
1395 rs_read_int(savef, &see_floor);
1396 rs_read_int(savef, &terse);
1397 rs_read_int(savef, &tombstone);
1398 rs_read_ints(savef, pack_used, 26);
1399 rs_read_chars(savef, file_name, MAXSTR);
1400 rs_read_chars(savef, huh, MAXSTR);
1401 rs_read_potions(savef);
1402 rs_read_rings(savef);
1403 rs_read_scrolls(savef);
1404 rs_read_chars(savef, whoami, MAXSTR);
1405 rs_read_sticks(savef);
1406 rs_read_chars(savef, fruit, MAXSTR);
1407 rs_read_int(savef, &n_objs);
1408 rs_read_int(savef, &ntraps);
1409 rs_read_int(savef, &hungry_state);
1410 rs_read_int(savef, &inpack);
1411 rs_read_int(savef, &inv_type);
1412 rs_read_int(savef, &level);
1413 rs_read_int(savef, &max_level);
1414 rs_read_int(savef, &no_food);
1415 rs_read_int(savef, &food_left);
1416 rs_read_int(savef, &lastscore);
1417 rs_read_int(savef, &no_move);
1418 rs_read_int(savef, &purse);
1419 rs_read_int(savef, &quiet);
1420 rs_read_int(savef, &vf_hit);
1421 rs_read_uint(savef, &seed);
1422 rs_read_coord(savef, &stairs);
1423 rs_read_thing(savef, &player);
1424 rs_read_object_reference(savef, player.t_pack, &cur_armor);
1425 rs_read_object_reference(savef, player.t_pack, &cur_ring[0]);
1426 rs_read_object_reference(savef, player.t_pack, &cur_ring[1]);
1427 rs_read_object_reference(savef, player.t_pack, &cur_weapon);
1428 rs_read_object_list(savef, &lvl_obj);
1429 rs_read_thing_list(savef, &mlist);
1430 rs_fix_thing(&player);
1431 rs_fix_thing_list(mlist);
1432 rs_read_places(savef,places,MAXLINES*MAXCOLS);
1433 rs_read_stats(savef, &max_stats);
1434 rs_read_rooms(savef, rooms, MAXROOMS);
1435 rs_read_rooms(savef, passages, MAXPASS);
1436 rs_read_monsters(savef,monsters,26);
1437 rs_read_obj_info(savef, things, NUMTHINGS);
1438 rs_read_obj_info(savef, arm_info, MAXARMORS);
1439 rs_read_obj_info(savef, pot_info, MAXPOTIONS);
1440 rs_read_obj_info(savef, ring_info, MAXRINGS);
1441 rs_read_obj_info(savef, scr_info, MAXSCROLLS);
1442 rs_read_obj_info(savef, weap_info, MAXWEAPONS+1);
1443 rs_read_obj_info(savef, ws_info, MAXSTICKS);
1444 rs_read_daemons(savef, d_list, 20);
1445 rs_read_int(savef,&between);
1446 rs_read_int(savef,&group);
1447 rs_read_window(savef,stdscr);
1448
1449 return( encclearerr() );
1450 }