Mercurial > hg > early-roguelike
diff rogue5/state.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children | 09db0cf536af |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue5/state.c Mon May 24 20:10:59 2010 +0000 @@ -0,0 +1,1450 @@ +/* + state.c - Portable Rogue Save State Code + + Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth + All rights reserved. + + 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. +*/ + +#include <stdlib.h> +#include <string.h> +#include <curses.h> +#include <errno.h> +#include "rogue.h" + +/************************************************************************/ +/* Save State Code */ +/************************************************************************/ + +#define RSID_STATS 0xABCD0001 +#define RSID_THING 0xABCD0002 +#define RSID_THING_NULL 0xDEAD0002 +#define RSID_OBJECT 0xABCD0003 +#define RSID_MAGICITEMS 0xABCD0004 +#define RSID_KNOWS 0xABCD0005 +#define RSID_GUESSES 0xABCD0006 +#define RSID_OBJECTLIST 0xABCD0007 +#define RSID_BAGOBJECT 0xABCD0008 +#define RSID_MONSTERLIST 0xABCD0009 +#define RSID_MONSTERSTATS 0xABCD000A +#define RSID_MONSTERS 0xABCD000B +#define RSID_TRAP 0xABCD000C +#define RSID_WINDOW 0xABCD000D +#define RSID_DAEMONS 0xABCD000E +#define RSID_IWEAPS 0xABCD000F +#define RSID_IARMOR 0xABCD0010 +#define RSID_SPELLS 0xABCD0011 +#define RSID_ILIST 0xABCD0012 +#define RSID_HLIST 0xABCD0013 +#define RSID_DEATHTYPE 0xABCD0014 +#define RSID_CTYPES 0XABCD0015 +#define RSID_COORDLIST 0XABCD0016 +#define RSID_ROOMS 0XABCD0017 + +#define READSTAT (format_error || read_error ) +#define WRITESTAT (write_error) + +static int read_error = FALSE; +static int write_error = FALSE; +static int format_error = FALSE; +static int endian = 0x01020304; +#define big_endian ( *((char *)&endian) == 0x01 ) + +void +rs_write(FILE *savef, const void *ptr, size_t size) +{ + encwrite(ptr, size, savef); +} + +void +rs_read(FILE *savef, void *ptr, size_t size) +{ + encread(ptr, size, savef); +} + +void +rs_write_int(FILE *savef, int c) +{ + char bytes[4]; + char *buf = (char *) &c; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); +} + +void +rs_read_int(FILE *savef, int *i) +{ + char bytes[4]; + int input = 0; + char *buf = (char *)&input; + + rs_read(savef, &input, 4); + + if (encerror()) + return; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((int *) buf); +} + +void +rs_write_uint(FILE *savef, unsigned int c) +{ + char bytes[4]; + char *buf = (char *) &c; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); +} + +void +rs_read_uint(FILE *savef, unsigned int *i) +{ + char bytes[4]; + int input = 0; + char *buf = (char *)&input; + + rs_read(savef, &input, 4); + + if (encerror()) + return; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((unsigned int *) buf); +} + +void +rs_write_chars(FILE *savef, const char *c, int cnt) +{ + rs_write_int(savef, cnt); + rs_write(savef, c, cnt); +} + +void +rs_read_chars(FILE *savef, char *i, int cnt) +{ + int value = 0; + + rs_read_int(savef, &value); + + if (!encerror() && (value != cnt)) + encseterr(EILSEQ); + + rs_read(savef, i, cnt); +} + +void +rs_write_ints(FILE *savef, int *c, int cnt) +{ + int n = 0; + + rs_write_int(savef, cnt); + + for(n = 0; n < cnt; n++) + rs_write_int(savef,c[n]); +} + +void +rs_read_ints(FILE *savef, int *i, int cnt) +{ + int n, value; + + rs_read_int(savef,&value); + + if (!encerror() && (value != cnt)) + encseterr(EILSEQ); + + for(n = 0; n < cnt; n++) + rs_read_int(savef, &i[n]); +} + +void +rs_write_marker(FILE *savef, int id) +{ + rs_write_int(savef, id); +} + +void +rs_read_marker(FILE *savef, int id) +{ + int nid; + + rs_read_int(savef, &nid); + + if (!encerror() && (id != nid)) + encseterr(EILSEQ); +} + +/******************************************************************************/ + +void +rs_write_string(FILE *savef, const char *s) +{ + int len = 0; + + len = (s == NULL) ? 0 : (int) strlen(s) + 1; + + rs_write_int(savef, len); + rs_write_chars(savef, s, len); +} + +void +rs_read_string(FILE *savef, char *s, int max) +{ + int len = 0; + + rs_read_int(savef, &len); + + if (!encerror() && (len > max)) + encseterr(EILSEQ); + + rs_read_chars(savef, s, len); +} + +void +rs_read_new_string(FILE *savef, char **s) +{ + int len=0; + char *buf=0; + + rs_read_int(savef, &len); + + if (encerror()) + return; + + if (len == 0) + buf = NULL; + else + { + buf = malloc(len); + + if (buf == NULL) + encseterr(ENOMEM); + } + + rs_read_chars(savef, buf, len); + + *s = buf; +} + +void +rs_write_string_index(FILE *savef, const char *master[], int max, const char *str) +{ + int i; + + for(i = 0; i < max; i++) + if (str == master[i]) + { + rs_write_int(savef, i); + return; + } + + rs_write_int(savef,-1); +} + +void +rs_read_string_index(FILE *savef, const char *master[], int maxindex, const char **str) +{ + int i; + + rs_read_int(savef, &i); + + if (!encerror() && (i > maxindex)) + encseterr(EILSEQ); + else if (i >= 0) + *str = master[i]; + else + *str = NULL; +} + +void +rs_write_coord(FILE *savef, coord c) +{ + rs_write_int(savef, c.x); + rs_write_int(savef, c.y); +} + +void +rs_read_coord(FILE *savef, coord *c) +{ + coord in; + + rs_read_int(savef,&in.x); + rs_read_int(savef,&in.y); + + if (!encerror()) + { + c->x = in.x; + c->y = in.y; + } +} + +void +rs_write_window(FILE *savef, WINDOW *win) +{ + int row,col,height,width; + + width = getmaxx(win); + height = getmaxy(win); + + rs_write_marker(savef,RSID_WINDOW); + rs_write_int(savef,height); + rs_write_int(savef,width); + + for(row=0;row<height;row++) + for(col=0;col<width;col++) + rs_write_int(savef, mvwinch(win,row,col)); +} + +void +rs_read_window(FILE *savef, WINDOW *win) +{ + int row,col,maxlines,maxcols,value,width,height; + + width = getmaxx(win); + height = getmaxy(win); + + rs_read_marker(savef, RSID_WINDOW); + + rs_read_int(savef, &maxlines); + rs_read_int(savef, &maxcols); + + if (encerror()) + return; + + for(row = 0; row < maxlines; row++) + for(col = 0; col < maxcols; col++) + { + rs_read_int(savef, &value); + + if ((row < height) && (col < width)) + mvwaddch(win,row,col,value); + } +} + +/******************************************************************************/ + +void * +get_list_item(THING *l, int i) +{ + int cnt; + + for(cnt = 0; l != NULL; cnt++, l = l->l_next) + if (cnt == i) + return(l); + + return(NULL); +} + +int +find_list_ptr(THING *l, void *ptr) +{ + int cnt; + + for(cnt = 0; l != NULL; cnt++, l = l->l_next) + if (l == ptr) + return(cnt); + + return(-1); +} + +int +list_size(THING *l) +{ + int cnt; + + for(cnt = 0; l != NULL; cnt++, l = l->l_next) + ; + + return(cnt); +} + +/******************************************************************************/ + +void +rs_write_stats(FILE *savef, struct stats *s) +{ + rs_write_marker(savef, RSID_STATS); + rs_write_int(savef, s->s_str); + rs_write_int(savef, s->s_exp); + rs_write_int(savef, s->s_lvl); + rs_write_int(savef, s->s_arm); + rs_write_int(savef, s->s_hpt); + rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg)); + rs_write_int(savef,s->s_maxhp); +} + +void +rs_read_stats(FILE *savef, struct stats *s) +{ + rs_read_marker(savef, RSID_STATS); + rs_read_int(savef,&s->s_str); + rs_read_int(savef,&s->s_exp); + rs_read_int(savef,&s->s_lvl); + rs_read_int(savef,&s->s_arm); + rs_read_int(savef,&s->s_hpt); + rs_read_chars(savef,s->s_dmg,sizeof(s->s_dmg)); + rs_read_int(savef,&s->s_maxhp); +} + +void +rs_write_stone_index(FILE *savef, const STONE master[], int max, const char *str) +{ + int i; + + for(i = 0; i < max; i++) + if (str == master[i].st_name) + { + rs_write_int(savef,i); + return; + } + + rs_write_int(savef,-1); +} + +void +rs_read_stone_index(FILE *savef, const STONE master[], int maxindex, const char **str) +{ + int i = 0; + + rs_read_int(savef,&i); + + if (!encerror() && (i > maxindex)) + encseterr(EILSEQ); + else if (i >= 0) + *str = master[i].st_name; + else + *str = NULL; +} + +void +rs_write_scrolls(FILE *savef) +{ + int i; + + for(i = 0; i < MAXSCROLLS; i++) + rs_write_string(savef, s_names[i]); +} + +void +rs_read_scrolls(FILE *savef) +{ + int i; + + for(i = 0; i < MAXSCROLLS; i++) + rs_read_new_string(savef, &s_names[i]); +} + +void +rs_write_potions(FILE *savef) +{ + int i; + + for(i = 0; i < MAXPOTIONS; i++) + rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]); +} + +void +rs_read_potions(FILE *savef) +{ + int i; + + for(i = 0; i < MAXPOTIONS; i++) + rs_read_string_index(savef, rainbow, cNCOLORS, &p_colors[i]); +} + +void +rs_write_rings(FILE *savef) +{ + int i; + + for(i = 0; i < MAXRINGS; i++) + rs_write_stone_index(savef, stones, cNSTONES, r_stones[i]); +} + +void +rs_read_rings(FILE *savef) +{ + int i; + + for(i = 0; i < MAXRINGS; i++) + rs_read_stone_index(savef, stones, cNSTONES, &r_stones[i]); +} + +void +rs_write_sticks(FILE *savef) +{ + int i; + + for (i = 0; i < MAXSTICKS; i++) + { + if (strcmp(ws_type[i],"staff") == 0) + { + rs_write_int(savef,0); + rs_write_string_index(savef, wood, cNWOOD, ws_made[i]); + } + else + { + rs_write_int(savef,1); + rs_write_string_index(savef, metal, cNMETAL, ws_made[i]); + } + } +} + +void +rs_read_sticks(FILE *savef) +{ + int i = 0, list = 0; + + for(i = 0; i < MAXSTICKS; i++) + { + rs_read_int(savef,&list); + + if (list == 0) + { + rs_read_string_index(savef, wood, cNWOOD, &ws_made[i]); + ws_type[i] = "staff"; + } + else + { + rs_read_string_index(savef, metal, cNMETAL, &ws_made[i]); + ws_type[i] = "wand"; + } + } +} + +void +rs_write_daemons(FILE *savef, struct delayed_action *dlist, int cnt) +{ + int i = 0; + int func = 0; + + rs_write_marker(savef, RSID_DAEMONS); + rs_write_int(savef, cnt); + + for(i = 0; i < cnt; i++) + { + if (dlist[i].d_func == rollwand) + func = 1; + else if (dlist[i].d_func == doctor) + func = 2; + else if (dlist[i].d_func == stomach) + func = 3; + else if (dlist[i].d_func == runners) + func = 4; + else if (dlist[i].d_func == swander) + func = 5; + else if (dlist[i].d_func == nohaste) + func = 6; + else if (dlist[i].d_func == unconfuse) + func = 7; + else if (dlist[i].d_func == unsee) + func = 8; + else if (dlist[i].d_func == sight) + func = 9; + else if (dlist[i].d_func == NULL) + func = 0; + else + func = -1; + + rs_write_int(savef, dlist[i].d_type); + rs_write_int(savef, func); + rs_write_int(savef, dlist[i].d_arg); + rs_write_int(savef, dlist[i].d_time); + } +} + +void +rs_read_daemons(FILE *savef, struct delayed_action *dlist, int cnt) +{ + int i = 0; + int func = 0; + int value = 0; + + rs_read_marker(savef, RSID_DAEMONS); + rs_read_int(savef, &value); + + if (!encerror() && (value > cnt)) + { + encseterr(EILSEQ); + return; + } + + for(i=0; i < cnt; i++) + { + func = 0; + rs_read_int(savef, &dlist[i].d_type); + rs_read_int(savef, &func); + rs_read_int(savef, &dlist[i].d_arg); + rs_read_int(savef, &dlist[i].d_time); + + if (encerror()) + return; + + switch(func) + { + case 1: dlist[i].d_func = rollwand; + break; + case 2: dlist[i].d_func = doctor; + break; + case 3: dlist[i].d_func = stomach; + break; + case 4: dlist[i].d_func = runners; + break; + case 5: dlist[i].d_func = swander; + break; + case 6: dlist[i].d_func = nohaste; + break; + case 7: dlist[i].d_func = unconfuse; + break; + case 8: dlist[i].d_func = unsee; + break; + case 9: dlist[i].d_func = sight; + break; + default:dlist[i].d_func = NULL; + break; + } + } + + if (dlist[i].d_func == NULL) + { + dlist[i].d_type = 0; + dlist[i].d_arg = 0; + dlist[i].d_time = 0; + } +} + +void +rs_write_obj_info(FILE *savef, struct obj_info *i, int cnt) +{ + int n; + + rs_write_marker(savef, RSID_MAGICITEMS); + rs_write_int(savef, cnt); + + for(n = 0; n < cnt; n++) + { + /* oi_name is constant, defined at compile time in all cases */ + rs_write_int(savef,i[n].oi_prob); + rs_write_int(savef,i[n].oi_worth); + rs_write_string(savef,i[n].oi_guess); + rs_write_int(savef,i[n].oi_know); + } +} + +void +rs_read_obj_info(FILE *savef, struct obj_info *mi, int cnt) +{ + int n; + int value; + + rs_read_marker(savef, RSID_MAGICITEMS); + + rs_read_int(savef, &value); + + if (!encerror() && (value > cnt)) + { + encseterr(EILSEQ); + return; + }