Mercurial > hg > early-roguelike
diff urogue/state.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | 2908dc47f9e2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/state.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,1445 @@ +/* + state.c - Portable Rogue Save State Code + + Copyright (C) 1993, 1995 Nicholas J. Kisseberth + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + Notes + + Should move all game variables into one place + Should move save/restore code into save.c or some such +*/ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "rogue.h" + +/* + Variables for global game state. + + All variables that need to get saved when saving a game + are defined in this file. Long term goal is to move many + of these variables into a "struct level" data type of some + kind... perhaps not, maybe struct game... + + Other global variables that don't need to get saved are + kept in main.c. + + Other global variables that don't change during the course + of a game are kept in urogue.c, monsdata.c, data.c. +*/ + +#define _X_ { 0, 0, 0, 0, 0 } + +struct delayed_action +d_list[MAXDAEMONS] = /* daemon/fuse list */ +{ + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, +}; + +#undef _X_ + +char *s_names[MAXSCROLLS]; /* Names of the scrolls */ +char *p_colors[MAXPOTIONS]; /* Colors of the potions */ +char *r_stones[MAXRINGS]; /* Stone settings of the rings */ +char *ws_made[MAXSTICKS]; /* What sticks are made of */ +char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */ + +char *guess_items[MAXMAGICTYPES][MAXMAGICITEMS]; /* guess magic is */ +int know_items[MAXMAGICTYPES][MAXMAGICITEMS]; /* flag knowlede of magic */ + /* object data */ + +struct trap traps[2 * MAXTRAPS]; /* 2x for special effects */ +struct room rooms[MAXROOMS]; /* One for each room -- A level */ +struct room *oldrp = NULL; /* Roomin(&player.t_oldpos) */ +struct thing player; /* The rogue */ +struct linked_list *lvl_obj = NULL; /* Treasure on this level */ +struct linked_list *fam_ptr = NULL; /* A ptr to the familiar */ +struct linked_list *mlist = NULL; /* Monsters on this level */ +struct thing *beast; /* The last beast that attacked */ +struct object *cur_armor = NULL; /* what rogue wears */ +struct object *cur_weapon = NULL; /* ... and wields */ +struct object *cur_ring[10]; /* His rings */ +struct linked_list *curr_mons = NULL; /* The mons. currently moving */ +struct linked_list *next_mons = NULL; /* The mons. after curr_mons */ + +/* Misc. game state info */ +char dummybuf1[50000]; +char dummybuf2[50000]; +char msgbuf[10][2*LINELEN]; /* message buffer history */ +int msg_index = 0; /* index in msg history buffer for nxt msg */ +int foodlev = 1; /* how fast he eats food */ +int ntraps = 0; /* Number of traps on this level */ +int dnum = 0; /* Dungeon number */ +int max_level = 0; /* Deepest player has gone */ +int lost_dext = 0; /* amount of lost dexterity */ +int no_command = 0; +int level = 0; +int see_dist = 3; +int no_food = 0; +int count = 0; +int food_left = HUNGERTIME; +int group = 1; +int hungry_state = F_OK; +int infest_dam = 0; +int lost_str = 0; +int hold_count = 0; +int trap_tries = 0; +int has_artifact = 0; +int picked_artifact = 0; +int luck = 0; +int resurrect = 0; +int fam_type = 0; /* The type of familiar */ +int mons_summoned = 0; /* Number of summoned monsters */ +char PLAYER = VPLAYER; /* what the player looks like */ +char take = 0; /* Thing the rogue is taking */ +char runch = 0; /* Direction player is running */ +int char_type = C_NOTSET; /* what type of character is player */ +int inv_type = INV_CLEAR; /* Overwrite style of inventory */ +int pool_teleport = FALSE; /* just teleported from a pool */ +int inwhgt = FALSE; /* true if from wghtchk() */ +int after = 0; /* True if we want after daemons */ +int waswizard = 0; /* Was a wizard sometime */ +int canwizard = 1; /* Will be permitted to do this */ +int playing = TRUE; +int running = FALSE; +int fighting = FALSE; +int wizard = FALSE; +int wiz_verbose = TRUE; +int moving = FALSE; +coord delta; /* Change indicated to get_dir() */ +LEVTYPE levtype; /* type of level i'm on */ +long purse = 0; +unsigned long total = 0; + +WINDOW *cw; /* Window that the player sees */ +WINDOW *hw; /* Used for the help command */ +WINDOW *mw; /* Used to store mosnters */ + +/* options.o */ +/* game options */ + +int terse = FALSE; +int door_stop = FALSE; +int jump = TRUE; +int doorstop = TRUE; +int firstmove = FALSE; +int askme = FALSE; +char whoami[2 * LINELEN]; /* Name of player */ +char fruit[2 * LINELEN]; /* Favorite fruit */ +char file_name[2 * LINELEN]; /* Save file name */ +char score_file[2 * LINELEN]; /* Score file name */ + +/****************************************************************************/ +/* Portable Save State Code */ +/* */ +/* UltraRogue v1.04 */ +/****************************************************************************/ + +#define URS_STATS 0xABCD0001 +#define URS_THING 0xABCD0002 +#define URS_OBJECT 0xABCD0003 +#define URS_MAGIC 0xABCD0004 +#define URS_KNOWS 0xABCD0005 +#define URS_GUESSES 0xABCD0006 +#define URS_STACKOBJECT 0xABCD0007 +#define URS_BAGOBJECT 0xABCD0008 +#define URS_MONSTERLIST 0xABCD0009 +#define URS_MONSTERSTATS 0xABCD000A +#define URS_MONSTER 0xABCD000B +#define URS_TRAP 0xABCD000C +#define URS_WINDOW 0xABCD000D +#define URS_DAEMONS 0xABCD000E + +void +ur_write(FILE *savef, void *ptr, size_t size) +{ + if (size == 0) + return; + + fwrite(ptr,size,1,savef); +} + +void +ur_read(FILE *savef, void *ptr, size_t size) +{ + if (size == 0) + return; + + fread(ptr,size,1,savef); +} + +void +ur_write_int(FILE *savef, int c) +{ + ur_write(savef,&c,sizeof(int)); +} + +int +ur_read_int(FILE *savef) +{ + int i; + + ur_read(savef, &i, sizeof(int)); + + return(i); +} + +void +ur_write_short(FILE *savef, short c) +{ + ur_write(savef,&c,sizeof(short)); +} + +short +ur_read_short(FILE *savef) +{ + short s; + + ur_read(savef, &s, sizeof(short)); + + return(s); +} + +void +ur_write_long(FILE *savef, long c) +{ + ur_write(savef,&c,sizeof(long)); +} + +long +ur_read_long(FILE *savef) +{ + long l; + + ur_read(savef, &l, sizeof(long)); + + return(l); +} + +void +ur_write_ulong(FILE *savef, unsigned long c) +{ + ur_write(savef,&c,sizeof(unsigned long)); +} + +unsigned long +ur_read_ulong(FILE *savef) +{ + long l; + + ur_read(savef, &l, sizeof(unsigned long)); + + return(l); +} + +void +ur_unread_long(FILE *savef) +{ + fseek(savef, -(long)sizeof(long), SEEK_CUR); +} + +void +ur_write_char(FILE *savef, char c) +{ + ur_write(savef,&c,sizeof(char)); +} + +char +ur_read_char(FILE *savef) +{ + char c; + + ur_read(savef, &c, sizeof(char)); + + return(c); +} + +void +ur_write_string(FILE *savef, char *s) +{ + size_t len; + + len = (s == NULL) ? 0L : strlen(s) + 1 ; + + ur_write_long(savef, (long) len); + ur_write(savef,s,len); +} + + +char * +ur_read_string(FILE *savef) +{ + size_t len; + char *buf; + + len = ur_read_long(savef); + + if (len == 0) + return(NULL); + + buf = ur_alloc(len); + + if (buf == NULL) /* Should flag a global error condition... */ + return(NULL); + + ur_read(savef,buf,len); + + return(buf); +} + +void +ur_write_coord(FILE *savef, coord c) +{ + ur_write_int(savef, c.x); + ur_write_int(savef, c.y); +} + +coord +ur_read_coord(FILE *savef) +{ + coord c; + + c.x = ur_read_int(savef); + c.y = ur_read_int(savef); + + return(c); +} + +void +ur_write_room(FILE *savef, struct room *r) +{ + int i; + + ur_write_coord(savef, r->r_pos); + ur_write_coord(savef, r->r_max); + + for(i=0; i<MAXDOORS; i++) + ur_write_coord(savef, r->r_exit[i]); + + ur_write_int(savef, r->r_flags); + ur_write_int(savef, r->r_nexits); + ur_write_int(savef, r->r_flags); +} + +struct room * +ur_read_room(FILE *savef) +{ + struct room *r; + int i; + + r = ur_alloc( sizeof(struct room) ); + + r->r_pos = ur_read_coord(savef); + r->r_max = ur_read_coord(savef); + + for(i=0; i<MAXDOORS; i++) + r->r_exit[i] = ur_read_coord(savef); + + r->r_flags = ur_read_int(savef); + r->r_nexits = ur_read_int(savef); + r->r_flags = ur_read_short(savef); + + return(r); +} + +void +ur_write_object(FILE *savef, struct object *o) +{ + int other; + + ur_write_long(savef, URS_OBJECT); + ur_write_coord(savef, o->o_pos); + ur_write_string(savef, o->o_text); + ur_write_string(savef, o->o_damage); + ur_write_string(savef, o->o_hurldmg); + ur_write_long(savef, o->o_flags); + ur_write_long(savef, o->ar_flags); + ur_write_char(savef, o->o_type); + ur_write_int(savef, o->o_ident); + ur_write_int(savef, o->o_count); + ur_write_int(savef, o->o_which); + ur_write_int(savef, o->o_hplus); + ur_write_int(savef, o->o_dplus); + ur_write_int(savef, o->o_ac); + ur_write_int(savef, o->o_group); + ur_write_int(savef, o->o_weight); + ur_write_char(savef, o->o_launch); + ur_write(savef, &o->o_mark[0], MARKLEN); + ur_write_long(savef, o->o_worth); + + other = 0; + + if (o->o_bag) + other = 1; + else if (o->next_obj) + other |= 2; + + ur_write_int(savef,other); + + if (o->o_bag) + ur_write_bag(savef,o->o_bag); + if (o->next_obj && (o->next_obj->l_prev == NULL) ) + ur_write_object_stack(savef, o->next_obj); +} + +struct object * +ur_read_object(FILE *savef) +{ + struct object *o; + long id; + int other; + + o = ur_alloc(sizeof(struct object)); + + if (o == NULL) + return(NULL); + + memset(o,0,sizeof(struct object)); + + id = ur_read_long(savef); + + assert(id == URS_OBJECT); + + o->o_pos = ur_read_coord(savef); + o->o_text = ur_read_string(savef); + o->o_damage = ur_read_string(savef); + o->o_hurldmg = ur_read_string(savef); + o->o_flags = ur_read_long(savef); + o->ar_flags = ur_read_long(savef); + o->o_type = ur_read_char(savef); + o->o_ident = ur_read_int(savef); + o->o_count = ur_read_int(savef); + o->o_which = ur_read_int(savef); + o->o_hplus = ur_read_int(savef); + o->o_dplus = ur_read_int(savef); + o->o_ac = ur_read_int(savef); + o->o_group = ur_read_int(savef); + o->o_weight = ur_read_int(savef); + o->o_launch = ur_read_char(savef); + ur_read(savef, &o->o_mark[0], MARKLEN); + o->o_worth = ur_read_long(savef); + + other = ur_read_int(savef); + + if (other & 1) + o->o_bag = ur_read_bag(savef); + if (other & 2) + o->next_obj = ur_read_object_stack(savef); + + return(o); +} + +int +list_size(struct linked_list *l) +{ + int cnt=0; + + if (l == NULL) + return(0); + + while(l != NULL) + { + cnt++; + l = l->l_next; + } + + return(cnt); +} + +int +find_thing_index(struct linked_list *l, struct thing *item) +{ + int cnt=0; + + if (l == NULL) + return(-1); + + while(l != NULL) + { + if (item == l->data.th) + return(cnt+1); + + cnt++; + l = l->l_next; + } + + return(0); +} + + +int +find_list_index(struct linked_list *l, struct object *item) +{ + int cnt=0; + + if (l == NULL) + return(-1); + + while(l != NULL) + { + if (item == l->data.obj) + return(cnt+1); + + cnt++; + l = l->l_next; + } + + return(0); +} + +struct object * +find_object(struct linked_list *list, int num) +{ + int cnt = 0; + struct linked_list *l = list; + + if ( (num < 1) || (list == NULL) ) + return(NULL); + + num--; + + for(cnt = 0; cnt < num; cnt++) + { + if ( l == NULL ) + return(NULL); + + l = l->l_next; + } + + return(l->data.obj); +} + +struct thing * +find_thing(struct linked_list *list, int num) +{ + int cnt = 0; + struct linked_list *l = list; + + if ( (num < 1) || (list == NULL) ) + return(NULL); + num--; + + for(cnt = 0; cnt < num; cnt++) + { + if (l == NULL) + return(NULL); + + l = l->l_next; + } + + return(l->data.th); +} + + +void +ur_write_object_stack(FILE *savef, struct linked_list *l) +{ + int cnt; + + ur_write_long(savef, URS_STACKOBJECT); + + ur_write_int(savef, cnt = list_size(l) ); + + if (cnt == 0) + return; + + while(l != NULL) + { + ur_write_object(savef, l->data.obj); + l = l->l_next; + } +} + +void +ur_write_bag(FILE *savef, struct linked_list *l) +{ + int cnt; + + ur_write_long(savef, URS_BAGOBJECT); + + ur_write_int(savef, cnt = list_size(l) ); + + if (cnt == 0) + return; + + while(l != NULL) + { + ur_write_object(savef, l->data.obj); + l = l->l_next; + } +} + +struct linked_list * +ur_read_object_stack(FILE *savef) +{ + long id; + int i,cnt; + struct linked_list *l = NULL, *previous = NULL, *head = NULL; + + id = ur_read_long(savef); + + assert(id == URS_STACKOBJECT); + + cnt = ur_read_int(savef); + + for(i = 0; i < cnt; i++) + { + l = new_list(); + l->l_prev = previous; + + if (previous != NULL) + previous->l_next = l; + + l->data.obj = ur_read_object(savef); + + if (previous == NULL) + head = l; + + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + return(head); +} + + +struct linked_list * +ur_read_bag(FILE *savef) +{ + long id; + int i,cnt; + struct linked_list *l = NULL, *previous = NULL, *head = NULL; + + id = ur_read_long(savef); + + assert( id == URS_BAGOBJECT ); + + cnt = ur_read_int(savef); + + for(i = 0; i < cnt; i++) + { + l = new_list(); + l->l_prev = previous; + + if (previous != NULL) + previous->l_next = l; + + l->data.obj = ur_read_object(savef); + + if (previous == NULL) + head = l; + + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + return(head); +} + +void +ur_fixup_monsters(struct linked_list *l) +{ + while(l != NULL) + { + if (l->data.th->t_chasee == (void *) -1L)