Annotation of early-roguelike/rogue5/state.c, Revision 1.1.1.1
1.1 rubenllo 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 == turn_see_off)
602: func = 10;
603: else if (dlist[i].d_func == land)
604: func = 11;
605: else if (dlist[i].d_func == come_down)
606: func = 12;
607: else if (dlist[i].d_func == visuals)
608: func = 13;
609: else if (dlist[i].d_func == NULL)
610: func = 0;
611: else
612: func = -1;
613:
614: rs_write_int(savef, dlist[i].d_type);
615: rs_write_int(savef, func);
616: rs_write_int(savef, dlist[i].d_arg);
617: rs_write_int(savef, dlist[i].d_time);
618: }
619: }
620:
621: void
622: rs_read_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
623: {
624: int i = 0;
625: int func = 0;
626: int value = 0;
627:
628: rs_read_marker(savef, RSID_DAEMONS);
629: rs_read_int(savef, &value);
630:
631: if (!encerror() && (value > cnt))
632: {
633: encseterr(EILSEQ);
634: return;
635: }
636:
637: for(i=0; i < cnt; i++)
638: {
639: func = 0;
640: rs_read_int(savef, &dlist[i].d_type);
641: rs_read_int(savef, &func);
642: rs_read_int(savef, &dlist[i].d_arg);
643: rs_read_int(savef, &dlist[i].d_time);
644:
645: if (encerror())
646: return;
647:
648: switch(func)
649: {
650: case 1: dlist[i].d_func = rollwand;
651: break;
652: case 2: dlist[i].d_func = doctor;
653: break;
654: case 3: dlist[i].d_func = stomach;
655: break;
656: case 4: dlist[i].d_func = runners;
657: break;
658: case 5: dlist[i].d_func = swander;
659: break;
660: case 6: dlist[i].d_func = nohaste;
661: break;
662: case 7: dlist[i].d_func = unconfuse;
663: break;
664: case 8: dlist[i].d_func = unsee;
665: break;
666: case 9: dlist[i].d_func = sight;
667: break;
668: case 10: dlist[i].d_func = turn_see_off;
669: break;
670: case 11: dlist[i].d_func = land;
671: break;
672: case 12: dlist[i].d_func = come_down;
673: break;
674: case 13: dlist[i].d_func = visuals;
675: break;
676: default:dlist[i].d_func = NULL;
677: break;
678: }
679:
680: if (dlist[i].d_func == NULL)
681: {
682: dlist[i].d_type = 0;
683: dlist[i].d_arg = 0;
684: dlist[i].d_time = 0;
685: }
686: }
687:
688: }
689:
690: void
691: rs_write_obj_info(FILE *savef, struct obj_info *i, int cnt)
692: {
693: int n;
694:
695: rs_write_marker(savef, RSID_MAGICITEMS);
696: rs_write_int(savef, cnt);
697:
698: for(n = 0; n < cnt; n++)
699: {
700: /* oi_name is constant, defined at compile time in all cases */
701: rs_write_int(savef,i[n].oi_prob);
702: rs_write_int(savef,i[n].oi_worth);
703: rs_write_string(savef,i[n].oi_guess);
704: rs_write_int(savef,i[n].oi_know);
705: }
706: }
707:
708: void
709: rs_read_obj_info(FILE *savef, struct obj_info *mi, int cnt)
710: {
711: int n;
712: int value;
713:
714: rs_read_marker(savef, RSID_MAGICITEMS);
715:
716: rs_read_int(savef, &value);
717:
718: if (!encerror() && (value > cnt))
719: {
720: encseterr(EILSEQ);
721: return;
722: }
723:
724: for(n = 0; n < value; n++)
725: {
726: /* mi_name is const, defined at compile time in all cases */
727: rs_read_int(savef,&mi[n].oi_prob);
728: rs_read_int(savef,&mi[n].oi_worth);
729: rs_read_new_string(savef,&mi[n].oi_guess);
730: rs_read_int(savef,&mi[n].oi_know);
731: }
732: }
733:
734: void
735: rs_write_room(FILE *savef, struct room *r)
736: {
737: rs_write_coord(savef, r->r_pos);
738: rs_write_coord(savef, r->r_max);
739: rs_write_coord(savef, r->r_gold);
740: rs_write_int(savef, r->r_goldval);
741: rs_write_int(savef, r->r_flags);
742: rs_write_int(savef, r->r_nexits);
743: rs_write_coord(savef, r->r_exit[0]);
744: rs_write_coord(savef, r->r_exit[1]);
745: rs_write_coord(savef, r->r_exit[2]);
746: rs_write_coord(savef, r->r_exit[3]);
747: rs_write_coord(savef, r->r_exit[4]);
748: rs_write_coord(savef, r->r_exit[5]);
749: rs_write_coord(savef, r->r_exit[6]);
750: rs_write_coord(savef, r->r_exit[7]);
751: rs_write_coord(savef, r->r_exit[8]);
752: rs_write_coord(savef, r->r_exit[9]);
753: rs_write_coord(savef, r->r_exit[10]);
754: rs_write_coord(savef, r->r_exit[11]);
755: }
756:
757: void
758: rs_read_room(FILE *savef, struct room *r)
759: {
760: rs_read_coord(savef,&r->r_pos);
761: rs_read_coord(savef,&r->r_max);
762: rs_read_coord(savef,&r->r_gold);
763: rs_read_int(savef,&r->r_goldval);
764: rs_read_int(savef,&r->r_flags);
765: rs_read_int(savef,&r->r_nexits);
766: rs_read_coord(savef,&r->r_exit[0]);
767: rs_read_coord(savef,&r->r_exit[1]);
768: rs_read_coord(savef,&r->r_exit[2]);
769: rs_read_coord(savef,&r->r_exit[3]);
770: rs_read_coord(savef,&r->r_exit[4]);
771: rs_read_coord(savef,&r->r_exit[5]);
772: rs_read_coord(savef,&r->r_exit[6]);
773: rs_read_coord(savef,&r->r_exit[7]);
774: rs_read_coord(savef,&r->r_exit[8]);
775: rs_read_coord(savef,&r->r_exit[9]);
776: rs_read_coord(savef,&r->r_exit[10]);
777: rs_read_coord(savef,&r->r_exit[11]);
778: }
779:
780: void
781: rs_write_rooms(FILE *savef, struct room r[], int cnt)
782: {
783: int n = 0;
784:
785: rs_write_int(savef, cnt);
786:
787: for(n = 0; n < cnt; n++)
788: rs_write_room(savef, &r[n]);
789: }
790:
791: void
792: rs_read_rooms(FILE *savef, struct room *r, int cnt)
793: {
794: int value = 0, n = 0;
795:
796: rs_read_int(savef,&value);
797:
798: if (!encerror() && (value > cnt))
799: encseterr(EILSEQ);
800: else
801: for(n = 0; n < value; n++)
802: rs_read_room(savef,&r[n]);
803: }
804:
805: void
806: rs_write_room_reference(FILE *savef, struct room *rp)
807: {
808: int i, room = -1;
809:
810: for (i = 0; i < MAXROOMS; i++)
811: if (&rooms[i] == rp)
812: room = i;
813:
814: rs_write_int(savef, room);
815: }
816:
817: void
818: rs_read_room_reference(FILE *savef, struct room **rp)
819: {
820: int i;
821:
822: rs_read_int(savef, &i);
823:
824: if (!encerror()) {
825: if (i >= 0 && i < MAXROOMS)
826: *rp = &rooms[i];
827: else
828: *rp = NULL;
829: }
830: }
831:
832: void
833: rs_write_monsters(FILE *savef, struct monster *m, int cnt)
834: {
835: int n;
836:
837: rs_write_marker(savef, RSID_MONSTERS);
838: rs_write_int(savef, cnt);
839:
840: for(n=0;n<cnt;n++)
841: rs_write_stats(savef, &m[n].m_stats);
842: }
843:
844: void
845: rs_read_monsters(FILE *savef, struct monster *m, int cnt)
846: {
847: int value = 0, n = 0;
848:
849: rs_read_marker(savef, RSID_MONSTERS);
850:
851: rs_read_int(savef, &value);
852:
853: if (!encerror() && (value != cnt))
854: encseterr(EILSEQ);
855: else
856: for(n = 0; n < cnt; n++)
857: rs_read_stats(savef, &m[n].m_stats);
858: }
859:
860: void
861: rs_write_object(FILE *savef, THING *o)
862: {
863: rs_write_marker(savef, RSID_OBJECT);
864: rs_write_int(savef, o->_o._o_type);
865: rs_write_coord(savef, o->_o._o_pos);
866: rs_write_int(savef, o->_o._o_launch);
867: rs_write_int(savef, o->_o._o_packch);
868: rs_write_chars(savef, o->_o._o_damage, sizeof(o->_o._o_damage));
869: rs_write_chars(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg));
870: rs_write_int(savef, o->_o._o_count);
871: rs_write_int(savef, o->_o._o_which);
872: rs_write_int(savef, o->_o._o_hplus);
873: rs_write_int(savef, o->_o._o_dplus);
874: rs_write_int(savef, o->_o._o_arm);
875: rs_write_int(savef, o->_o._o_flags);
876: rs_write_int(savef, o->_o._o_group);
877: rs_write_string(savef, o->_o._o_label);
878: }
879:
880: void
881: rs_read_object(FILE *savef, THING *o)
882: {
883: rs_read_marker(savef, RSID_OBJECT);
884: rs_read_int(savef, &o->_o._o_type);
885: rs_read_coord(savef, &o->_o._o_pos);
886: rs_read_int(savef, &o->_o._o_launch);
887: rs_read_int(savef, &o->_o._o_packch);
888: rs_read_chars(savef, o->_o._o_damage, sizeof(o->_o._o_damage));
889: rs_read_chars(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg));
890: rs_read_int(savef, &o->_o._o_count);
891: rs_read_int(savef, &o->_o._o_which);
892: rs_read_int(savef, &o->_o._o_hplus);
893: rs_read_int(savef, &o->_o._o_dplus);
894: rs_read_int(savef, &o->_o._o_arm);
895: rs_read_int(savef, &o->_o._o_flags);
896: rs_read_int(savef, &o->_o._o_group);
897: rs_read_new_string(savef, &o->_o._o_label);
898: }
899:
900: void
901: rs_write_object_list(FILE *savef, THING *l)
902: {
903: rs_write_marker(savef, RSID_OBJECTLIST);
904: rs_write_int(savef, list_size(l));
905:
906: for( ;l != NULL; l = l->l_next)
907: rs_write_object(savef, l);
908: }
909:
910: void
911: rs_read_object_list(FILE *savef, THING **list)
912: {
913: int i, cnt;
914: THING *l = NULL, *previous = NULL, *head = NULL;
915:
916: rs_read_marker(savef, RSID_OBJECTLIST);
917: rs_read_int(savef, &cnt);
918:
919: if (encerror())
920: return;
921:
922: for (i = 0; i < cnt; i++)
923: {
924: l = new_item();
925:
926: l->l_prev = previous;
927:
928: if (previous != NULL)
929: previous->l_next = l;
930:
931: rs_read_object(savef,l);
932:
933: if (previous == NULL)
934: head = l;
935:
936: previous = l;
937: }
938:
939: if (l != NULL)
940: l->l_next = NULL;
941:
942: *list = head;
943: }
944:
945: void
946: rs_write_object_reference(FILE *savef, THING *list, THING *item)
947: {
948: int i;
949:
950: i = find_list_ptr(list, item);
951:
952: rs_write_int(savef, i);
953: }
954:
955: void
956: rs_read_object_reference(FILE *savef, THING *list, THING **item)
957: {
958: int i;
959:
960: rs_read_int(savef, &i);
961:
962: if (!encerror())
963: *item = get_list_item(list,i);
964: else
965: *item = NULL;
966: }
967:
968: int
969: find_room_coord(const struct room *rmlist,const coord *c, int n)
970: {
971: int i = 0;
972:
973: for(i = 0; i < n; i++)
974: if(&rmlist[i].r_gold == c)
975: return(i);
976:
977: return(-1);
978: }
979:
980: int
981: find_thing_coord(THING *monlist, const coord *c)
982: {
983: THING *mitem;
984: THING *tp;
985: int i = 0;
986:
987: for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
988: {
989: tp = mitem;
990:
991: if (c == &tp->t_pos)
992: return(i);
993:
994: i++;
995: }
996:
997: return(-1);
998: }
999:
1000: int
1001: find_object_coord(THING *objlist, const coord *c)
1002: {
1003: THING *oitem;
1004: THING *obj;
1005: int i = 0;
1006:
1007: for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
1008: {
1009: obj = oitem;
1010:
1011: if (c == &obj->o_pos)
1012: return(i);
1013:
1014: i++;
1015: }
1016:
1017: return(-1);
1018: }
1019:
1020: void
1021: rs_write_thing(FILE *savef, THING *t)
1022: {
1023: int i = -1;
1024:
1025: rs_write_marker(savef, RSID_THING);
1026:
1027: if (t == NULL)
1028: {
1029: rs_write_int(savef, 0);
1030: return;
1031: }
1032:
1033: rs_write_int(savef, 1);
1034: rs_write_coord(savef, t->_t._t_pos);
1035: rs_write_int(savef, t->_t._t_turn);
1036: rs_write_int(savef, t->_t._t_type);
1037: rs_write_int(savef, t->_t._t_disguise);
1038: rs_write_int(savef, t->_t._t_oldch);
1039:
1040: /*
1041: t_dest can be:
1042: 0,0: NULL
1043: 0,1: location of hero
1044: 1,i: location of a thing (monster)
1045: 2,i: location of an object
1046: 3,i: location of gold in a room
1047:
1048: We need to remember what we are chasing rather than
1049: the current location of what we are chasing.
1050: */
1051:
1052: if (t->t_dest == &hero)
1053: {
1054: rs_write_int(savef,0);
1055: rs_write_int(savef,1);
1056: }
1057: else if (t->t_dest != NULL)
1058: {
1059: i = find_thing_coord(mlist, t->t_dest);
1060:
1061: if (i >=0 )
1062: {
1063: rs_write_int(savef,1);
1064: rs_write_int(savef,i);
1065: }
1066: else
1067: {
1068: i = find_object_coord(lvl_obj, t->t_dest);
1069:
1070: if (i >= 0)
1071: {
1072: rs_write_int(savef,2);
1073: rs_write_int(savef,i);
1074: }
1075: else
1076: {
1077: i = find_room_coord(rooms, t->t_dest, MAXROOMS);
1078:
1079: if (i >= 0)
1080: {
1081: rs_write_int(savef,3);
1082: rs_write_int(savef,i);
1083: }
1084: else
1085: {
1086: rs_write_int(savef, 0);
1087: rs_write_int(savef,1); /* chase the hero anyway */
1088: }
1089: }
1090: }
1091: }
1092: else
1093: {
1094: rs_write_int(savef,0);
1095: rs_write_int(savef,0);
1096: }
1097:
1098: rs_write_int(savef, t->_t._t_flags);
1099: rs_write_stats(savef, &t->_t._t_stats);
1100: rs_write_room_reference(savef, t->_t._t_room);
1101: rs_write_object_list(savef, t->_t._t_pack);
1102: }
1103:
1104: void
1105: rs_read_thing(FILE *savef, THING *t)
1106: {
1107: int listid = 0, index = -1;
1108: THING *item;
1109:
1110: rs_read_marker(savef, RSID_THING);
1111: rs_read_int(savef, &index);
1112:
1113: if (encerror())
1114: return;
1115:
1116: if (index == 0)
1117: return;
1118:
1119: rs_read_coord(savef,&t->_t._t_pos);
1120: rs_read_int(savef,&t->_t._t_turn);
1121: rs_read_int(savef,&t->_t._t_type);
1122: rs_read_int(savef,&t->_t._t_disguise);
1123: rs_read_int(savef,&t->_t._t_oldch);
1124:
1125: /*
1126: t_dest can be (listid,index):
1127: 0,0: NULL
1128: 0,1: location of hero
1129: 1,i: location of a thing (monster)
1130: 2,i: location of an object
1131: 3,i: location of gold in a room
1132:
1133: We need to remember what we are chasing rather than
1134: the current location of what we are chasing.
1135: */
1136:
1137: rs_read_int(savef, &listid);
1138: rs_read_int(savef, &index);
1139: t->_t._t_reserved = -1;
1140:
1141: if (encerror())
1142: return;
1143:
1144: if (listid == 0) /* hero or NULL */
1145: {
1146: if (index == 1)
1147: t->_t._t_dest = &hero;
1148: else
1149: t->_t._t_dest = NULL;
1150: }
1151: else if (listid == 1) /* monster/thing */
1152: {
1153: t->_t._t_dest = NULL;
1154: t->_t._t_reserved = index;
1155: }
1156: else if (listid == 2) /* object */
1157: {
1158: THING *obj;
1159:
1160: item = get_list_item(lvl_obj, index);
1161:
1162: if (item != NULL)
1163: {
1164: obj = item;
1165: t->_t._t_dest = &obj->o_pos;
1166: }
1167: }
1168: else if (listid == 3) /* gold */
1169: {
1170: t->_t._t_dest = &rooms[index].r_gold;
1171: }
1172: else
1173: t->_t._t_dest = NULL;
1174:
1175: rs_read_int(savef,&t->_t._t_flags);
1176: rs_read_stats(savef,&t->_t._t_stats);
1177: rs_read_room_reference(savef, &t->_t._t_room);
1178: rs_read_object_list(savef,&t->_t._t_pack);
1179: }
1180:
1181: void
1182: rs_fix_thing(THING *t)
1183: {
1184: THING *item;
1185: THING *tp;
1186:
1187: if (t->t_reserved < 0)
1188: return;
1189:
1190: item = get_list_item(mlist,t->t_reserved);
1191:
1192: if (item != NULL)
1193: {
1194: tp = item;
1195: t->t_dest = &tp->t_pos;
1196: }
1197: }
1198:
1199: void
1200: rs_write_thing_list(FILE *savef, THING *l)
1201: {
1202: int cnt = 0;
1203:
1204: rs_write_marker(savef, RSID_MONSTERLIST);
1205:
1206: cnt = list_size(l);
1207:
1208: rs_write_int(savef, cnt);
1209:
1210: if (cnt < 1)
1211: return;
1212:
1213: while (l != NULL) {
1214: rs_write_thing(savef, l);
1215: l = l->l_next;
1216: }
1217: }
1218:
1219: void
1220: rs_read_thing_list(FILE *savef, THING **list)
1221: {
1222: int i, cnt;
1223: THING *l = NULL, *previous = NULL, *head = NULL;
1224:
1225: rs_read_marker(savef, RSID_MONSTERLIST);
1226: rs_read_int(savef, &cnt);
1227:
1228: if (encerror())
1229: return;
1230:
1231: for (i = 0; i < cnt; i++)
1232: {
1233: l = new_item();
1234:
1235: l->l_prev = previous;
1236:
1237: if (previous != NULL)
1238: previous->l_next = l;
1239:
1240: rs_read_thing(savef,l);
1241:
1242: if (previous == NULL)
1243: head = l;
1244:
1245: previous = l;
1246: }
1247:
1248: if (l != NULL)
1249: l->l_next = NULL;
1250:
1251: *list = head;
1252: }
1253:
1254: void
1255: rs_fix_thing_list(THING *list)
1256: {
1257: THING *item;
1258:
1259: for(item = list; item != NULL; item = item->l_next)
1260: rs_fix_thing(item);
1261: }
1262:
1263: void
1264: rs_write_thing_reference(FILE *savef, THING *list, THING *item)
1265: {
1266: int i;
1267:
1268: if (item == NULL)
1269: rs_write_int(savef,-1);
1270: else
1271: {
1272: i = find_list_ptr(list, item);
1273:
1274: rs_write_int(savef, i);
1275: }
1276: }
1277:
1278: void
1279: rs_read_thing_reference(FILE *savef, THING *list, THING **item)
1280: {
1281: int i;
1282:
1283: rs_read_int(savef, &i);
1284:
1285: if (encerror())
1286: return;
1287:
1288: if (i == -1)
1289: *item = NULL;
1290: else
1291: *item = get_list_item(list,i);
1292:
1293: }
1294:
1295: void
1296: rs_write_thing_references(FILE *savef, THING *list, THING *items[], int cnt)
1297: {
1298: int i;
1299:
1300: for(i = 0; i < cnt; i++)
1301: rs_write_thing_reference(savef,list,items[i]);
1302: }
1303:
1304: void
1305: rs_read_thing_references(FILE *savef, THING *list, THING *items[], int cnt)
1306: {
1307: int i;
1308:
1309: for(i = 0; i < cnt; i++)
1310: rs_read_thing_reference(savef,list,&items[i]);
1311: }
1312:
1313: void
1314: rs_write_places(FILE *savef, PLACE *p, int cnt)
1315: {
1316: int i = 0;
1317:
1318: for(i = 0; i < cnt; i++)
1319: {
1320: rs_write_int(savef, p[i].p_ch);
1321: rs_write_int(savef, p[i].p_flags);
1322: rs_write_thing_reference(savef, mlist, p[i].p_monst);
1323: }
1324: }
1325:
1326: void
1327: rs_read_places(FILE *savef, PLACE *p, int cnt)
1328: {
1329: int i = 0;
1330:
1331: for(i = 0; i < cnt; i++)
1332: {
1333: rs_read_int(savef,&p[i].p_ch);
1334: rs_read_int(savef,&p[i].p_flags);
1335: rs_read_thing_reference(savef, mlist, &p[i].p_monst);
1336: }
1337: }
1338:
1339: int
1340: rs_save_file(FILE *savef)
1341: {
1342: encclearerr();
1343:
1344: rs_write_int(savef, noscore);
1345: rs_write_int(savef, seenstairs);
1346: rs_write_int(savef, amulet);
1347: rs_write_int(savef, fight_flush);
1348: rs_write_int(savef, jump);
1349: rs_write_int(savef, passgo);
1350: rs_write_int(savef, see_floor);
1351: rs_write_int(savef, terse);
1352: rs_write_int(savef, tombstone);
1353: rs_write_ints(savef, pack_used, 26);
1354: rs_write_chars(savef, file_name, MAXSTR);
1355: rs_write_chars(savef, huh, MAXSTR);
1356: rs_write_potions(savef);
1357: rs_write_rings(savef);
1358: rs_write_scrolls(savef);
1359: rs_write_chars(savef, whoami, MAXSTR);
1360: rs_write_sticks(savef);
1361: rs_write_chars(savef, fruit, MAXSTR);
1362: rs_write_int(savef,n_objs);
1363: rs_write_int(savef, ntraps);
1364: rs_write_int(savef, hungry_state);
1365: rs_write_int(savef, inpack);
1366: rs_write_int(savef, inv_type);
1367: rs_write_int(savef, level);
1368: rs_write_int(savef, max_level);
1369: rs_write_int(savef, no_food);
1370: rs_write_int(savef, food_left);
1371: rs_write_int(savef, lastscore);
1372: rs_write_int(savef, no_move);
1373: rs_write_int(savef, purse);
1374: rs_write_int(savef, quiet);
1375: rs_write_int(savef, vf_hit);
1376: rs_write_uint(savef, seed);
1377: rs_write_coord(savef, stairs);
1378: rs_write_thing(savef, &player);
1379: rs_write_object_reference(savef, player.t_pack, cur_armor);
1380: rs_write_object_reference(savef, player.t_pack, cur_ring[0]);
1381: rs_write_object_reference(savef, player.t_pack, cur_ring[1]);
1382: rs_write_object_reference(savef, player.t_pack, cur_weapon);
1383: rs_write_object_list(savef, lvl_obj);
1384: rs_write_thing_list(savef, mlist);
1385: rs_write_places(savef,places,MAXLINES*MAXCOLS);
1386: rs_write_stats(savef,&max_stats);
1387: rs_write_rooms(savef, rooms, MAXROOMS);
1388: rs_write_rooms(savef, passages, MAXPASS);
1389: rs_write_monsters(savef,monsters,26);
1390: rs_write_obj_info(savef, things, NUMTHINGS);
1391: rs_write_obj_info(savef, arm_info, MAXARMORS);
1392: rs_write_obj_info(savef, pot_info, MAXPOTIONS);
1393: rs_write_obj_info(savef, ring_info, MAXRINGS);
1394: rs_write_obj_info(savef, scr_info, MAXSCROLLS);
1395: rs_write_obj_info(savef, weap_info, MAXWEAPONS+1);
1396: rs_write_obj_info(savef, ws_info, MAXSTICKS);
1397: rs_write_daemons(savef, &d_list[0], 20);
1398: rs_write_int(savef,between);
1399: rs_write_int(savef, group);
1400: rs_write_window(savef,stdscr);
1401:
1402: return( encclearerr() );
1403: }
1404:
1405: int
1406: rs_restore_file(FILE *savef)
1407: {
1408: char fake_file_name[MAXSTR];
1409: THING *mitem;
1410: encclearerr();
1411:
1412: rs_read_int(savef, &noscore);
1413: rs_read_int(savef, &seenstairs);
1414: rs_read_int(savef, &amulet);
1415: rs_read_int(savef, &fight_flush);
1416: rs_read_int(savef, &jump);
1417: rs_read_int(savef, &passgo);
1418: rs_read_int(savef, &see_floor);
1419: rs_read_int(savef, &terse);
1420: rs_read_int(savef, &tombstone);
1421: rs_read_ints(savef, pack_used, 26);
1422: rs_read_chars(savef, fake_file_name, MAXSTR);
1423: rs_read_chars(savef, huh, MAXSTR);
1424: rs_read_potions(savef);
1425: rs_read_rings(savef);
1426: rs_read_scrolls(savef);
1427: rs_read_chars(savef, whoami, MAXSTR);
1428: rs_read_sticks(savef);
1429: rs_read_chars(savef, fruit, MAXSTR);
1430: rs_read_int(savef, &n_objs);
1431: rs_read_int(savef, &ntraps);
1432: rs_read_int(savef, &hungry_state);
1433: rs_read_int(savef, &inpack);
1434: rs_read_int(savef, &inv_type);
1435: rs_read_int(savef, &level);
1436: rs_read_int(savef, &max_level);
1437: rs_read_int(savef, &no_food);
1438: rs_read_int(savef, &food_left);
1439: rs_read_int(savef, &lastscore);
1440: rs_read_int(savef, &no_move);
1441: rs_read_int(savef, &purse);
1442: rs_read_int(savef, &quiet);
1443: rs_read_int(savef, &vf_hit);
1444: rs_read_uint(savef, &seed);
1445: rs_read_coord(savef, &stairs);
1446: rs_read_thing(savef, &player);
1447: rs_read_object_reference(savef, player.t_pack, &cur_armor);
1448: rs_read_object_reference(savef, player.t_pack, &cur_ring[0]);
1449: rs_read_object_reference(savef, player.t_pack, &cur_ring[1]);
1450: rs_read_object_reference(savef, player.t_pack, &cur_weapon);
1451: rs_read_object_list(savef, &lvl_obj);
1452: rs_read_thing_list(savef, &mlist);
1453: rs_fix_thing(&player);
1454: rs_fix_thing_list(mlist);
1455: rs_read_places(savef,places,MAXLINES*MAXCOLS);
1456: rs_read_stats(savef, &max_stats);
1457: rs_read_rooms(savef, rooms, MAXROOMS);
1458: rs_read_rooms(savef, passages, MAXPASS);
1459: rs_read_monsters(savef,monsters,26);
1460: rs_read_obj_info(savef, things, NUMTHINGS);
1461: rs_read_obj_info(savef, arm_info, MAXARMORS);
1462: rs_read_obj_info(savef, pot_info, MAXPOTIONS);
1463: rs_read_obj_info(savef, ring_info, MAXRINGS);
1464: rs_read_obj_info(savef, scr_info, MAXSCROLLS);
1465: rs_read_obj_info(savef, weap_info, MAXWEAPONS+1);
1466: rs_read_obj_info(savef, ws_info, MAXSTICKS);
1467: rs_read_daemons(savef, d_list, 20);
1468: rs_read_int(savef,&between);
1469: rs_read_int(savef,&group);
1470: rs_read_window(savef,stdscr);
1471:
1472: if (player.t_room == NULL)
1473: player.t_room = roomin(&hero);
1474: for (mitem = mlist; mitem != NULL; mitem = mitem->l_next) {
1475: if (mitem->t_room == NULL)
1476: mitem->t_room = roomin(&(mitem->t_pos));
1477: }
1478:
1479: return( encclearerr() );
1480: }
CVSweb