Annotation of early-roguelike/urogue/state.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: state.c - Portable Rogue Save State Code
3:
4: Copyright (C) 1993, 1995 Nicholas J. Kisseberth
5:
6: Redistribution and use in source and binary forms, with or without
7: modification, are permitted provided that the following conditions
8: are met:
9: 1. Redistributions of source code must retain the above copyright
10: notice, this list of conditions and the following disclaimer.
11: 2. Redistributions in binary form must reproduce the above copyright
12: notice, this list of conditions and the following disclaimer in the
13: documentation and/or other materials provided with the distribution.
14: 3. Neither the name(s) of the author(s) nor the names of other contributors
15: may be used to endorse or promote products derived from this software
16: without specific prior written permission.
17:
18: THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
19: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21: ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
22: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: SUCH DAMAGE.
29: */
30:
31: /*
32: Notes
33:
34: Should move all game variables into one place
35: Should move save/restore code into save.c or some such
36: */
37:
38: #include <assert.h>
39: #include <stdlib.h>
40: #include <string.h>
41: #include "rogue.h"
42:
43: /*
44: Variables for global game state.
45:
46: All variables that need to get saved when saving a game
47: are defined in this file. Long term goal is to move many
48: of these variables into a "struct level" data type of some
49: kind... perhaps not, maybe struct game...
50:
51: Other global variables that don't need to get saved are
52: kept in main.c.
53:
54: Other global variables that don't change during the course
55: of a game are kept in urogue.c, monsdata.c, data.c.
56: */
57:
58: #define _X_ { 0, 0, 0, 0, 0 }
59:
60: struct delayed_action
61: d_list[MAXDAEMONS] = /* daemon/fuse list */
62: {
63: _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
64: _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
65: _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
66: _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
67: _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
68: _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
69: };
70:
71: #undef _X_
72:
73: char *s_names[MAXSCROLLS]; /* Names of the scrolls */
74: char *p_colors[MAXPOTIONS]; /* Colors of the potions */
75: char *r_stones[MAXRINGS]; /* Stone settings of the rings */
76: char *ws_made[MAXSTICKS]; /* What sticks are made of */
77: char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
78:
79: char *guess_items[MAXMAGICTYPES][MAXMAGICITEMS]; /* guess magic is */
80: int know_items[MAXMAGICTYPES][MAXMAGICITEMS]; /* flag knowlede of magic */
81: /* object data */
82:
83: struct trap traps[2 * MAXTRAPS]; /* 2x for special effects */
84: struct room rooms[MAXROOMS]; /* One for each room -- A level */
85: struct room *oldrp = NULL; /* Roomin(&player.t_oldpos) */
86: struct thing player; /* The rogue */
87: struct linked_list *lvl_obj = NULL; /* Treasure on this level */
88: struct linked_list *fam_ptr = NULL; /* A ptr to the familiar */
89: struct linked_list *mlist = NULL; /* Monsters on this level */
90: struct thing *beast; /* The last beast that attacked */
91: struct object *cur_armor = NULL; /* what rogue wears */
92: struct object *cur_weapon = NULL; /* ... and wields */
93: struct object *cur_ring[10]; /* His rings */
94: struct linked_list *curr_mons = NULL; /* The mons. currently moving */
95: struct linked_list *next_mons = NULL; /* The mons. after curr_mons */
96:
97: /* Misc. game state info */
98: char dummybuf1[50000];
99: char dummybuf2[50000];
100: char msgbuf[10][2*LINELEN]; /* message buffer history */
101: int msg_index = 0; /* index in msg history buffer for nxt msg */
102: int foodlev = 1; /* how fast he eats food */
103: int ntraps = 0; /* Number of traps on this level */
104: int dnum = 0; /* Dungeon number */
105: int max_level = 0; /* Deepest player has gone */
106: int lost_dext = 0; /* amount of lost dexterity */
107: int no_command = 0;
108: int level = 0;
109: int see_dist = 3;
110: int no_food = 0;
111: int count = 0;
112: int food_left = HUNGERTIME;
113: int group = 1;
114: int hungry_state = F_OK;
115: int infest_dam = 0;
116: int lost_str = 0;
117: int hold_count = 0;
118: int trap_tries = 0;
119: int has_artifact = 0;
120: int picked_artifact = 0;
121: int luck = 0;
122: int resurrect = 0;
123: int fam_type = 0; /* The type of familiar */
124: int mons_summoned = 0; /* Number of summoned monsters */
125: char PLAYER = VPLAYER; /* what the player looks like */
126: char take = 0; /* Thing the rogue is taking */
127: char runch = 0; /* Direction player is running */
128: int char_type = C_NOTSET; /* what type of character is player */
129: int inv_type = INV_CLEAR; /* Overwrite style of inventory */
130: int pool_teleport = FALSE; /* just teleported from a pool */
131: int inwhgt = FALSE; /* true if from wghtchk() */
132: int after = 0; /* True if we want after daemons */
133: int waswizard = 0; /* Was a wizard sometime */
134: int canwizard = 1; /* Will be permitted to do this */
135: int playing = TRUE;
136: int running = FALSE;
137: int fighting = FALSE;
138: int wizard = FALSE;
139: int wiz_verbose = TRUE;
140: int moving = FALSE;
141: int use_savedir = FALSE;
142: coord delta; /* Change indicated to get_dir() */
143: LEVTYPE levtype; /* type of level i'm on */
144: long purse = 0;
145: unsigned long total = 0;
146:
147: WINDOW *cw; /* Window that the player sees */
148: WINDOW *hw; /* Used for the help command */
149: WINDOW *mw; /* Used to store mosnters */
150:
151: /* options.o */
152: /* game options */
153:
154: int terse = FALSE;
155: int door_stop = FALSE;
156: int jump = TRUE;
157: int doorstop = TRUE;
158: int firstmove = FALSE;
159: int askme = TRUE;
160: char whoami[2 * LINELEN]; /* Name of player */
161: char fruit[2 * LINELEN]; /* Favorite fruit */
162: char file_name[2 * LINELEN]; /* Save file name */
163: char score_file[2 * LINELEN]; /* Score file name */
164:
165: /****************************************************************************/
166: /* Portable Save State Code */
167: /* */
168: /* UltraRogue v1.04 */
169: /****************************************************************************/
170:
171: #define URS_STATS 0xABCD0001
172: #define URS_THING 0xABCD0002
173: #define URS_OBJECT 0xABCD0003
174: #define URS_MAGIC 0xABCD0004
175: #define URS_KNOWS 0xABCD0005
176: #define URS_GUESSES 0xABCD0006
177: #define URS_STACKOBJECT 0xABCD0007
178: #define URS_BAGOBJECT 0xABCD0008
179: #define URS_MONSTERLIST 0xABCD0009
180: #define URS_MONSTERSTATS 0xABCD000A
181: #define URS_MONSTER 0xABCD000B
182: #define URS_TRAP 0xABCD000C
183: #define URS_WINDOW 0xABCD000D
184: #define URS_DAEMONS 0xABCD000E
185:
186: void
187: ur_write(FILE *savef, void *ptr, size_t size)
188: {
189: if (size == 0)
190: return;
191:
192: fwrite(ptr,size,1,savef);
193: }
194:
195: void
196: ur_read(FILE *savef, void *ptr, size_t size)
197: {
198: if (size == 0)
199: return;
200:
201: fread(ptr,size,1,savef);
202: }
203:
204: void
205: ur_write_int(FILE *savef, int c)
206: {
207: ur_write(savef,&c,sizeof(int));
208: }
209:
210: int
211: ur_read_int(FILE *savef)
212: {
213: int i;
214:
215: ur_read(savef, &i, sizeof(int));
216:
217: return(i);
218: }
219:
220: void
221: ur_write_short(FILE *savef, short c)
222: {
223: ur_write(savef,&c,sizeof(short));
224: }
225:
226: short
227: ur_read_short(FILE *savef)
228: {
229: short s;
230:
231: ur_read(savef, &s, sizeof(short));
232:
233: return(s);
234: }
235:
236: void
237: ur_write_long(FILE *savef, long c)
238: {
239: ur_write(savef,&c,sizeof(long));
240: }
241:
242: long
243: ur_read_long(FILE *savef)
244: {
245: long l;
246:
247: ur_read(savef, &l, sizeof(long));
248:
249: return(l);
250: }
251:
252: void
253: ur_write_ulong(FILE *savef, unsigned long c)
254: {
255: ur_write(savef,&c,sizeof(unsigned long));
256: }
257:
258: unsigned long
259: ur_read_ulong(FILE *savef)
260: {
261: long l;
262:
263: ur_read(savef, &l, sizeof(unsigned long));
264:
265: return(l);
266: }
267:
268: void
269: ur_unread_long(FILE *savef)
270: {
271: fseek(savef, -(long)sizeof(long), SEEK_CUR);
272: }
273:
274: void
275: ur_write_char(FILE *savef, char c)
276: {
277: ur_write(savef,&c,sizeof(char));
278: }
279:
280: char
281: ur_read_char(FILE *savef)
282: {
283: char c;
284:
285: ur_read(savef, &c, sizeof(char));
286:
287: return(c);
288: }
289:
290: void
291: ur_write_string(FILE *savef, char *s)
292: {
293: size_t len;
294:
295: len = (s == NULL) ? 0L : strlen(s) + 1 ;
296:
297: ur_write_long(savef, (long) len);
298: ur_write(savef,s,len);
299: }
300:
301:
302: char *
303: ur_read_string(FILE *savef)
304: {
305: size_t len;
306: char *buf;
307:
308: len = ur_read_long(savef);
309:
310: if (len == 0)
311: return(NULL);
312:
313: buf = ur_alloc(len);
314:
315: if (buf == NULL) /* Should flag a global error condition... */
316: return(NULL);
317:
318: ur_read(savef,buf,len);
319:
320: return(buf);
321: }
322:
323: void
324: ur_write_coord(FILE *savef, coord c)
325: {
326: ur_write_int(savef, c.x);
327: ur_write_int(savef, c.y);
328: }
329:
330: coord
331: ur_read_coord(FILE *savef)
332: {
333: coord c;
334:
335: c.x = ur_read_int(savef);
336: c.y = ur_read_int(savef);
337:
338: return(c);
339: }
340:
341: void
342: ur_write_room(FILE *savef, struct room *r)
343: {
344: int i;
345:
346: ur_write_coord(savef, r->r_pos);
347: ur_write_coord(savef, r->r_max);
348:
349: for(i=0; i<MAXDOORS; i++)
350: ur_write_coord(savef, r->r_exit[i]);
351:
352: ur_write_int(savef, r->r_flags);
353: ur_write_int(savef, r->r_nexits);
354: ur_write_short(savef, r->r_fires);
355: }
356:
357: struct room *
358: ur_read_room(FILE *savef)
359: {
360: struct room *r;
361: int i;
362:
363: r = ur_alloc( sizeof(struct room) );
364:
365: r->r_pos = ur_read_coord(savef);
366: r->r_max = ur_read_coord(savef);
367:
368: for(i=0; i<MAXDOORS; i++)
369: r->r_exit[i] = ur_read_coord(savef);
370:
371: r->r_flags = ur_read_int(savef);
372: r->r_nexits = ur_read_int(savef);
373: r->r_fires = ur_read_short(savef);
374:
375: return(r);
376: }
377:
378: void
379: ur_write_object(FILE *savef, struct object *o)
380: {
381: int other;
382:
383: ur_write_long(savef, URS_OBJECT);
384: ur_write_coord(savef, o->o_pos);
385: ur_write_string(savef, o->o_text);
386: ur_write_string(savef, o->o_damage);
387: ur_write_string(savef, o->o_hurldmg);
388: ur_write_long(savef, o->o_flags);
389: ur_write_long(savef, o->ar_flags);
390: ur_write_char(savef, o->o_type);
391: ur_write_int(savef, o->o_ident);
392: ur_write_int(savef, o->o_count);
393: ur_write_int(savef, o->o_which);
394: ur_write_int(savef, o->o_hplus);
395: ur_write_int(savef, o->o_dplus);
396: ur_write_int(savef, o->o_ac);
397: ur_write_int(savef, o->o_group);
398: ur_write_int(savef, o->o_weight);
399: ur_write_char(savef, o->o_launch);
400: ur_write(savef, &o->o_mark[0], MARKLEN);
401: ur_write_long(savef, o->o_worth);
402:
403: other = 0;
404:
405: if (o->o_bag)
406: other = 1;
407: else if (o->next_obj)
408: other |= 2;
409:
410: ur_write_int(savef,other);
411:
412: if (o->o_bag)
413: ur_write_bag(savef,o->o_bag);
414: if (o->next_obj && (o->next_obj->l_prev == NULL) )
415: ur_write_object_stack(savef, o->next_obj);
416: }
417:
418: /*
419: * Puts objects with identifiers into the global ident_list, keeping it sorted
420: * by type and identifier.
421: */
422: void
423: add_to_ident(struct object *o)
424: {
425: extern linked_list *ident_list;
426: linked_list *obj_ll;
427: linked_list *list_p, *prev_p = NULL;
428: struct object *list_o;
429:
430: obj_ll = new_list();
431: obj_ll->data.obj = o;
432:
433: for (list_p = ident_list; list_p != NULL; list_p = next(list_p))
434: {
435: list_o = list_p->data.obj;
436: if (list_o->o_type == o->o_type)
437: {
438: if (list_o->o_ident > o->o_ident)
439: {
440: prev_p = list_p->l_prev;
441: break;
442: }
443: else if (next(list_p) &&
444: next(list_p)->data.obj->o_type != o->o_type)
445: {
446: prev_p = list_p;
447: break;
448: }
449: }
450: if (!next(list_p))
451: prev_p = list_p;
452: }
453: _attach_after(&ident_list, prev_p, obj_ll);
454: return;
455: }
456:
457: struct object *
458: ur_read_object(FILE *savef)
459: {
460: struct object *o;
461: long id;
462: int other;
463:
464: o = ur_alloc(sizeof(struct object));
465:
466: if (o == NULL)
467: return(NULL);
468:
469: memset(o,0,sizeof(struct object));
470:
471: id = ur_read_long(savef);
472:
473: assert(id == URS_OBJECT);
474:
475: o->o_pos = ur_read_coord(savef);
476: o->o_text = ur_read_string(savef);
477: o->o_damage = ur_read_string(savef);
478: o->o_hurldmg = ur_read_string(savef);
479: o->o_flags = ur_read_long(savef);
480: o->ar_flags = ur_read_long(savef);
481: o->o_type = ur_read_char(savef);
482: o->o_ident = ur_read_int(savef);
483: o->o_count = ur_read_int(savef);
484: o->o_which = ur_read_int(savef);
485: o->o_hplus = ur_read_int(savef);
486: o->o_dplus = ur_read_int(savef);
487: o->o_ac = ur_read_int(savef);
488: o->o_group = ur_read_int(savef);
489: o->o_weight = ur_read_int(savef);
490: o->o_launch = ur_read_char(savef);
491: ur_read(savef, &o->o_mark[0], MARKLEN);
492: o->o_worth = ur_read_long(savef);
493:
494: other = ur_read_int(savef);
495:
496: if (o->o_ident != 0) {
497: /* The object needs to be placed in the identifiers list. */
498: add_to_ident(o);
499: }
500:
501: if (other & 1)
502: o->o_bag = ur_read_bag(savef);
503: if (other & 2)
504: o->next_obj = ur_read_object_stack(savef);
505:
506: return(o);
507: }
508:
509: int
510: list_size(struct linked_list *l)
511: {
512: int cnt=0;
513:
514: if (l == NULL)
515: return(0);
516:
517: while(l != NULL)
518: {
519: cnt++;
520: l = l->l_next;
521: }
522:
523: return(cnt);
524: }
525:
526: int
527: find_thing_index(struct linked_list *l, struct thing *item)
528: {
529: int cnt=0;
530:
531: if (l == NULL)
532: return(-1);
533:
534: while(l != NULL)
535: {
536: if (item == l->data.th)
537: return(cnt+1);
538:
539: cnt++;
540: l = l->l_next;
541: }
542:
543: return(0);
544: }
545:
546:
547: int
548: find_list_index(struct linked_list *l, struct object *item)
549: {
550: int cnt=0;
551:
552: if (l == NULL)
553: return(-1);
554:
555: while(l != NULL)
556: {
557: if (item == l->data.obj)
558: return(cnt+1);
559:
560: cnt++;
561: l = l->l_next;
562: }
563:
564: return(0);
565: }
566:
567: struct object *
568: find_object(struct linked_list *list, int num)
569: {
570: int cnt = 0;
571: struct linked_list *l = list;
572:
573: if ( (num < 1) || (list == NULL) )
574: return(NULL);
575:
576: num--;
577:
578: for(cnt = 0; cnt < num; cnt++)
579: {
580: if ( l == NULL )
581: return(NULL);
582:
583: l = l->l_next;
584: }
585:
586: return(l->data.obj);
587: }
588:
589: struct thing *
590: find_thing(struct linked_list *list, int num)
591: {
592: int cnt = 0;
593: struct linked_list *l = list;
594:
595: if ( (num < 1) || (list == NULL) )
596: return(NULL);
597: num--;
598:
599: for(cnt = 0; cnt < num; cnt++)
600: {
601: if (l == NULL)
602: return(NULL);
603:
604: l = l->l_next;
605: }
606:
607: return(l->data.th);
608: }
609:
610:
611: void
612: ur_write_object_stack(FILE *savef, struct linked_list *l)
613: {
614: int cnt;
615:
616: ur_write_long(savef, URS_STACKOBJECT);
617:
618: ur_write_int(savef, cnt = list_size(l) );
619:
620: if (cnt == 0)
621: return;
622:
623: while(l != NULL)
624: {
625: ur_write_object(savef, l->data.obj);
626: l = l->l_next;
627: }
628: }
629:
630: void
631: ur_write_bag(FILE *savef, struct linked_list *l)
632: {
633: int cnt;
634:
635: ur_write_long(savef, URS_BAGOBJECT);
636:
637: ur_write_int(savef, cnt = list_size(l) );
638:
639: if (cnt == 0)
640: return;
641:
642: while(l != NULL)
643: {
644: ur_write_object(savef, l->data.obj);
645: l = l->l_next;
646: }
647: }
648:
649: struct linked_list *
650: ur_read_object_stack(FILE *savef)
651: {
652: long id;
653: int i,cnt;
654: struct linked_list *l = NULL, *previous = NULL, *head = NULL;
655:
656: id = ur_read_long(savef);
657:
658: assert(id == URS_STACKOBJECT);
659:
660: cnt = ur_read_int(savef);
661:
662: for(i = 0; i < cnt; i++)
663: {
664: l = new_list();
665: l->l_prev = previous;
666:
667: if (previous != NULL)
668: previous->l_next = l;
669:
670: l->data.obj = ur_read_object(savef);
671:
672: if (previous == NULL)
673: head = l;
674:
675: previous = l;
676: }
677:
678: if (l != NULL)
679: l->l_next = NULL;
680:
681: return(head);
682: }
683:
684:
685: struct linked_list *
686: ur_read_bag(FILE *savef)
687: {
688: long id;
689: int i,cnt;
690: struct linked_list *l = NULL, *previous = NULL, *head = NULL;
691:
692: id = ur_read_long(savef);
693:
694: assert( id == URS_BAGOBJECT );
695:
696: cnt = ur_read_int(savef);
697:
698: for(i = 0; i < cnt; i++)
699: {
700: l = new_list();
701: l->l_prev = previous;
702:
703: if (previous != NULL)
704: previous->l_next = l;
705:
706: l->data.obj = ur_read_object(savef);
707:
708: if (previous == NULL)
709: head = l;
710:
711: previous = l;
712: }
713:
714: if (l != NULL)
715: l->l_next = NULL;
716:
717: return(head);
718: }
719:
720: void
721: ur_fixup_monsters(struct linked_list *l)
722: {
723: while(l != NULL)
724: {
725: if (l->data.th->chasee_index == -1L)
726: l->data.th->t_chasee = &player;
727: else
728: l->data.th->t_chasee = find_thing(mlist, l->data.th->chasee_index);
729:
730: l->data.th->t_horde = find_object(lvl_obj, l->data.th->horde_index);
731:
732: l = l->l_next;
733: }
734: }
735:
736: void
737: ur_write_monsters(FILE *savef, struct linked_list *l)
738: {
739: int cnt;
740:
741: ur_write_long(savef, URS_MONSTERLIST);
742:
743: cnt = list_size(l);
744:
745: ur_write_int(savef, cnt);
746:
747: if (cnt < 1)
748: return;
749:
750: while(l != NULL)
751: {
752: ur_write_thing(savef, l->data.th);
753: l = l->l_next;
754: }
755: }
756:
757: struct linked_list *
758: ur_read_monsters(FILE *savef)
759: {
760: long id;
761: int i,cnt;
762: struct linked_list *l=NULL, *previous = NULL, *head = NULL;
763:
764: id = ur_read_long(savef);
765:
766: assert(id == URS_MONSTERLIST);
767:
768: cnt = ur_read_int(savef);
769:
770: if (cnt == 0)
771: return(NULL);
772:
773: for(i = 0; i < cnt; i++)
774: {
775: l = new_list();
776:
777: l->l_prev = previous;
778:
779: if (previous != NULL)
780: previous->l_next = l;
781:
782: l->data.th = ur_read_thing(savef);
783:
784: if (previous == NULL)
785: head = l;
786:
787: previous = l;
788: }
789:
790: if (l != NULL)
791: l->l_next = NULL;
792:
793: return(head);
794: }
795:
796: void
797: ur_write_monster_stats(FILE *savef, struct mstats *m)
798: {
799: ur_write_long(savef, URS_MONSTERSTATS);
800: ur_write_short(savef, m->s_str);
801: ur_write_long(savef, m->s_exp);
802: ur_write_int(savef, m->s_lvl);
803: ur_write_int(savef, m->s_arm);
804: ur_write_string(savef, m->s_hpt);
805: ur_write_string(savef, m->s_dmg);
806: }
807:
808: struct mstats *
809: ur_read_monster_stats(FILE *savef)
810: {
811: long id;
812: struct mstats *m;
813:
814: id = ur_read_long(savef);
815:
816: assert(id == URS_MONSTERSTATS);
817:
818: m = ur_alloc( sizeof(struct mstats) );
819:
820: m->s_str = ur_read_short(savef);
821: m->s_exp = ur_read_long(savef);
822: m->s_lvl = ur_read_int(savef);
823: m->s_arm = ur_read_int(savef);
824: m->s_hpt = ur_read_string(savef);
825: m->s_dmg = ur_read_string(savef);
826:
827: return(m);
828: }
829:
830: void
831: ur_write_monster(FILE *savef, struct monster *m)
832: {
833: int i;
834:
835: ur_write_long(savef, URS_MONSTER);
836: ur_write_string(savef, m->m_name);
837: ur_write_short(savef, m->m_carry);
838: ur_write_int(savef, m->m_normal);
839: ur_write_int(savef, m->m_wander);
840: ur_write_char(savef, m->m_appear);
841: ur_write_string(savef, m->m_intel);
842:
843: for(i = 0; i < 10; i++)
844: ur_write_long(savef, m->m_flags[i]);
845:
846: ur_write_string(savef, m->m_typesum);
847: ur_write_short(savef, m->m_numsum);
848: ur_write_short(savef, m->m_add_exp);
849: ur_write_monster_stats(savef, &m->m_stats);
850: }
851:
852: struct monster *
853: ur_read_monster(FILE *savef)
854: {
855: struct monster *m;
856: struct mstats *mstats;
857:
858: m = ur_alloc( sizeof(struct monster) );
859:
860: m->m_name = ur_read_string(savef);
861: m->m_carry = ur_read_short(savef);
862: m->m_normal = ur_read_int(savef);
863: m->m_wander = ur_read_int(savef);
864: m->m_appear = ur_read_char(savef);
865: m->m_intel = ur_read_string(savef);
866: ur_read(savef, &m->m_flags[0], 10*sizeof(long));
867: m->m_typesum = ur_read_string(savef);
868: m->m_numsum = ur_read_short(savef);
869: m->m_add_exp = ur_read_short(savef);
870:
871: mstats = ur_read_monster_stats(savef);
872:
873: m->m_stats = *mstats;
874: ur_free(mstats);
875:
876: return(m);
877: }
878:
879: void
880: ur_write_trap(FILE *savef, struct trap *t)
881: {
882: ur_write_long(savef, URS_TRAP);
883: ur_write_coord(savef, t->tr_pos);
884: ur_write_long(savef, t->tr_flags);
885: ur_write_char(savef, t->tr_type);
886: ur_write_char(savef, t->tr_show);
887: }
888:
889: struct trap *
890: ur_read_trap(FILE *savef)
891: {
892: struct trap *t;
893: long id;
894:
895: id = ur_read_long(savef);
896:
897: assert(id == URS_TRAP);
898:
899: t = ur_alloc( sizeof(struct trap));
900:
901: t->tr_pos = ur_read_coord(savef);
902: t->tr_flags = ur_read_long(savef);
903: t->tr_type = ur_read_char(savef);
904: t->tr_show = ur_read_char(savef);
905:
906: return(t);
907: }
908:
909: void
910: ur_write_stats(FILE *savef, struct stats *s)
911: {
912: ur_write_long(savef, URS_STATS);
913: ur_write_string(savef, s->s_dmg);
914: ur_write_long(savef, s->s_exp);
915: ur_write_int(savef, s->s_hpt);
916: ur_write_int(savef, s->s_pack);
917: ur_write_int(savef, s->s_carry);
918: ur_write_int(savef, s->s_lvl);
919: ur_write_int(savef, s->s_arm);
920: ur_write_int(savef, s->s_acmod);
921: ur_write_int(savef, s->s_power);
922: ur_write_int(savef, s->s_str);
923: ur_write_int(savef, s->s_intel);
924: ur_write_int(savef, s->s_wisdom);
925: ur_write_int(savef, s->s_dext);
926: ur_write_int(savef, s->s_const);
927: ur_write_int(savef, s->s_charisma);
928: }
929:
930: struct stats *
931: ur_read_stats(FILE *savef)
932: {
933: struct stats *s;
934: long id;
935:
936: id = ur_read_long(savef);
937:
938: assert(id == URS_STATS);
939:
940: s = ur_alloc(sizeof(struct stats));
941:
942: s->s_dmg = ur_read_string(savef);
943: s->s_exp = ur_read_long(savef);
944: s->s_hpt = ur_read_int(savef);
945: s->s_pack = ur_read_int(savef);
946: s->s_carry = ur_read_int(savef);
947: s->s_lvl = ur_read_int(savef);
948: s->s_arm = ur_read_int(savef);
949: s->s_acmod = ur_read_int(savef);
950: s->s_power = ur_read_int(savef);
951: s->s_str = ur_read_int(savef);
952: s->s_intel = ur_read_int(savef);
953: s->s_wisdom = ur_read_int(savef);
954: s->s_dext = ur_read_int(savef);
955: s->s_const = ur_read_int(savef);
956: s->s_charisma = ur_read_int(savef);
957:
958: return(s);
959: }
960:
961: void
962: ur_write_thing(FILE *savef, struct thing *t)
963: {
964: int i;
965:
966: ur_write_long(savef, URS_THING);
967: ur_write_bag(savef, t->t_pack);
968: ur_write_stats(savef, &t->t_stats);
969: ur_write_stats(savef, &t->maxstats);
970: ur_write_int(savef, t->t_ischasing);
971:
972: if (t->t_chasee == &player)
973: ur_write_long(savef, -1L);
974: else if (t->t_chasee == NULL)
975: ur_write_long(savef, 0L);
976: else
977: {
978: long m;
979:
980: m = find_thing_index(mlist, t->t_chasee);
981:
982: ur_write_long(savef,m);
983: }
984:
985: ur_write_long(savef, find_list_index(lvl_obj, t->t_horde));
986: ur_write_coord(savef, t->t_pos);
987: ur_write_coord(savef, t->t_oldpos);
988: ur_write_coord(savef, t->t_nxtpos);
989:
990: for(i = 0; i < 16; i++)
991: ur_write_long(savef, t->t_flags[i]);
992:
993: ur_write_int(savef, t->t_praycnt);
994: ur_write_int(savef, t->t_trans);
995: ur_write_int(savef, t->t_turn);
996: ur_write_int(savef, t->t_wasshot);
997: ur_write_int(savef, t->t_ctype);
998: ur_write_int(savef, t->t_index);
999: ur_write_int(savef, t->t_no_move);
1000: ur_write_int(savef, t->t_rest_hpt);
1001: ur_write_int(savef, t->t_rest_pow);
1002: ur_write_int(savef, t->t_doorgoal);
1003: ur_write_char(savef, t->t_type);
1004: ur_write_char(savef, t->t_disguise);
1005: ur_write_char(savef, t->t_oldch);
1006: }
1007:
1008: struct thing *
1009: ur_read_thing(FILE *savef)
1010: {
1011: long id;
1012: int i;
1013: struct thing *t;
1014: struct stats *s;
1015:
1016: id = ur_read_long(savef);
1017:
1018: assert(id == URS_THING);
1019:
1020: t = ur_alloc( sizeof(struct thing) );
1021:
1022: t->t_pack = ur_read_bag(savef);
1023:
1024: s = ur_read_stats(savef);
1025: t->t_stats = *s;
1026: ur_free(s);
1027:
1028: s = ur_read_stats(savef);
1029: t->maxstats = *s;
1030: ur_free(s);
1031:
1032: t->t_ischasing = ur_read_int(savef);
1033: t->chasee_index = ur_read_long(savef);
1034: t->horde_index = ur_read_long(savef);
1035: t->t_pos = ur_read_coord(savef);
1036: t->t_oldpos = ur_read_coord(savef);
1037: t->t_nxtpos = ur_read_coord(savef);
1038:
1039: for(i = 0; i < 16; i++)
1040: t->t_flags[i] = ur_read_long(savef);
1041:
1042: t->t_praycnt = ur_read_int(savef);
1043: t->t_trans = ur_read_int(savef);
1044: t->t_turn = ur_read_int(savef);
1045: t->t_wasshot = ur_read_int(savef);
1046: t->t_ctype = ur_read_int(savef);
1047: t->t_index = ur_read_int(savef);
1048: t->t_no_move = ur_read_int(savef);
1049: t->t_rest_hpt = ur_read_int(savef);
1050: t->t_rest_pow = ur_read_int(savef);
1051: t->t_doorgoal = ur_read_int(savef);
1052: t->t_type = ur_read_char(savef);
1053: t->t_disguise = ur_read_char(savef);
1054: t->t_oldch = ur_read_char(savef);
1055:
1056: return(t);
1057: }
1058:
1059: void
1060: ur_write_window(FILE *savef, WINDOW *win)
1061: {
1062: int i,j;
1063:
1064: ur_write_long(savef, URS_WINDOW);
1065:
1066: ur_write_int(savef, win->_maxy);
1067: ur_write_int(savef, win->_maxx);
1068:
1069: for(i=0; i < win->_maxy; i++)
1070: for(j = 0; j < win->_maxx; j++)
1071: ur_write_ulong(savef, mvwinch(win,i,j));
1072: }
1073:
1074: void
1075: ur_read_window(FILE *savef, WINDOW *win)
1076: {
1077: int i,j;
1078: int maxy, maxx;
1079: long id;
1080:
1081: id = ur_read_long(savef);
1082:
1083: assert(id == URS_WINDOW);
1084:
1085: maxy = ur_read_int(savef);
1086: maxx = ur_read_int(savef);
1087:
1088: for(i=0; i < maxy; i++)
1089: for(j = 0; j < maxx; j++)
1090: mvwaddch(win,i,j,ur_read_long(savef));
1091: }
1092:
1093: void
1094: ur_write_daemons(FILE *savef)
1095: {
1096: int i;
1097: int id=0;
1098:
1099: ur_write_long(savef, URS_DAEMONS);
1100:
1101: for(i = 0; i < MAXDAEMONS; i++)
1102: {
1103: ur_write_int(savef, d_list[i].d_type );
1104: ur_write_int(savef, d_list[i].d_when );
1105: ur_write_int(savef, d_list[i].d_id);
1106:
1107: if (d_list[i].d_id == FUSE_UNSUMMON)
1108: id = find_thing_index(mlist, d_list[i].d_arg);
1109:
1110: if (d_list[i].d_id == DAEMON_DOCTOR)
1111: id = find_thing_index(mlist, d_list[i].d_arg);
1112:
1113: ur_write_int(savef, id);
1114: ur_write_int(savef, d_list[i].d_time );
1115: }
1116: }
1117:
1118: void
1119: ur_read_daemons(FILE *savef)
1120: {
1121: long id;
1122: int i;
1123: demoncnt = 0;
1124:
1125: id = ur_read_long(savef);
1126:
1127: assert(id == URS_DAEMONS);
1128:
1129: for(i = 0; i < MAXDAEMONS; i++)
1130: {
1131: d_list[i].d_type = ur_read_int(savef);
1132: d_list[i].d_when = ur_read_int(savef);
1133: d_list[i].d_id = ur_read_int(savef);
1134: id = ur_read_int(savef);
1135: d_list[i].d_time = ur_read_int(savef);
1136:
1137: if ((d_list[i].d_type != EMPTY) && (d_list[i].d_id == FUSE_UNSUMMON))
1138: {
1139: d_list[i].d_arg = find_thing(mlist,id);
1140:
1141: if (d_list[i].d_arg == NULL)
1142: d_list[i].d_type = EMPTY;
1143: }
1144:
1145: if ((d_list[i].d_type != EMPTY) && (d_list[i].d_id == DAEMON_DOCTOR) )
1146: {
1147: if (id == 0)
1148: d_list[i].d_arg = &player;
1149: else
1150: d_list[i].d_arg = find_thing(mlist, id);
1151:
1152: if (d_list[i].d_arg == NULL)
1153: d_list[i].d_type = EMPTY;
1154: }
1155:
1156: if (d_list[i].d_type != EMPTY)
1157: demoncnt++;
1158: }
1159: }
1160:
1161: void
1162: save_file(FILE *savef)
1163: {
1164: int i,weapon,armor,ring=0,room= -1,monster;
1165:
1166: ur_write_string(savef, save_format);
1167:
1168: ur_write_string(savef,"\nScroll Names\n");
1169: for(i = 0; i < MAXSCROLLS; i++)
1170: ur_write_string(savef,s_names[i]);
1171:
1172: ur_write_string(savef,"\nPotion Colors\n");
1173: for(i = 0; i < MAXPOTIONS; i++)
1174: ur_write_string(savef,p_colors[i]);
1175:
1176: ur_write_string(savef,"\nRing Stones\n");
1177: for(i = 0; i < MAXRINGS; i++)
1178: ur_write_string(savef,r_stones[i]);
1179:
1180: ur_write_string(savef,"\nStick types\n");
1181: for(i = 0; i < MAXSTICKS; i++)
1182: ur_write_string(savef,ws_made[i]);
1183:
1184: ur_write_string(savef,"\nStick types\n");
1185: for(i = 0; i < MAXSTICKS; i++)
1186: ur_write_string(savef,ws_type[i]);
1187:
1188: ur_write_string(savef, "\nTraps on this level\n");
1189: ur_write_int(savef, MAXTRAPS);
1190: for(i = 0; i < MAXTRAPS; i++)
1191: ur_write_trap(savef, &traps[i]);
1192:
1193: ur_write_string(savef,"\nRooms on this level\n");
1194: ur_write_int(savef, MAXROOMS);
1195: for(i = 0; i < MAXROOMS; i++)
1196: {
1197: ur_write_room(savef, &rooms[i]);
1198:
1199: if (&rooms[i] == oldrp)
1200: room = i;
1201: }
1202: ur_write_int(savef,room); /* save for recovery of oldrp */
1203:
1204: ur_write_string(savef,"\nThe Rogue\n");
1205: ur_write_thing(savef, &player);
1206:
1207: ur_write_string(savef,"\nObjects on this level\n");
1208: ur_write_bag(savef, lvl_obj);
1209:
1210: ur_write_string(savef,"\nRogue's Familiar, if any \n");
1211: ur_write_monsters(savef, fam_ptr);
1212:
1213: ur_write_string(savef,"\nMonsters on this level\n");
1214: ur_write_monsters(savef, mlist);
1215:
1216: monster = find_thing_index(mlist, beast);
1217: ur_write_int(savef, monster);
1218:
1219: ur_write_string(savef,"\nItems in use by rogue\n");
1220: weapon = find_list_index(player.t_pack, cur_weapon);
1221: armor = find_list_index(player.t_pack, cur_armor);
1222: ur_write_int(savef, weapon);
1223: ur_write_int(savef, armor);
1224:
1225: for(i=0; i < 10; i++)
1226: {
1227: if (cur_ring[i] == NULL)
1228: ring = find_list_index(player.t_pack, cur_ring[i]);
1229:
1230: ur_write_int(savef, ring);
1231: }
1232:
1233: ur_write_string(savef,"\nActive Daemons and Fuses\n");
1234: ur_write_daemons(savef);
1235:
1236: ur_write_string(savef, "\nMisc\n");
1237:
1238: for(i = 0; i < 10; i++)
1239: ur_write_string(savef, msgbuf[i]);
1240:
1241: ur_write_int(savef, msg_index);
1242: ur_write_int(savef, foodlev);
1243: ur_write_int(savef, ntraps);
1244: ur_write_int(savef, dnum);
1245: ur_write_int(savef, max_level);
1246: ur_write_int(savef, lost_dext);
1247: ur_write_int(savef, no_command);
1248: ur_write_int(savef, level);
1249: ur_write_int(savef, see_dist);
1250: ur_write_int(savef, no_food);
1251: ur_write_int(savef, count);
1252: ur_write_int(savef, food_left);
1253: ur_write_int(savef, group);
1254: ur_write_int(savef, hungry_state);
1255: ur_write_int(savef, infest_dam);
1256: ur_write_int(savef, lost_str);
1257: ur_write_int(savef, hold_count);
1258: ur_write_int(savef, trap_tries);
1259: ur_write_int(savef, has_artifact);
1260: ur_write_int(savef, picked_artifact);
1261: ur_write_int(savef, luck);
1262: ur_write_int(savef, resurrect);
1263: ur_write_int(savef, fam_type);
1264: ur_write_int(savef, mons_summoned);
1265: ur_write_char(savef, PLAYER);
1266: ur_write_char(savef, take);
1267: ur_write_char(savef, runch);
1268: ur_write_int(savef, char_type);
1269: ur_write_int(savef, inv_type);
1270: ur_write_int(savef, pool_teleport);
1271: ur_write_int(savef, inwhgt);
1272: ur_write_int(savef, after);
1273: ur_write_int(savef, waswizard);
1274: ur_write_int(savef, canwizard);
1275: ur_write_int(savef, playing);
1276: ur_write_int(savef, running);
1277: ur_write_int(savef, fighting);
1278: ur_write_int(savef, wizard);
1279: ur_write_int(savef, wiz_verbose);
1280: ur_write_int(savef, moving);
1281: ur_write_coord(savef, delta);
1282: ur_write_int(savef, levtype);
1283: ur_write_int(savef, purse);
1284: ur_write_int(savef, total);
1285: ur_write_window(savef, cw);
1286: ur_write_window(savef, hw);
1287: ur_write_window(savef, mw);
1288: ur_write_window(savef, stdscr);
1289:
1290: ur_write_string(savef,"\nGame Options\n");
1291: ur_write_int(savef, terse);
1292: ur_write_int(savef, door_stop);
1293: ur_write_int(savef, doorstop);
1294: ur_write_int(savef, jump);
1295: ur_write_int(savef, firstmove);
1296: ur_write_int(savef, askme);
1297: ur_write_string(savef,whoami);
1298: ur_write_string(savef,fruit);
1299: ur_write_string(savef,file_name);
1300: ur_write_string(savef,score_file);
1301:
1302: ur_write_string(savef,"\nEnd of UltraRogue Game State\n");
1303: }
1304:
1305: #define DUMPSTRING { str = ur_read_string(savef); /*printf("%s",str);*/ ur_free(str); }
1306:
1307: int
1308: restore_file(FILE *savef)
1309: {
1310: int i,j;
1311: char *str;
1312: struct trap *t;
1313: struct room *r;
1314: struct thing *p;
1315:
1316: str = ur_read_string(savef);
1317:
1318: if (strcmp(str, save_format) != 0)
1319: {
1320: printf("Save Game Version: %s\n", str);
1321: printf("Real Game Version: %s\n", save_format);
1322: printf("Sorry, versions don't match.\n");
1323: return(FALSE);
1324: }
1325:
1326: DUMPSTRING
1327: for(i=0; i < MAXSCROLLS; i++)
1328: s_names[i] = ur_read_string(savef);
1329:
1330: DUMPSTRING
1331: for(i=0; i < MAXPOTIONS; i++)
1332: p_colors[i] = ur_read_string(savef);
1333:
1334: DUMPSTRING
1335: for(i=0; i < MAXRINGS; i++)
1336: r_stones[i] = ur_read_string(savef);
1337:
1338: DUMPSTRING
1339: for(i=0; i < MAXSTICKS; i++)
1340: ws_made[i] = ur_read_string(savef);
1341:
1342: DUMPSTRING
1343: for(i=0; i < MAXSTICKS; i++)
1344: ws_type[i] = ur_read_string(savef);
1345:
1346: DUMPSTRING
1347: i = ur_read_int(savef);
1348: assert(i == MAXTRAPS);
1349:
1350: for(i=0;i<MAXTRAPS;i++)
1351: {
1352: t = ur_read_trap(savef);
1353: traps[i] = *t;
1354: ur_free(t);
1355: }
1356:
1357: DUMPSTRING
1358: i = ur_read_int(savef);
1359: assert(i == MAXROOMS);
1360:
1361: for(i=0;i<MAXROOMS;i++)
1362: {
1363: r = ur_read_room(savef);
1364: rooms[i] = *r;
1365: ur_free(r);
1366: }
1367: i = ur_read_int(savef);
1368: oldrp = &rooms[i];
1369:
1370: DUMPSTRING
1371: p = ur_read_thing(savef);
1372: player = *p;
1373: ur_free(p);
1374:
1375: DUMPSTRING
1376: lvl_obj = ur_read_bag(savef);
1377:
1378: DUMPSTRING
1379: fam_ptr = ur_read_monsters(savef);
1380:
1381: DUMPSTRING
1382: mlist = ur_read_monsters(savef);
1383: i = ur_read_int(savef);
1384: beast = find_thing(mlist, i);
1385:
1386: ur_fixup_monsters(fam_ptr);
1387: ur_fixup_monsters(mlist);
1388:
1389: DUMPSTRING
1390: i = ur_read_int(savef);
1391: cur_weapon = find_object(player.t_pack, i);
1392:
1393: i = ur_read_int(savef);
1394: cur_armor = find_object(player.t_pack, i);
1395:
1396: for(j=0; j < 10; j++)
1397: {
1398: i = ur_read_int(savef);
1399: if (i == -1)
1400: cur_ring[j] = NULL;
1401: else
1402: cur_ring[j] = find_object(player.t_pack, i);
1403: }
1404:
1405: DUMPSTRING
1406: ur_read_daemons(savef);
1407:
1408: DUMPSTRING
1409: for(i = 0; i < 10; i++)
1410: {
1411: str = ur_read_string(savef);
1412: strcpy(&msgbuf[i][0],str);
1413: ur_free(str);
1414: }
1415:
1416: msg_index = ur_read_int(savef);
1417:
1418: foodlev = ur_read_int(savef);
1419: ntraps = ur_read_int(savef);
1420: dnum = ur_read_int(savef);
1421: max_level = ur_read_int(savef);
1422: lost_dext = ur_read_int(savef);
1423: no_command = ur_read_int(savef);
1424: level = ur_read_int(savef);
1425: see_dist = ur_read_int(savef);
1426: no_food = ur_read_int(savef);
1427: count = ur_read_int(savef);
1428: food_left = ur_read_int(savef);
1429: group = ur_read_int(savef);
1430: hungry_state = ur_read_int(savef);
1431: infest_dam = ur_read_int(savef);
1432: lost_str = ur_read_int(savef);
1433: hold_count = ur_read_int(savef);
1434: trap_tries = ur_read_int(savef);
1435: has_artifact = ur_read_int(savef);
1436: picked_artifact = ur_read_int(savef);
1437: luck = ur_read_int(savef);
1438: resurrect = ur_read_int(savef);
1439: fam_type = ur_read_int(savef);
1440: mons_summoned = ur_read_int(savef);
1441: PLAYER = ur_read_char(savef);
1442: take = ur_read_char(savef);
1443: runch = ur_read_char(savef);
1444: char_type = ur_read_int(savef);
1445: inv_type = ur_read_int(savef);
1446: pool_teleport = ur_read_int(savef);
1447: inwhgt = ur_read_int(savef);
1448: after = ur_read_int(savef);
1449: waswizard = ur_read_int(savef);
1450: canwizard = ur_read_int(savef);
1451: playing = ur_read_int(savef);
1452: running = ur_read_int(savef);
1453: fighting = ur_read_int(savef);
1454: wizard = ur_read_int(savef);
1455: wiz_verbose = ur_read_int(savef);
1456: moving = ur_read_int(savef);
1457: delta = ur_read_coord(savef);
1458: levtype = ur_read_int(savef);
1459: purse = ur_read_int(savef);
1460: total = ur_read_int(savef);
1461: ur_read_window(savef, cw);
1462: ur_read_window(savef, hw);
1463: ur_read_window(savef, mw);
1464: ur_read_window(savef, stdscr);
1465:
1466: DUMPSTRING
1467: terse = ur_read_int(savef);
1468: door_stop = ur_read_int(savef);
1469: doorstop = ur_read_int(savef);
1470: jump = ur_read_int(savef);
1471: firstmove = ur_read_int(savef);
1472: askme = ur_read_int(savef);
1473: str = ur_read_string(savef);
1474: strcpy(whoami,str);
1475: ur_free(str);
1476: str = ur_read_string(savef);
1477: strcpy(fruit,str);
1478: ur_free(str);
1479: str = ur_read_string(savef);
1480: // The file_name stored in the file no longer replaces its actual name.
1481: ur_free(str);
1482: str = ur_read_string(savef);
1483: if (!use_savedir)
1484: strcpy(score_file,str);
1485: ur_free(str);
1486:
1487: DUMPSTRING
1488: return(TRUE);
1489: }
1490:
1491:
CVSweb