home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume14
/
umoria4
/
part08
< prev
next >
Wrap
Internet Message Format
|
1992-08-31
|
57KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v14i040: umoria4 - single player dungeon simulation (ver. 5.5), Part08/39
Message-ID: <3398@master.CNA.TEK.COM>
Date: 20 Aug 92 18:03:13 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1953
Approved: billr@saab.CNA.TEK.COM
Submitted-by: grabiner@math.harvard.edu (David Grabiner)
Posting-number: Volume 14, Issue 40
Archive-name: umoria4/Part08
Supersedes: umoria3: Volume 9, Issue 55-97; Volume 10, Issue 15-17
Environment: Curses, Unix, Mac, MS-DOS, Atari-ST, Amiga, VMS
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 8 (of 39)."
# Contents: source/save.c source/tables.c
# Wrapped by billr@saab on Thu Aug 20 09:11:27 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'source/save.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source/save.c'\"
else
echo shar: Extracting \"'source/save.c'\" \(41704 characters\)
sed "s/^X//" >'source/save.c' <<'END_OF_FILE'
X/* source/save.c: save and restore games and monster memory info
X
X Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X/* For debugging the savefile code on systems with broken compilers. */
X#if 0
X#define DEBUG(x) x
X#else
X#define DEBUG(x)
X#endif
X
X#include <stdio.h>
X
X#ifndef STDIO_LOADED
X#define STDIO_LOADED
X#endif
X
X#ifdef __TURBOC__
X#include <io.h>
X#endif /* __TURBOC__ */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X
X#ifndef USG
X/* stuff only needed for Berkeley UNIX */
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/param.h>
X#endif
X
X#ifdef VMS
X#include <string.h>
X#include <file.h>
X#else
X#ifdef USG
X#ifndef ATARIST_MWC
X#include <string.h>
X#ifndef ATARIST_TC
X#include <fcntl.h>
X#endif
X#else
X#include "string.h"
X#endif
X#else
X#include <strings.h>
X#endif
X#endif
X
X/* This must be included after fcntl.h, which has a prototype for `open'
X on some systems. Otherwise, the `open' prototype conflicts with the
X `topen' declaration. */
X#include "externs.h"
X
X#ifdef ATARIST_TC
X#include <time.h>
X#endif
X
XDEBUG(static FILE *logfile);
X
X#if defined(LINT_ARGS)
Xstatic int sv_write(void);
Xstatic void wr_byte(int8u);
Xstatic void wr_short(int16u);
Xstatic void wr_long(int32u);
Xstatic void wr_bytes(int8u *, int);
Xstatic void wr_string(char *);
Xstatic void wr_shorts(int16u *, int);
Xstatic void wr_item(inven_type *);
Xstatic void wr_monster(monster_type *);
Xstatic void rd_byte(int8u *);
Xstatic void rd_short(int16u *);
Xstatic void rd_long(int32u *);
Xstatic void rd_bytes(int8u *, int);
Xstatic void rd_string(char *);
Xstatic void rd_shorts(int16u *, int);
Xstatic void rd_item(inven_type *);
Xstatic void rd_monster(monster_type *);
X#else
Xstatic int sv_write();
Xstatic void wr_byte();
Xstatic void wr_short();
Xstatic void wr_long();
Xstatic void wr_bytes();
Xstatic void wr_string();
Xstatic void wr_shorts();
Xstatic void wr_item();
Xstatic void wr_monster();
Xstatic void rd_byte();
Xstatic void rd_short();
Xstatic void rd_long();
Xstatic void rd_bytes();
Xstatic void rd_string();
Xstatic void rd_shorts();
Xstatic void rd_item();
Xstatic void rd_monster();
X#endif
X
X#if !defined(ATARIST_MWC)
X#ifdef MAC
X#include <time.h>
X#else
Xlong time();
X#endif
X#else
Xchar *malloc();
X#endif
X
X/* these are used for the save file, to avoid having to pass them to every
X procedure */
Xstatic FILE *fileptr;
Xstatic int8u xor_byte;
Xstatic int from_savefile; /* can overwrite old savefile when save */
Xstatic int32u start_time; /* time that play started */
X
X/* This save package was brought to by -JWT-
X and -RAK-
X and has been completely rewritten for UNIX by -JEW- */
X/* and has been completely rewritten again by -CJS- */
X/* and completely rewritten again! for portability by -JEW- */
X
Xstatic int sv_write()
X{
X int32u l;
X register int i, j;
X int count;
X int8u char_tmp, prev_char;
X register cave_type *c_ptr;
X register recall_type *r_ptr;
X struct stats *s_ptr;
X register struct flags *f_ptr;
X store_type *st_ptr;
X struct misc *m_ptr;
X#if defined(MSDOS) || defined(ATARI_ST)
X inven_type *t_ptr;
X#endif
X
X /* clear the death flag when creating a HANGUP save file, so that player
X can see tombstone when restart */
X if (eof_flag)
X death = FALSE;
X
X l = 0;
X if (find_cut)
X l |= 0x1;
X if (find_examine)
X l |= 0x2;
X if (find_prself)
X l |= 0x4;
X if (find_bound)
X l |= 0x8;
X if (prompt_carry_flag)
X l |= 0x10;
X if (rogue_like_commands)
X l |= 0x20;
X if (show_weight_flag)
X l |= 0x40;
X if (highlight_seams)
X l |= 0x80;
X if (find_ignore_doors)
X l |= 0x100;
X if (sound_beep_flag)
X l |= 0x200;
X if (display_counts)
X l |= 0x400;
X if (death)
X l |= 0x80000000L; /* Sign bit */
X if (total_winner)
X l |= 0x40000000L;
X
X for (i = 0; i < MAX_CREATURES; i++)
X {
X r_ptr = &c_recall[i];
X if (r_ptr->r_cmove || r_ptr->r_cdefense || r_ptr->r_kills ||
X r_ptr->r_spells || r_ptr->r_deaths || r_ptr->r_attacks[0] ||
X r_ptr->r_attacks[1] || r_ptr->r_attacks[2] || r_ptr->r_attacks[3])
X {
X wr_short((int16u)i);
X wr_long(r_ptr->r_cmove);
X wr_long(r_ptr->r_spells);
X wr_short(r_ptr->r_kills);
X wr_short(r_ptr->r_deaths);
X wr_short(r_ptr->r_cdefense);
X wr_byte(r_ptr->r_wake);
X wr_byte(r_ptr->r_ignore);
X wr_bytes(r_ptr->r_attacks, MAX_MON_NATTACK);
X }
X }
X wr_short((int16u)0xFFFF); /* sentinel to indicate no more monster info */
X
X wr_long(l);
X
X m_ptr = &py.misc;
X wr_string(m_ptr->name);
X wr_byte(m_ptr->male);
X wr_long((int32u)m_ptr->au);
X wr_long((int32u)m_ptr->max_exp);
X wr_long((int32u)m_ptr->exp);
X wr_short(m_ptr->exp_frac);
X wr_short(m_ptr->age);
X wr_short(m_ptr->ht);
X wr_short(m_ptr->wt);
X wr_short(m_ptr->lev);
X wr_short(m_ptr->max_dlv);
X wr_short((int16u)m_ptr->srh);
X wr_short((int16u)m_ptr->fos);
X wr_short((int16u)m_ptr->bth);
X wr_short((int16u)m_ptr->bthb);
X wr_short((int16u)m_ptr->mana);
X wr_short((int16u)m_ptr->mhp);
X wr_short((int16u)m_ptr->ptohit);
X wr_short((int16u)m_ptr->ptodam);
X wr_short((int16u)m_ptr->pac);
X wr_short((int16u)m_ptr->ptoac);
X wr_short((int16u)m_ptr->dis_th);
X wr_short((int16u)m_ptr->dis_td);
X wr_short((int16u)m_ptr->dis_ac);
X wr_short((int16u)m_ptr->dis_tac);
X wr_short((int16u)m_ptr->disarm);
X wr_short((int16u)m_ptr->save);
X wr_short((int16u)m_ptr->sc);
X wr_short((int16u)m_ptr->stl);
X wr_byte(m_ptr->pclass);
X wr_byte(m_ptr->prace);
X wr_byte(m_ptr->hitdie);
X wr_byte(m_ptr->expfact);
X wr_short((int16u)m_ptr->cmana);
X wr_short(m_ptr->cmana_frac);
X wr_short((int16u)m_ptr->chp);
X wr_short(m_ptr->chp_frac);
X for (i = 0; i < 4; i++)
X wr_string (m_ptr->history[i]);
X
X s_ptr = &py.stats;
X wr_bytes(s_ptr->max_stat, 6);
X wr_bytes(s_ptr->cur_stat, 6);
X wr_shorts((int16u *)s_ptr->mod_stat, 6);
X wr_bytes(s_ptr->use_stat, 6);
X
X f_ptr = &py.flags;
X wr_long(f_ptr->status);
X wr_short((int16u)f_ptr->rest);
X wr_short((int16u)f_ptr->blind);
X wr_short((int16u)f_ptr->paralysis);
X wr_short((int16u)f_ptr->confused);
X wr_short((int16u)f_ptr->food);
X wr_short((int16u)f_ptr->food_digested);
X wr_short((int16u)f_ptr->protection);
X wr_short((int16u)f_ptr->speed);
X wr_short((int16u)f_ptr->fast);
X wr_short((int16u)f_ptr->slow);
X wr_short((int16u)f_ptr->afraid);
X wr_short((int16u)f_ptr->poisoned);
X wr_short((int16u)f_ptr->image);
X wr_short((int16u)f_ptr->protevil);
X wr_short((int16u)f_ptr->invuln);
X wr_short((int16u)f_ptr->hero);
X wr_short((int16u)f_ptr->shero);
X wr_short((int16u)f_ptr->blessed);
X wr_short((int16u)f_ptr->resist_heat);
X wr_short((int16u)f_ptr->resist_cold);
X wr_short((int16u)f_ptr->detect_inv);
X wr_short((int16u)f_ptr->word_recall);
X wr_short((int16u)f_ptr->see_infra);
X wr_short((int16u)f_ptr->tim_infra);
X wr_byte(f_ptr->see_inv);
X wr_byte(f_ptr->teleport);
X wr_byte(f_ptr->free_act);
X wr_byte(f_ptr->slow_digest);
X wr_byte(f_ptr->aggravate);
X wr_byte(f_ptr->fire_resist);
X wr_byte(f_ptr->cold_resist);
X wr_byte(f_ptr->acid_resist);
X wr_byte(f_ptr->regenerate);
X wr_byte(f_ptr->lght_resist);
X wr_byte(f_ptr->ffall);
X wr_byte(f_ptr->sustain_str);
X wr_byte(f_ptr->sustain_int);
X wr_byte(f_ptr->sustain_wis);
X wr_byte(f_ptr->sustain_con);
X wr_byte(f_ptr->sustain_dex);
X wr_byte(f_ptr->sustain_chr);
X wr_byte(f_ptr->confuse_monster);
X wr_byte(f_ptr->new_spells);
X
X wr_short((int16u)missile_ctr);
X wr_long((int32u)turn);
X wr_short((int16u)inven_ctr);
X for (i = 0; i < inven_ctr; i++)
X wr_item(&inventory[i]);
X for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++)
X wr_item(&inventory[i]);
X wr_short((int16u)inven_weight);
X wr_short((int16u)equip_ctr);
X wr_long(spell_learned);
X wr_long(spell_worked);
X wr_long(spell_forgotten);
X wr_bytes(spell_order, 32);
X wr_bytes(object_ident, OBJECT_IDENT_SIZE);
X wr_long(randes_seed);
X wr_long(town_seed);
X wr_short((int16u)last_msg);
X for (i = 0; i < MAX_SAVE_MSG; i++)
X wr_string(old_msg[i]);
X
X /* this indicates 'cheating' if it is a one */
X wr_short((int16u)panic_save);
X wr_short((int16u)total_winner);
X wr_short((int16u)noscore);
X wr_shorts(player_hp, MAX_PLAYER_LEVEL);
X
X for (i = 0; i < MAX_STORES; i++)
X {
X st_ptr = &store[i];
X wr_long((int32u)st_ptr->store_open);
X wr_short((int16u)st_ptr->insult_cur);
X wr_byte(st_ptr->owner);
X wr_byte(st_ptr->store_ctr);
X wr_short(st_ptr->good_buy);
X wr_short(st_ptr->bad_buy);
X for (j = 0; j < st_ptr->store_ctr; j++)
X {
X wr_long((int32u)st_ptr->store_inven[j].scost);
X wr_item(&st_ptr->store_inven[j].sitem);
X }
X }
X
X /* save the current time in the savefile */
X#ifdef MAC
X l = time((time_t *)0);
X#else
X l = time((long *)0);
X#endif
X if (l < start_time)
X {
X /* someone is messing with the clock!, assume that we have been
X playing for 1 day */
X l = start_time + 86400L;
X }
X wr_long(l);
X
X /* starting with 5.2, put died_from string in savefile */
X wr_string(died_from);
X
X /* starting with 5.2.2, put the max_score in the savefile */
X l = total_points ();
X wr_long (l);
X
X /* starting with 5.2.2, put the birth_date in the savefile */
X wr_long ((int32u) birth_date);
X
X /* only level specific info follows, this allows characters to be
X resurrected, the dungeon level info is not needed for a resurrection */
X if (death)
X {
X if (ferror(fileptr) || fflush(fileptr) == EOF)
X return FALSE;
X return TRUE;
X }
X
X wr_short((int16u)dun_level);
X wr_short((int16u)char_row);
X wr_short((int16u)char_col);
X wr_short((int16u)mon_tot_mult);
X wr_short((int16u)cur_height);
X wr_short((int16u)cur_width);
X wr_short((int16u)max_panel_rows);
X wr_short((int16u)max_panel_cols);
X
X for (i = 0; i < MAX_HEIGHT; i++)
X for (j = 0; j < MAX_WIDTH; j++)
X {
X c_ptr = &cave[i][j];
X if (c_ptr->cptr != 0)
X {
X wr_byte((int8u)i);
X wr_byte((int8u)j);
X wr_byte(c_ptr->cptr);
X }
X }
X wr_byte((int8u)0xFF); /* marks end of cptr info */
X for (i = 0; i < MAX_HEIGHT; i++)
X for (j = 0; j < MAX_WIDTH; j++)
X {
X c_ptr = &cave[i][j];
X if (c_ptr->tptr != 0)
X {
X wr_byte((int8u)i);
X wr_byte((int8u)j);
X wr_byte(c_ptr->tptr);
X }
X }
X wr_byte((int8u)0xFF); /* marks end of tptr info */
X /* must set counter to zero, note that code may write out two bytes
X unnecessarily */
X count = 0;
X prev_char = 0;
X for (i = 0; i < MAX_HEIGHT; i++)
X for (j = 0; j < MAX_WIDTH; j++)
X {
X c_ptr = &cave[i][j];
X char_tmp = c_ptr->fval | (c_ptr->lr << 4) | (c_ptr->fm << 5) |
X (c_ptr->pl << 6) | (c_ptr->tl << 7);
X if (char_tmp != prev_char || count == MAX_UCHAR)
X {
X wr_byte((int8u)count);
X wr_byte(prev_char);
X prev_char = char_tmp;
X count = 1;
X }
X else
X count++;
X }
X /* save last entry */
X wr_byte((int8u)count);
X wr_byte(prev_char);
X
X#if defined(MSDOS) || defined(ATARI_ST)
X /* must change graphics symbols for walls and floors back to default chars,
X this is necessary so that if the user changes the graphics line, the
X program will be able change all existing walls and floors to the new
X symbol */
X /* Or if the user moves the savefile from one machine to another, we
X must have a consistent representation here. */
X t_ptr = &t_list[tcptr - 1];
X for (i = tcptr - 1; i >= MIN_TRIX; i--)
X {
X#ifdef MSDOS
X if (t_ptr->tchar == wallsym)
X t_ptr->tchar = '#';
X#endif
X#ifdef ATARI_ST
X if (t_ptr->tchar == (unsigned char)240)
X t_ptr->tchar = '#';
X#endif
X t_ptr--;
X }
X#endif
X wr_short((int16u)tcptr);
X for (i = MIN_TRIX; i < tcptr; i++)
X wr_item(&t_list[i]);
X wr_short((int16u)mfptr);
X for (i = MIN_MONIX; i < mfptr; i++)
X wr_monster(&m_list[i]);
X
X if (ferror(fileptr) || (fflush(fileptr) == EOF))
X return FALSE;
X return TRUE;
X}
X
X#ifdef MAC
X
X/* Set up prior to actual save, do the save, then clean up */
X/* Notice that Mac version of this function takes a parameter */
X/* To do a "save as" set always_ask */
X/* To do a "save" clear always_ask */
X
Xint save_char(always_ask)
Xint always_ask;
X{
X int rc, already_set, proceed;
X int16 vrefnum;
X
X /* cannot rely on _save_char to do this because we may put up a dialog */
X if (character_saved) return(TRUE);
X
X enablefilemenu(FALSE);
X
X already_set = getsavedefaults(savefile, &vrefnum);
X
X if (!already_set || always_ask)
X {
X /* Here if always_ask or user has not yet specified a save file */
X /* User specifies a save file when he restarts a previous one */
X sfposition(vrefnum);
X proceed = doputfile(death ? "Save memories as:" : "Save game as:",
X savefile, &vrefnum);
X }
X else
X proceed = TRUE;
X
X if (proceed)
X {
X changedirectory(vrefnum);
X rc = _save_char(savefile);
X restoredirectory();
X }
X else
X rc = FALSE;
X
X if (rc)
X (void) setfileinfo(savefile, vrefnum, SAVE_FTYPE);
X
X enablefilemenu(TRUE);
X
X return(rc);
X}
X
X#else
X
X/* The Mac has different logic here -- See above */
X
Xint save_char()
X{
X int i;
X vtype temp;
X
X#ifdef SECURE
X bePlayer();
X#endif
X
X while (!_save_char(savefile))
X {
X (void) sprintf(temp, "Savefile '%s' fails.", savefile);
X msg_print(temp);
X i = 0;
X if (access(savefile, 0) < 0
X || get_check("File exists. Delete old savefile?") == 0
X || (i = unlink(savefile)) < 0)
X {
X if (i < 0)
X {
X (void) sprintf(temp, "Can't delete '%s'", savefile);
X msg_print(temp);
X }
X prt("New Savefile [ESC to give up]:", 0, 0);
X if (!get_string(temp, 0, 31, 45))
X return FALSE;
X if (temp[0])
X (void) strcpy(savefile, temp);
X }
X (void) sprintf(temp, "Saving with %s...", savefile);
X prt(temp, 0, 0);
X }
X#ifdef SECURE
X beGames();
X#endif
X return TRUE;
X}
X#endif
X
Xint _save_char(fnam)
Xchar *fnam;
X{
X vtype temp;
X register int ok, fd;
X int8u char_tmp;
X
X if (character_saved)
X return TRUE; /* Nothing to save. */
X
X nosignals();
X put_qio();
X disturb (1, 0); /* Turn off resting and searching. */
X change_speed(-pack_heavy); /* Fix the speed */
X pack_heavy = 0;
X ok = FALSE;
X /* VMS files have version numbers, so don't worry about overwriting
X the old save file. */
X#if !defined(ATARIST_MWC) && !defined(VMS)
X fd = -1;
X fileptr = NULL; /* Do not assume it has been init'ed */
X#if defined(MAC) || defined(AMIGA)
X /* The Mac version automatically overwrites */
X fd = open(fnam, O_RDWR|O_CREAT|O_TRUNC);
X#ifdef MAC
X macbeginwait ();
X#endif
X#else
X fd = open(fnam, O_RDWR|O_CREAT|O_EXCL, 0600);
X if (fd < 0 && access(fnam, 0) >= 0 &&
X (from_savefile ||
X (wizard && get_check("Can't make new savefile. Overwrite old?"))))
X {
X (void) chmod(fnam, 0600);
X fd = open(fnam, O_RDWR|O_TRUNC, 0600);
X }
X#endif
X if (fd >= 0)
X {
X (void) close(fd);
X#endif /* !ATARIST_MWC && !VMS */
X /* GCC for atari st defines atarist */
X#if defined(atarist) || defined(ATARI_ST) || defined(THINK_C) || defined(MSDOS)
X fileptr = fopen(savefile, "wb");
X#else
X fileptr = fopen(savefile, "w");
X#endif
X#if !defined(ATARIST_MWC) && !defined(VMS)
X }
X#endif
X DEBUG(logfile = fopen("IO_LOG", "a"));
X DEBUG(fprintf (logfile, "Saving data to %s\n", savefile));
X if (fileptr != NULL)
X {
X xor_byte = 0;
X wr_byte((int8u)CUR_VERSION_MAJ);
X xor_byte = 0;
X wr_byte((int8u)CUR_VERSION_MIN);
X xor_byte = 0;
X wr_byte((int8u)PATCH_LEVEL);
X xor_byte = 0;
X char_tmp = randint(256) - 1;
X wr_byte(char_tmp);
X /* Note that xor_byte is now equal to char_tmp */
X
X ok = sv_write();
X
X DEBUG(fclose (logfile));
X
X if (fclose(fileptr) == EOF)
X ok = FALSE;
X }
X
X#ifdef MAC
X macendwait ();
X#endif
X
X if (!ok)
X {
X if (fd >= 0)
X (void) unlink(fnam);
X signals();
X if (fd >= 0)
X (void) sprintf(temp, "Error writing to file %s", fnam);
X else
X (void) sprintf(temp, "Can't create new file %s", fnam);
X msg_print(temp);
X return FALSE;
X }
X else
X character_saved = 1;
X
X turn = -1;
X signals();
X
X return TRUE;
X}
X
X
X#ifdef MAC
X/* Wrapper to set the appropriate directory */
Xint get_char(generate)
Xint *generate;
X{
X int rc, exit_flag;
X int16 vrefnum;
X
X (void) getsavedefaults(savefile, &vrefnum);
X
X changedirectory(vrefnum);
X rc = _get_char(generate, &exit_flag);
X restoredirectory();
X
X if (exit_flag)
X exit_game();
X
X return(rc);
X}
X#endif
X
X/* Certain checks are ommitted for the wizard. -CJS- */
X
X#ifdef MAC
Xint _get_char(generate, exit_flag)
Xint *generate, *exit_flag;
X#else
Xint get_char(generate)
Xint *generate;
X#endif
X{
X register int i, j;
X int fd, c, ok, total_count;
X int32u l, age, time_saved;
X vtype temp;
X int16u int16u_tmp;
X register cave_type *c_ptr;
X register recall_type *r_ptr;
X struct misc *m_ptr;
X struct stats *s_ptr;
X register struct flags *f_ptr;
X store_type *st_ptr;
X int8u char_tmp, ychar, xchar, count;
X int8u version_maj, version_min, patch_level;
X#if defined(MSDOS) || defined(ATARI_ST)
X inven_type *t_ptr;
X#endif
X
X#ifdef MAC
X *exit_flag = FALSE;
X#endif
X
X nosignals();
X *generate = TRUE;
X fd = -1;
X
X#ifndef MAC
X /* Not required for Mac, because the file name is obtained through a dialog.
X There is no way for a non existnat file to be specified. -BS- */
X if (access(savefile, 0) != 0)
X {
X signals();
X msg_print("Savefile does not exist.");
X return FALSE; /* Don't bother with messages here. File absent. */
X }
X#endif
X
X clear_screen();
X
X (void) sprintf(temp, "Savefile %s present. Attempting restore.", savefile);
X put_buffer(temp, 23, 0);
X
X if (turn >= 0)
X msg_print("IMPOSSIBLE! Attempt to restore while still alive!");
X
X /* Allow restoring a file belonging to someone else, if we can delete it. */
X /* Hence first try to read without doing a chmod. */
X
X#if defined(MAC) || defined(AMIGA)
X else if ((fd = open(savefile, O_RDONLY)) < 0)
X#else
X#ifdef ATARI_ST
X else if (FALSE)
X#else
X else if ((fd = open(savefile, O_RDONLY, 0)) < 0
X && (chmod(savefile, 0400) < 0 ||
X (fd = open(savefile, O_RDONLY, 0)) < 0))
X#endif
X#endif
X msg_print("Can't open file for reading.");
X else
X {
X turn = -1;
X ok = TRUE;
X
X (void) close(fd);
X /* GCC for atari st defines atarist */
X#if defined(atarist) || defined(ATARI_ST) || defined(THINK_C) || defined(MSDOS)
X fileptr = fopen(savefile, "rb");
X#else
X fileptr = fopen(savefile, "r");
X#endif
X if (fileptr == NULL)
X goto error;
X
X#ifdef MAC
X macbeginwait ();
X#endif
X
X prt("Restoring Memory...", 0, 0);
X put_qio();
X
X DEBUG(logfile = fopen("IO_LOG", "a"));
X DEBUG(fprintf (logfile, "Reading data from %s\n", savefile));
X
X xor_byte = 0;
X rd_byte(&version_maj);
X xor_byte = 0;
X rd_byte(&version_min);
X xor_byte = 0;
X rd_byte(&patch_level);
X xor_byte = 0;
X rd_byte(&xor_byte);
X
X /* COMPAT support savefiles from 5.0.14 to 5.0.17 */
X /* support savefiles from 5.1.0 to present */
X if ((version_maj != CUR_VERSION_MAJ)
X#if 0
X /* As of version 5.4, accept savefiles even if they have higher
X version numbers. The savefile format was frozen as of version
X 5.2.2. */
X || (version_min > CUR_VERSION_MIN)
X || (version_min == CUR_VERSION_MIN && patch_level > PATCH_LEVEL)
X#endif
X || (version_min == 0 && patch_level < 14))
X {
X prt("Sorry. This savefile is from a different version of umoria.",
X 2, 0);
X goto error;
X }
X
X rd_short(&int16u_tmp);
X while (int16u_tmp != 0xFFFF)
X {
X if (int16u_tmp >= MAX_CREATURES)
X goto error;
X r_ptr = &c_recall[int16u_tmp];
X rd_long(&r_ptr->r_cmove);
X rd_long(&r_ptr->r_spells);
X rd_short(&r_ptr->r_kills);
X rd_short(&r_ptr->r_deaths);
X rd_short(&r_ptr->r_cdefense);
X rd_byte(&r_ptr->r_wake);
X rd_byte(&r_ptr->r_ignore);
X rd_bytes(r_ptr->r_attacks, MAX_MON_NATTACK);
X rd_short(&int16u_tmp);
X }
X
X /* for save files before 5.2.2, read and ignore log_index (sic) */
X if ((version_min < 2) || (version_min == 2 && patch_level < 2))
X rd_short(&int16u_tmp);
X rd_long(&l);
X
X if (l & 0x1)
X find_cut = TRUE;
X else
X find_cut = FALSE;
X if (l & 0x2)
X find_examine = TRUE;
X else
X find_examine = FALSE;
X if (l & 0x4)
X find_prself = TRUE;
X else
X find_prself = FALSE;
X if (l & 0x8)
X find_bound = TRUE;
X else
X find_bound = FALSE;
X if (l & 0x10)
X prompt_carry_flag = TRUE;
X else
X prompt_carry_flag = FALSE;
X if (l & 0x20)
X rogue_like_commands = TRUE;
X else
X rogue_like_commands = FALSE;
X if (l & 0x40)
X show_weight_flag = TRUE;
X else
X show_weight_flag = FALSE;
X if (l & 0x80)
X highlight_seams = TRUE;
X else
X highlight_seams = FALSE;
X if (l & 0x100)
X find_ignore_doors = TRUE;
X else
X find_ignore_doors = FALSE;
X /* save files before 5.2.2 don't have sound_beep_flag, set it on
X for compatibility */
X if ((version_min < 2) || (version_min == 2 && patch_level < 2))
X sound_beep_flag = TRUE;
X else if (l & 0x200)
X sound_beep_flag = TRUE;
X else
X sound_beep_flag = FALSE;
X /* save files before 5.2.2 don't have display_counts, set it on
X for compatibility */
X if ((version_min < 2) || (version_min == 2 && patch_level < 2))
X display_counts = TRUE;
X else if (l & 0x400)
X display_counts = TRUE;
X else
X display_counts = FALSE;
X
X /* Don't allow resurrection of total_winner characters. It causes
X problems because the character level is out of the allowed range. */
X if (to_be_wizard && (l & 0x40000000L))
X {
X msg_print ("Sorry, this character is retired from moria.");
X msg_print ("You can not resurrect a retired character.");
X }
X else if (to_be_wizard && (l & 0x80000000L)
X && get_check("Resurrect a dead character?"))
X l &= ~0x80000000L;
X if ((l & 0x80000000L) == 0)
X {
X m_ptr = &py.misc;
X rd_string(m_ptr->name);
X rd_byte(&m_ptr->male);
X rd_long((int32u *)&m_ptr->au);
X rd_long((int32u *)&m_ptr->max_exp);
X rd_long((int32u *)&m_ptr->exp);
X rd_short(&m_ptr->exp_frac);
X rd_short(&m_ptr->age);
X rd_short(&m_ptr->ht);
X rd_short(&m_ptr->wt);
X rd_short(&m_ptr->lev);
X rd_short(&m_ptr->max_dlv);
X rd_short((int16u *)&m_ptr->srh);
X rd_short((int16u *)&m_ptr->fos);
X rd_short((int16u *)&m_ptr->bth);
X rd_short((int16u *)&m_ptr->bthb);
X rd_short((int16u *)&m_ptr->mana);
X rd_short((int16u *)&m_ptr->mhp);
X rd_short((int16u *)&m_ptr->ptohit);
X rd_short((int16u *)&m_ptr->ptodam);
X rd_short((int16u *)&m_ptr->pac);
X rd_short((int16u *)&m_ptr->ptoac);
X rd_short((int16u *)&m_ptr->dis_th);
X rd_short((int16u *)&m_ptr->dis_td);
X rd_short((int16u *)&m_ptr->dis_ac);
X rd_short((int16u *)&m_ptr->dis_tac);
X rd_short((int16u *)&m_ptr->disarm);
X rd_short((int16u *)&m_ptr->save);
X rd_short((int16u *)&m_ptr->sc);
X rd_short((int16u *)&m_ptr->stl);
X rd_byte(&m_ptr->pclass);
X rd_byte(&m_ptr->prace);
X rd_byte(&m_ptr->hitdie);
X rd_byte(&m_ptr->expfact);
X rd_short((int16u *)&m_ptr->cmana);
X rd_short(&m_ptr->cmana_frac);
X rd_short((int16u *)&m_ptr->chp);
X rd_short(&m_ptr->chp_frac);
X for (i = 0; i < 4; i++)
X rd_string (m_ptr->history[i]);
X
X s_ptr = &py.stats;
X rd_bytes(s_ptr->max_stat, 6);
X rd_bytes(s_ptr->cur_stat, 6);
X rd_shorts((int16u *)s_ptr->mod_stat, 6);
X rd_bytes(s_ptr->use_stat, 6);
X
X f_ptr = &py.flags;
X rd_long(&f_ptr->status);
X rd_short((int16u *)&f_ptr->rest);
X rd_short((int16u *)&f_ptr->blind);
X rd_short((int16u *)&f_ptr->paralysis);
X rd_short((int16u *)&f_ptr->confused);
X rd_short((int16u *)&f_ptr->food);
X rd_short((int16u *)&f_ptr->food_digested);
X rd_short((int16u *)&f_ptr->protection);
X rd_short((int16u *)&f_ptr->speed);
X rd_short((int16u *)&f_ptr->fast);
X rd_short((int16u *)&f_ptr->slow);
X rd_short((int16u *)&f_ptr->afraid);
X rd_short((int16u *)&f_ptr->poisoned);
X rd_short((int16u *)&f_ptr->image);
X rd_short((int16u *)&f_ptr->protevil);
X rd_short((int16u *)&f_ptr->invuln);
X rd_short((int16u *)&f_ptr->hero);
X rd_short((int16u *)&f_ptr->shero);
X rd_short((int16u *)&f_ptr->blessed);
X rd_short((int16u *)&f_ptr->resist_heat);
X rd_short((int16u *)&f_ptr->resist_cold);
X rd_short((int16u *)&f_ptr->detect_inv);
X rd_short((int16u *)&f_ptr->word_recall);
X rd_short((int16u *)&f_ptr->see_infra);
X rd_short((int16u *)&f_ptr->tim_infra);
X rd_byte(&f_ptr->see_inv);
X rd_byte(&f_ptr->teleport);
X rd_byte(&f_ptr->free_act);
X rd_byte(&f_ptr->slow_digest);
X rd_byte(&f_ptr->aggravate);
X rd_byte(&f_ptr->fire_resist);
X rd_byte(&f_ptr->cold_resist);
X rd_byte(&f_ptr->acid_resist);
X rd_byte(&f_ptr->regenerate);
X rd_byte(&f_ptr->lght_resist);
X rd_byte(&f_ptr->ffall);
X rd_byte(&f_ptr->sustain_str);
X rd_byte(&f_ptr->sustain_int);
X rd_byte(&f_ptr->sustain_wis);
X rd_byte(&f_ptr->sustain_con);
X rd_byte(&f_ptr->sustain_dex);
X rd_byte(&f_ptr->sustain_chr);
X rd_byte(&f_ptr->confuse_monster);
X rd_byte(&f_ptr->new_spells);
X
X rd_short((int16u *)&missile_ctr);
X rd_long((int32u *)&turn);
X rd_short((int16u *)&inven_ctr);
X if (inven_ctr > INVEN_WIELD)
X goto error;
X for (i = 0; i < inven_ctr; i++)
X rd_item(&inventory[i]);
X for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++)
X rd_item(&inventory[i]);
X rd_short((int16u *)&inven_weight);
X rd_short((int16u *)&equip_ctr);
X rd_long(&spell_learned);
X rd_long(&spell_worked);
X rd_long(&spell_forgotten);
X rd_bytes(spell_order, 32);
X rd_bytes(object_ident, OBJECT_IDENT_SIZE);
X rd_long(&randes_seed);
X rd_long(&town_seed);
X rd_short((int16u *)&last_msg);
X for (i = 0; i < MAX_SAVE_MSG; i++)
X rd_string(old_msg[i]);
X
X rd_short((int16u *)&panic_save);
X rd_short((int16u *)&total_winner);
X rd_short((int16u *)&noscore);
X rd_shorts(player_hp, MAX_PLAYER_LEVEL);
X
X if ((version_min >= 2)
X || (version_min == 1 && patch_level >= 3))
X for (i = 0; i < MAX_STORES; i++)
X {
X st_ptr = &store[i];
X rd_long((int32u *)&st_ptr->store_open);
X rd_short((int16u *)&st_ptr->insult_cur);
X rd_byte(&st_ptr->owner);
X rd_byte(&st_ptr->store_ctr);
X rd_short(&st_ptr->good_buy);
X rd_short(&st_ptr->bad_buy);
X if (st_ptr->store_ctr > STORE_INVEN_MAX)
X goto error;
X for (j = 0; j < st_ptr->store_ctr; j++)
X {
X rd_long((int32u *)&st_ptr->store_inven[j].scost);
X rd_item(&st_ptr->store_inven[j].sitem);
X }
X }
X
X if ((version_min >= 2)
X || (version_min == 1 && patch_level >= 3))
X rd_long(&time_saved);
X
X if (version_min >= 2)
X rd_string(died_from);
X
X if ((version_min >= 3)
X || (version_min == 2 && patch_level >= 2))
X rd_long ((int32u *)&max_score);
X else
X max_score = 0;
X
X if ((version_min >= 3)
X || (version_min == 2 && patch_level >= 2))
X rd_long ((int32u *)&birth_date);
X else
X#ifdef MAC
X birth_date = time((time_t *)0);
X#else
X birth_date = time((long *)0);
X#endif
X }
X if ((c = getc(fileptr)) == EOF || (l & 0x80000000L))
X {
X if ((l & 0x80000000L) == 0)
X {
X if (!to_be_wizard || turn < 0)
X goto error;
X prt("Attempting a resurrection!", 0, 0);
X if (py.misc.chp < 0)
X {
X py.misc.chp = 0;
X py.misc.chp_frac = 0;
X }
X /* don't let him starve to death immediately */
X if (py.flags.food < 0)
X py.flags.food = 0;
X /* don't let him die of poison again immediately */
X if (py.flags.poisoned > 1)
X py.flags.poisoned = 1;
X dun_level = 0; /* Resurrect on the town level. */
X character_generated = 1;
X /* set noscore to indicate a resurrection, and don't enter
X wizard mode */
X to_be_wizard = FALSE;
X noscore |= 0x1;
X }
X else
X {
X /* Make sure that this message is seen, since it is a bit
X more interesting than the other messages. */
X msg_print("Restoring Memory of a departed spirit...");
X turn = -1;
X }
X put_qio();
X goto closefiles;
X }
X if (ungetc(c, fileptr) == EOF)
X goto error;
X
X prt("Restoring Character...", 0, 0);
X put_qio();
X
X /* only level specific info should follow, not present for dead
X characters */
X
X rd_short((int16u *)&dun_level);
X rd_short((int16u *)&char_row);
X rd_short((int16u *)&char_col);
X rd_short((int16u *)&mon_tot_mult);
X rd_short((int16u *)&cur_height);
X rd_short((int16u *)&cur_width);
X rd_short((int16u *)&max_panel_rows);
X rd_short((int16u *)&max_panel_cols);
X
X /* read in the creature ptr info */
X rd_byte(&char_tmp);
X while (char_tmp != 0xFF)
X {
X ychar = char_tmp;
X rd_byte(&xchar);
X rd_byte(&char_tmp);
X if (xchar > MAX_WIDTH || ychar > MAX_HEIGHT)
X goto error;
X cave[ychar][xchar].cptr = char_tmp;
X rd_byte(&char_tmp);
X }
X /* read in the treasure ptr info */
X rd_byte(&char_tmp);
X while (char_tmp != 0xFF)
X {
X ychar = char_tmp;
X rd_byte(&xchar);
X rd_byte(&char_tmp);
X if (xchar > MAX_WIDTH || ychar > MAX_HEIGHT)
X goto error;
X cave[ychar][xchar].tptr = char_tmp;
X rd_byte(&char_tmp);
X }
X /* read in the rest of the cave info */
X c_ptr = &cave[0][0];
X total_count = 0;
X while (total_count != MAX_HEIGHT*MAX_WIDTH)
X {
X rd_byte(&count);
X rd_byte(&char_tmp);
X for (i = count; i > 0; i--)
X {
X#ifndef ATARIST_MWC
X if (c_ptr >= &cave[MAX_HEIGHT][0])
X goto error;
X#endif
X c_ptr->fval = char_tmp & 0xF;
X c_ptr->lr = (char_tmp >> 4) & 0x1;
X c_ptr->fm = (char_tmp >> 5) & 0x1;
X c_ptr->pl = (char_tmp >> 6) & 0x1;
X c_ptr->tl = (char_tmp >> 7) & 0x1;
X c_ptr++;
X }
X total_count += count;
X }
X
X rd_short((int16u *)&tcptr);
X if (tcptr > MAX_TALLOC)
X goto error;
X for (i = MIN_TRIX; i < tcptr; i++)
X rd_item(&t_list[i]);
X rd_short((int16u *)&mfptr);
X if (mfptr > MAX_MALLOC)
X goto error;
X for (i = MIN_MONIX; i < mfptr; i++)
X rd_monster(&m_list[i]);
X
X#if defined(MSDOS) || defined(ATARI_ST)
X /* change walls and floors to graphic symbols */
X t_ptr = &t_list[tcptr - 1];
X for (i = tcptr - 1; i >= MIN_TRIX; i--)
X {
X#ifdef MSDOS
X if (t_ptr->tchar == '#')
X t_ptr->tchar = wallsym;
X#endif
X#ifdef ATARI_ST
X if (t_ptr->tchar == '#')
X t_ptr->tchar = (unsigned char) 240;
X#endif
X t_ptr--;
X }
X#endif
X
X *generate = FALSE; /* We have restored a cave - no need to generate. */
X
X if ((version_min == 1 && patch_level < 3)
X || (version_min == 0))
X for (i = 0; i < MAX_STORES; i++)
X {
X st_ptr = &store[i];
X rd_long((int32u *)&st_ptr->store_open);
X rd_short((int16u *)&st_ptr->insult_cur);
X rd_byte(&st_ptr->owner);
X rd_byte(&st_ptr->store_ctr);
X rd_short(&st_ptr->good_buy);
X rd_short(&st_ptr->bad_buy);
X if (st_ptr->store_ctr > STORE_INVEN_MAX)
X goto error;
X for (j = 0; j < st_ptr->store_ctr; j++)
X {
X rd_long((int32u *)&st_ptr->store_inven[j].scost);
X rd_item(&st_ptr->store_inven[j].sitem);
X }
X }
X
X /* read the time that the file was saved */
X if (version_min == 0 && patch_level < 16)
X time_saved = 0; /* no time in file, clear to zero */
X else if (version_min == 1 && patch_level < 3)
X rd_long(&time_saved);
X
X if (ferror(fileptr))
X goto error;
X
X if (turn < 0)
X error:
X ok = FALSE; /* Assume bad data. */
X else
X {
X /* don't overwrite the killed by string if character is dead */
X if (py.misc.chp >= 0)
X (void) strcpy(died_from, "(alive and well)");
X character_generated = 1;
X }
X
X closefiles:
X
X DEBUG(fclose (logfile));
X
X if (fileptr != NULL)
X {
X if (fclose(fileptr) < 0)
X ok = FALSE;
X }
X if (fd >= 0)
X (void) close(fd);
X
X#ifdef MAC
X macendwait ();
X#endif
X
X if (!ok)
X msg_print("Error during reading of file.");
X else
X {
X /* let the user overwrite the old savefile when save/quit */
X from_savefile = 1;
X
X signals();
X
X if (panic_save == 1)
X {
X (void) sprintf(temp, "This game is from a panic save. \
XScore will not be added to scoreboard.");
X msg_print (temp);
X }
X else if ((!noscore & 0x04) && duplicate_character ())
X {
X (void) sprintf (temp, "This character is already on the \
Xscoreboard; it will not be scored again.");
X msg_print (temp);
X noscore |= 0x4;
X }
X
X if (turn >= 0)
X { /* Only if a full restoration. */
X weapon_heavy = FALSE;
X pack_heavy = 0;
X check_strength();
X
X /* rotate store inventory, depending on how old the save file */
X /* is foreach day old (rounded up), call store_maint */
X /* calculate age in seconds */
X#ifdef MAC
X start_time = time((time_t *)0);
X#else
X start_time = time((long *)0);
X#endif
X /* check for reasonable values of time here ... */
X if (start_time < time_saved)
X age = 0;
X else
X age = start_time - time_saved;
X
X age = (age + 43200L) / 86400L; /* age in days */
X if (age > 10) age = 10; /* in case savefile is very old */
X for (i = 0; i < age; i++)
X store_maint();
X }
X
X if (noscore)
X msg_print("This save file cannot be used to get on the score board.");
X
X if (version_maj != CUR_VERSION_MAJ
X || version_min != CUR_VERSION_MIN)
X {
X (void) sprintf(temp,
X "Save file version %d.%d %s on game version %d.%d.",
X version_maj, version_min,
X version_min <= CUR_VERSION_MIN
X ? "accepted" : "risky" ,
X CUR_VERSION_MAJ, CUR_VERSION_MIN);
X msg_print(temp);
X }
X
X if (turn >= 0)
X return TRUE;
X else
X return FALSE; /* Only restored options and monster memory. */
X }
X }
X turn = -1;
X prt("Please try again without that savefile.", 1, 0);
X signals();
X#ifdef MAC
X *exit_flag = TRUE;
X#else
X exit_game();
X#endif
X
X return FALSE; /* not reached, unless on mac */
X}
X
Xstatic void wr_byte(c)
Xint8u c;
X{
X xor_byte ^= c;
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, "BYTE: %02X = %d\n", (int) xor_byte, (int) c));
X}
X
Xstatic void wr_short(s)
Xint16u s;
X{
X xor_byte ^= (s & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, "SHORT: %02X", (int) xor_byte));
X xor_byte ^= ((s >> 8) & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X = %d\n", (int) xor_byte, (int) s));
X}
X
Xstatic void wr_long(l)
Xregister int32u l;
X{
X xor_byte ^= (l & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, "LONG: %02X", (int) xor_byte));
X xor_byte ^= ((l >> 8) & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
X xor_byte ^= ((l >> 16) & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
X xor_byte ^= ((l >> 24) & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X = %ld\n", (int) xor_byte, (long) l));
X}
X
Xstatic void wr_bytes(c, count)
Xint8u *c;
Xregister int count;
X{
X register int i;
X register int8u *ptr;
X
X DEBUG(fprintf (logfile, "%d BYTES:", count));
X ptr = c;
X for (i = 0; i < count; i++)
X {
X xor_byte ^= *ptr++;
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X = %d", (int) xor_byte,
X (int) (ptr[-1])));
X }
X DEBUG(fprintf (logfile, "\n"));
X}
X
Xstatic void wr_string(str)
Xregister char *str;
X{
X DEBUG(char *s = str);
X DEBUG(fprintf (logfile, "STRING:"));
X while (*str != '\0')
X {
X xor_byte ^= *str++;
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
X }
X xor_byte ^= *str;
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X = \"%s\"\n", (int) xor_byte, s));
X}
X
Xstatic void wr_shorts(s, count)
Xint16u *s;
Xregister int count;
X{
X register int i;
X register int16u *sptr;
X
X DEBUG(fprintf (logfile, "%d SHORTS:", count));
X sptr = s;
X for (i = 0; i < count; i++)
X {
X xor_byte ^= (*sptr & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
X xor_byte ^= ((*sptr++ >> 8) & 0xFF);
X (void) putc((int)xor_byte, fileptr);
X DEBUG(fprintf (logfile, " %02X = %d", (int) xor_byte, (int) sptr[-1]));
X }
X DEBUG(fprintf (logfile, "\n"));
X}
X
Xstatic void wr_item(item)
Xregister inven_type *item;
X{
X DEBUG(fprintf (logfile, "ITEM:\n"));
X wr_short(item->index);
X wr_byte(item->name2);
X wr_string(item->inscrip);
X wr_long(item->flags);
X wr_byte(item->tval);
X wr_byte(item->tchar);
X wr_short((int16u)item->p1);
X wr_long((int32u)item->cost);
X wr_byte(item->subval);
X wr_byte(item->number);
X wr_short(item->weight);
X wr_short((int16u)item->tohit);
X wr_short((int16u)item->todam);
X wr_short((int16u)item->ac);
X wr_short((int16u)item->toac);
X wr_bytes(item->damage, 2);
X wr_byte(item->level);
X wr_byte(item->ident);
X}
X
Xstatic void wr_monster(mon)
Xregister monster_type *mon;
X{
X DEBUG(fprintf (logfile, "MONSTER:\n"));
X wr_short((int16u)mon->hp);
X wr_short((int16u)mon->csleep);
X wr_short((int16u)mon->cspeed);
X wr_short(mon->mptr);
X wr_byte(mon->fy);
X wr_byte(mon->fx);
X wr_byte(mon->cdis);
X wr_byte(mon->ml);
X wr_byte(mon->stunned);
X wr_byte(mon->confused);
X}
X
Xstatic void rd_byte(ptr)
Xint8u *ptr;
X{
X int8u c;
X
X c = getc(fileptr) & 0xFF;
X *ptr = c ^ xor_byte;
X xor_byte = c;
X DEBUG(fprintf (logfile, "BYTE: %02X = %d\n", (int) c, (int) *ptr));
X}
X
Xstatic void rd_short(ptr)
Xint16u *ptr;
X{
X int8u c;
X int16u s;
X
X c = (getc(fileptr) & 0xFF);
X s = c ^ xor_byte;
X xor_byte = (getc(fileptr) & 0xFF);
X s |= (int16u)(c ^ xor_byte) << 8;
X *ptr = s;
X DEBUG(fprintf (logfile, "SHORT: %02X %02X = %d\n", (int) c, (int) xor_byte,\
X (int) s));
X}
X
Xstatic void rd_long(ptr)
Xint32u *ptr;
X{
X register int32u l;
X register int8u c;
X
X c = (getc(fileptr) & 0xFF);
X l = c ^ xor_byte;
X xor_byte = (getc(fileptr) & 0xFF);
X l |= (int32u)(c ^ xor_byte) << 8;
X DEBUG(fprintf (logfile, "LONG: %02X %02X ", (int) c, (int) xor_byte));
X c = (getc(fileptr) & 0xFF);
X l |= (int32u)(c ^ xor_byte) << 16;
X xor_byte = (getc(fileptr) & 0xFF);
X l |= (int32u)(c ^ xor_byte) << 24;
X *ptr = l;
X DEBUG(fprintf (logfile, "%02X %02X = %ld\n", (int) c, (int) xor_byte,\
X (long) l));
X}
X
Xstatic void rd_bytes(ch_ptr, count)
Xint8u *ch_ptr;
Xregister int count;
X{
X register int i;
X register int8u *ptr;
X register int8u c;
X
X DEBUG(fprintf (logfile, "%d BYTES:", count));
X ptr = ch_ptr;
X for (i = 0; i < count; i++)
X {
X c = (getc(fileptr) & 0xFF);
X *ptr++ = c ^ xor_byte;
X xor_byte = c;
X DEBUG(fprintf (logfile, " %02X = %d", (int) c, (int) ptr[-1]));
X }
X DEBUG(fprintf (logfile, "\n"));
X}
X
Xstatic void rd_string(str)
Xchar *str;
X{
X register int8u c;
X
X DEBUG(char *s = str);
X DEBUG(fprintf (logfile, "STRING: "));
X do
X {
X c = (getc(fileptr) & 0xFF);
X *str = c ^ xor_byte;
X xor_byte = c;
X DEBUG(fprintf (logfile, "%02X ", (int) c));
X }
X while (*str++ != '\0');
X DEBUG(fprintf (logfile, "= \"%s\"\n", s));
X}
X
Xstatic void rd_shorts(ptr, count)
Xint16u *ptr;
Xregister int count;
X{
X register int i;
X register int16u *sptr;
X register int16u s;
X int8u c;
X
X DEBUG(fprintf (logfile, "%d SHORTS:", count));
X sptr = ptr;
X for (i = 0; i < count; i++)
X {
X c = (getc(fileptr) & 0xFF);
X s = c ^ xor_byte;
X xor_byte = (getc(fileptr) & 0xFF);
X s |= (int16u)(c ^ xor_byte) << 8;
X *sptr++ = s;
X DEBUG(fprintf (logfile, " %02X %02X = %d", (int) c, (int) xor_byte,\
X (int) s));
X }
X DEBUG(fprintf (logfile, "\n"));
X}
X
Xstatic void rd_item(item)
Xregister inven_type *item;
X{
X DEBUG(fprintf (logfile, "ITEM:\n"));
X rd_short(&item->index);
X rd_byte(&item->name2);
X rd_string(item->inscrip);
X rd_long(&item->flags);
X rd_byte(&item->tval);
X rd_byte(&item->tchar);
X rd_short((int16u *)&item->p1);
X rd_long((int32u *)&item->cost);
X rd_byte(&item->subval);
X rd_byte(&item->number);
X rd_short(&item->weight);
X rd_short((int16u *)&item->tohit);
X rd_short((int16u *)&item->todam);
X rd_short((int16u *)&item->ac);
X rd_short((int16u *)&item->toac);
X rd_bytes(item->damage, 2);
X rd_byte(&item->level);
X rd_byte(&item->ident);
X}
X
Xstatic void rd_monster(mon)
Xregister monster_type *mon;
X{
X DEBUG(fprintf (logfile, "MONSTER:\n"));
X rd_short((int16u *)&mon->hp);
X rd_short((int16u *)&mon->csleep);
X rd_short((int16u *)&mon->cspeed);
X rd_short(&mon->mptr);
X rd_byte(&mon->fy);
X rd_byte(&mon->fx);
X rd_byte(&mon->cdis);
X rd_byte(&mon->ml);
X rd_byte(&mon->stunned);
X rd_byte(&mon->confused);
X}
X
X/* functions called from death.c to implement the score file */
X
X/* set the local fileptr to the scorefile fileptr */
Xvoid set_fileptr(file)
XFILE *file;
X{
X fileptr = file;
X}
X
Xvoid wr_highscore(score)
Xhigh_scores *score;
X{
X DEBUG(logfile = fopen ("IO_LOG", "a"));
X DEBUG(fprintf (logfile, "Saving score:\n"));
X /* Save the encryption byte for robustness. */
X wr_byte(xor_byte);
X
X wr_long((int32u) score->points);
X wr_long((int32u) score->birth_date);
X wr_short((int16u) score->uid);
X wr_short((int16u) score->mhp);
X wr_short((int16u) score->chp);
X wr_byte(score->dun_level);
X wr_byte(score->lev);
X wr_byte(score->max_dlv);
X wr_byte(score->sex);
X wr_byte(score->race);
X wr_byte(score->class);
X wr_bytes((int8u *)score->name, PLAYER_NAME_SIZE);
X wr_bytes((int8u *)score->died_from, 25);
X DEBUG(fclose (logfile));
X}
X
Xvoid rd_highscore(score)
Xhigh_scores *score;
X{
X DEBUG(logfile = fopen ("IO_LOG", "a"));
X DEBUG(fprintf (logfile, "Reading score:\n"));
X /* Read the encryption byte. */
X rd_byte (&xor_byte);
X
X rd_long((int32u *)&score->points);
X rd_long((int32u *)&score->birth_date);
X rd_short((int16u *)&score->uid);
X rd_short((int16u *)&score->mhp);
X rd_short((int16u *)&score->chp);
X rd_byte(&score->dun_level);
X rd_byte(&score->lev);
X rd_byte(&score->max_dlv);
X rd_byte(&score->sex);
X rd_byte(&score->race);
X rd_byte(&score->class);
X rd_bytes((int8u *)score->name, PLAYER_NAME_SIZE);
X rd_bytes((int8u *)score->died_from, 25);
X DEBUG(fclose (logfile));
X}
END_OF_FILE
if test 41704 -ne `wc -c <'source/save.c'`; then
echo shar: \"'source/save.c'\" unpacked with wrong size!
fi
# end of 'source/save.c'
fi
if test -f 'source/tables.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source/tables.c'\"
else
echo shar: Extracting \"'source/tables.c'\" \(10747 characters\)
sed "s/^X//" >'source/tables.c' <<'END_OF_FILE'
X/* source/tables.c: store/attack/RNG/etc tables and variables
X
X Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X
X#ifdef MORIA_HOU
X/* Operating hours for Moria -RAK- */
X/* X = Open; . = Closed */
Xchar days[7][29] = { "SUN:XXXXXXXXXXXXXXXXXXXXXXXX",
X "MON:XXXXXXXX.........XXXXXXX",
X "TUE:XXXXXXXX.........XXXXXXX",
X "WED:XXXXXXXX.........XXXXXXX",
X "THU:XXXXXXXX.........XXXXXXX",
X "FRI:XXXXXXXX.........XXXXXXX",
X "SAT:XXXXXXXXXXXXXXXXXXXXXXXX" };
X#endif
X
X#ifdef MAC
Xstore_type *store;
X#else
Xstore_type store[MAX_STORES];
X#endif
X
X/* Store owners have different characteristics for pricing and haggling*/
X/* Note: Store owners should be added in groups, one for each store */
X#ifdef MACGAME
Xowner_type *owners;
X#else
Xowner_type owners[MAX_OWNERS] = {
X{"Erick the Honest (Human) General Store",
X 250, 175, 108, 4, 0, 12},
X{"Mauglin the Grumpy (Dwarf) Armory" ,
X 32000, 200, 112, 4, 5, 5},
X{"Arndal Beast-Slayer (Half-Elf) Weaponsmith" ,
X 10000, 185, 110, 5, 1, 8},
X{"Hardblow the Humble (Human) Temple" ,
X 3500, 175, 109, 6, 0, 15},
X{"Ga-nat the Greedy (Gnome) Alchemist" ,
X 12000, 220, 115, 4, 4, 9},
X{"Valeria Starshine (Elf) Magic Shop" ,
X 32000, 175, 110, 5, 2, 11},
X{"Andy the Friendly (Halfling) General Store",
X 200, 170, 108, 5, 3, 15},
X{"Darg-Low the Grim (Human) Armory" ,
X 10000, 190, 111, 4, 0, 9},
X{"Oglign Dragon-Slayer (Dwarf) Weaponsmith" ,
X 32000, 195, 112, 4, 5, 8},
X{"Gunnar the Paladin (Human) Temple" ,
X 5000, 185, 110, 5, 0, 23},
X{"Mauser the Chemist (Half-Elf) Alchemist" ,
X 10000, 190, 111, 5, 1, 8},
X{"Gopher the Great! (Gnome) Magic Shop" ,
X 20000, 215, 113, 6, 4, 10},
X{"Lyar-el the Comely (Elf) General Store",
X 300, 165, 107, 6, 2, 18},
X{"Mauglim the Horrible (Half-Orc) Armory" ,
X 3000, 200, 113, 5, 6, 9},
X{"Ithyl-Mak the Beastly (Half-Troll) Weaponsmith" ,
X 3000, 210, 115, 6, 7, 8},
X{"Delilah the Pure (Half-Elf) Temple" ,
X 25000, 180, 107, 6, 1, 20},
X{"Wizzle the Chaotic (Halfling) Alchemist" ,
X 10000, 190, 110, 6, 3, 8},
X{"Inglorian the Mage (Human?) Magic Shop" ,
X 32000, 200, 110, 7, 0, 10}
X};
X#endif
X
X/* Buying and selling adjustments for character race VS store */
X/* owner race */
Xint8u rgold_adj[MAX_RACES][MAX_RACES] = {
X /* Hum, HfE, Elf, Hal, Gno, Dwa, HfO, HfT*/
X/*Human */ { 100, 105, 105, 110, 113, 115, 120, 125},
X/*Half-Elf */ { 110, 100, 100, 105, 110, 120, 125, 130},
X/*Elf */ { 110, 105, 100, 105, 110, 120, 125, 130},
X/*Halfling */ { 115, 110, 105, 95, 105, 110, 115, 130},
X/*Gnome */ { 115, 115, 110, 105, 95, 110, 115, 130},
X/*Dwarf */ { 115, 120, 120, 110, 110, 95, 125, 135},
X/*Half-Orc */ { 115, 120, 125, 115, 115, 130, 110, 115},
X/*Half-Troll */ { 110, 115, 115, 110, 110, 130, 110, 110}
X };
X/* object_list[] index of objects that may appear in the store */
Xint16u store_choice[MAX_STORES][STORE_CHOICES] = {
X /* General Store */
X{366,365,364,84,84,365,123,366,365,350,349,348,347,346,346,345,345,345,
X 344,344,344,344,344,344,344,344},
X /* Armory */
X{94,95,96,109,103,104,105,106,110,111,112,114,116,124,125,126,127,129,103,
X 104,124,125,91,92,95,96},
X /* Weaponsmith */
X{29,30,34,37,45,49,57,58,59,65,67,68,73,74,75,77,79,80,81,83,29,30,80,83,
X 80,83},
X /* Temple */
X{322,323,324,325,180,180,233,237,240,241,361,362,57,58,59,260,358,359,265,
X 237,237,240,240,241,323,359},
X /* Alchemy shop */
X{173,174,175,351,351,352,353,354,355,356,357,206,227,230,236,252,253,352,
X 353,354,355,356,359,363,359,359},
X /* Magic-User store*/
X{318,141,142,153,164,167,168,140,319,320,320,321,269,270,282,286,287,292,
X 293,294,295,308,269,290,319,282}
X};
X
X#ifndef MAC
X/* MPW doesn't seem to handle this very well, so replace store_buy array
X with a function call on mac */
X/* functions defined in sets.c */
Xextern int general_store(), armory(), weaponsmith(), temple(),
X alchemist(), magic_shop();
X
X/* Each store will buy only certain items, based on TVAL */
Xint (*store_buy[MAX_STORES])() = {
X general_store, armory, weaponsmith, temple, alchemist, magic_shop};
X#endif
X
X/* Following are arrays for descriptive pieces */
X
X#ifdef MACGAME
X
Xchar **colors;
Xchar **mushrooms;
Xchar **woods;
Xchar **metals;
Xchar **rocks;
Xchar **amulets;
Xchar **syllables;
X
X#else
X
Xchar *colors[MAX_COLORS] = {
X/* Do not move the first three */
X "Icky Green", "Light Brown", "Clear",
X "Azure","Blue","Blue Speckled","Black","Brown","Brown Speckled","Bubbling",
X "Chartreuse","Cloudy","Copper Speckled","Crimson","Cyan","Dark Blue",
X "Dark Green","Dark Red","Gold Speckled","Green","Green Speckled","Grey",
X "Grey Speckled","Hazy","Indigo","Light Blue","Light Green","Magenta",
X "Metallic Blue","Metallic Red","Metallic Green","Metallic Purple","Misty",
X "Orange","Orange Speckled","Pink","Pink Speckled","Puce","Purple",
X "Purple Speckled","Red","Red Speckled","Silver Speckled","Smoky",
X "Tangerine","Violet","Vermilion","White","Yellow"
X};
X
Xchar *mushrooms[MAX_MUSH] = {
X "Blue","Black","Black Spotted","Brown","Dark Blue","Dark Green","Dark Red",
X "Ecru","Furry","Green","Grey","Light Blue","Light Green","Plaid","Red",
X "Slimy","Tan","White","White Spotted","Wooden","Wrinkled","Yellow",
X};
X
Xchar *woods[MAX_WOODS] = {
X "Aspen","Balsa","Banyan","Birch","Cedar","Cottonwood","Cypress","Dogwood",
X "Elm","Eucalyptus","Hemlock","Hickory","Ironwood","Locust","Mahogany",
X "Maple","Mulberry","Oak","Pine","Redwood","Rosewood","Spruce","Sycamore",
X "Teak","Walnut",
X};
X
Xchar *metals[MAX_METALS] = {
X "Aluminum","Cast Iron","Chromium","Copper","Gold","Iron","Magnesium",
X "Molybdenum","Nickel","Rusty","Silver","Steel","Tin","Titanium","Tungsten",
X "Zirconium","Zinc","Aluminum-Plated","Copper-Plated","Gold-Plated",
X "Nickel-Plated","Silver-Plated","Steel-Plated","Tin-Plated","Zinc-Plated"
X};
X
Xchar *rocks[MAX_ROCKS] = {
X "Alexandrite","Amethyst","Aquamarine","Azurite","Beryl","Bloodstone",
X "Calcite","Carnelian","Corundum","Diamond","Emerald","Fluorite","Garnet",
X "Granite","Jade","Jasper","Lapis Lazuli","Malachite","Marble","Moonstone",
X "Onyx","Opal","Pearl","Quartz","Quartzite","Rhodonite","Ruby","Sapphire",
X "Tiger Eye","Topaz","Turquoise","Zircon"
X};
X
Xchar *amulets[MAX_AMULETS] = {
X "Amber","Driftwood","Coral","Agate","Ivory","Obsidian",
X "Bone","Brass","Bronze","Pewter","Tortoise Shell"
X};
X
Xchar *syllables[MAX_SYLLABLES] = {
X "a","ab","ag","aks","ala","an","ankh","app",
X "arg","arze","ash","aus","ban","bar","bat","bek",
X "bie","bin","bit","bjor","blu","bot","bu",
X "byt","comp","con","cos","cre","dalf","dan",
X "den","doe","dok","eep","el","eng","er","ere","erk",
X "esh","evs","fa","fid","for","fri","fu","gan",
X "gar","glen","gop","gre","ha","he","hyd","i",
X "ing","ion","ip","ish","it","ite","iv","jo",
X "kho","kli","klis","la","lech","man","mar",
X "me","mi","mic","mik","mon","mung","mur","nej",
X "nelg","nep","ner","nes","nis","nih","nin","o",
X "od","ood","org","orn","ox","oxy","pay","pet",
X "ple","plu","po","pot","prok","re","rea","rhov",
X "ri","ro","rog","rok","rol","sa","san","sat",
X "see","sef","seh","shu","ski","sna","sne","snik",
X "sno","so","sol","sri","sta","sun","ta","tab",
X "tem","ther","ti","tox","trol","tue","turs","u",
X "ulk","um","un","uni","ur","val","viv","vly",
X "vom","wah","wed","werg","wex","whon","wun","x",
X "yerg","yp","zun"
X};
X#endif
X
X/* used to calculate the number of blows the player gets in combat */
Xint8u blows_table[7][6] = {
X/* STR/W: 9 18 67 107 117 118 : DEX */
X/* <2 */ { 1, 1, 1, 1, 1, 1 },
X/* <3 */ { 1, 1, 1, 1, 2, 2 },
X/* <4 */ { 1, 1, 1, 2, 2, 3 },
X/* <5 */ { 1, 1, 2, 2, 3, 3 },
X/* <7 */ { 1, 2, 2, 3, 3, 4 },
X/* <9 */ { 1, 2, 2, 3, 4, 4 },
X/* >9 */ { 2, 2, 3, 3, 4, 4 }
X};
X
X/* this table is used to generate a psuedo-normal distribution. See the
X function randnor() in misc1.c, this is much faster than calling
X transcendental function to calculate a true normal distribution */
Xint16u normal_table[NORMAL_TABLE_SIZE] = {
X 206, 613, 1022, 1430, 1838, 2245, 2652, 3058,
X 3463, 3867, 4271, 4673, 5075, 5475, 5874, 6271,
X 6667, 7061, 7454, 7845, 8234, 8621, 9006, 9389,
X 9770, 10148, 10524, 10898, 11269, 11638, 12004, 12367,
X 12727, 13085, 13440, 13792, 14140, 14486, 14828, 15168,
X 15504, 15836, 16166, 16492, 16814, 17133, 17449, 17761,
X 18069, 18374, 18675, 18972, 19266, 19556, 19842, 20124,
X 20403, 20678, 20949, 21216, 21479, 21738, 21994, 22245,
X 22493, 22737, 22977, 23213, 23446, 23674, 23899, 24120,
X 24336, 24550, 24759, 24965, 25166, 25365, 25559, 25750,
X 25937, 26120, 26300, 26476, 26649, 26818, 26983, 27146,
X 27304, 27460, 27612, 27760, 27906, 28048, 28187, 28323,
X 28455, 28585, 28711, 28835, 28955, 29073, 29188, 29299,
X 29409, 29515, 29619, 29720, 29818, 29914, 30007, 30098,
X 30186, 30272, 30356, 30437, 30516, 30593, 30668, 30740,
X 30810, 30879, 30945, 31010, 31072, 31133, 31192, 31249,
X 31304, 31358, 31410, 31460, 31509, 31556, 31601, 31646,
X 31688, 31730, 31770, 31808, 31846, 31882, 31917, 31950,
X 31983, 32014, 32044, 32074, 32102, 32129, 32155, 32180,
X 32205, 32228, 32251, 32273, 32294, 32314, 32333, 32352,
X 32370, 32387, 32404, 32420, 32435, 32450, 32464, 32477,
X 32490, 32503, 32515, 32526, 32537, 32548, 32558, 32568,
X 32577, 32586, 32595, 32603, 32611, 32618, 32625, 32632,
X 32639, 32645, 32651, 32657, 32662, 32667, 32672, 32677,
X 32682, 32686, 32690, 32694, 32698, 32702, 32705, 32708,
X 32711, 32714, 32717, 32720, 32722, 32725, 32727, 32729,
X 32731, 32733, 32735, 32737, 32739, 32740, 32742, 32743,
X 32745, 32746, 32747, 32748, 32749, 32750, 32751, 32752,
X 32753, 32754, 32755, 32756, 32757, 32757, 32758, 32758,
X 32759, 32760, 32760, 32761, 32761, 32761, 32762, 32762,
X 32763, 32763, 32763, 32764, 32764, 32764, 32764, 32765,
X 32765, 32765, 32765, 32766, 32766, 32766, 32766, 32766,
X};
END_OF_FILE
if test 10747 -ne `wc -c <'source/tables.c'`; then
echo shar: \"'source/tables.c'\" unpacked with wrong size!
fi
# end of 'source/tables.c'
fi
echo shar: End of archive 8 \(of 39\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 39 archives.
echo "Now run "bldfiles.sh" to build split files"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0