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)