home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume10
/
nethack3p9
/
part27
< prev
next >
Wrap
Internet Message Format
|
1990-07-27
|
60KB
Path: uunet!cs.utexas.edu!rice!uw-beaver!zephyr.ens.tek.com!tekred!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v10i072: nethack3p9 - display oriented dungeons & dragons (Ver. 3.0i), Part27/56
Message-ID: <5930@tekred.CNA.TEK.COM>
Date: 12 Jul 90 16:03:29 GMT
Sender: news@tekred.CNA.TEK.COM
Lines: 2495
Approved: billr@saab.CNA.TEK.COM
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 72
Archive-name: nethack3p9/Part27
Supersedes: NetHack3: Volume 7, Issue 56-93
#! /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 27 (of 56)."
# Contents: others/msdos.c src/restore.c
# Wrapped by billr@saab on Wed Jul 11 17:11:32 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'others/msdos.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'others/msdos.c'\"
else
echo shar: Extracting \"'others/msdos.c'\" \(30281 characters\)
sed "s/^X//" >'others/msdos.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)msdos.c 3.0 89/12/26
X/* NetHack may be freely redistributed. See license for details. */
X/* An assortment of MSDOS functions.
X */
X
X#define NEED_VARARGS
X#include "hack.h"
X
X#ifdef MSDOS
X
X# ifdef TOS
X# include <osbind.h>
X# ifndef WORD
X# define WORD short /* 16 bits -- redefine if necessary */
X# endif
X# else
X# ifdef __TURBOC__ /* avoid incompatible redeclaration */
X# undef getdate
X# endif
X# include <dos.h>
X# endif
X# ifdef OS2
X# include "def_os2.h" /* OS2 definitions (Timo Hakulinen) */
X# endif
X
X#include <ctype.h>
X#include <fcntl.h>
X#include <process.h>
X
Xstatic char NDECL(DOSgetch);
X# ifdef DGK
Xstatic char NDECL(BIOSgetch);
X# endif
X# ifdef TOS
Xstatic void NDECL(init_aline);
Xchar *_a_line; /* for Line A variables */
X# else
Xstatic unsigned int FDECL(ioctl, (int,int,unsigned));
Xstatic boolean NDECL(comspec_exists);
X# endif
X
Xstatic int FDECL(findfirst, (char *));
Xstatic int NDECL(findnext);
Xstatic boolean NDECL(record_exists);
X# if !defined(TOS) && !defined(__TURBOC__) && !defined(OS2)
Xstatic char NDECL(switchar);
X# endif
X# ifndef OS2
Xstatic char * NDECL(getdta);
X# endif
X
Xvoid
Xflushout()
X{
X (void) fflush(stdout);
X return;
X}
X
Xint
Xtgetch() {
X char ch;
X
X# ifdef DGK
X /* BIOSgetch can use the numeric key pad on IBM compatibles. */
X if (flags.IBMBIOS)
X ch = BIOSgetch();
X else
X# endif
X ch = DOSgetch();
X return ((ch == '\r') ? '\n' : ch);
X}
X
X# if !defined(OS2) && !defined(TOS)
X/*
X * MS-DOS functions
X */
X#define DIRECT_INPUT 0x07 /* Unfiltered Character Input Without Echo */
X#define FATINFO 0x1B /* Get Default Drive Data */
X/* MS-DOS 2.0+: */
X#define GETDTA 0x2F /* Get DTA Address */
X#define FREESPACE 0x36 /* Get Drive Allocation Info */
X#define GETSWITCHAR 0x3700 /* Get Switch Character */
X#define FINDFIRST 0x4E /* Find First File */
X#define FINDNEXT 0x4F /* Find Next File */
X#define SETFILETIME 0x5701 /* Set File Date & Time */
X/*
X * BIOS interrupts
X */
X#define KEYBRD_BIOS 0x16
X#define VIDEO_BIOS 0x10
X/*
X * Keyboard BIOS functions
X */
X#define READCHAR 0x00 /* Read Character from Keyboard */
X#define GETKEYFLAGS 0x02 /* Get Keyboard Flags */
X/*
X * Video BIOS functions
X */
X#define SETCURPOS 0x02 /* Set Cursor Position */
X#define GETMODE 0x0f /* Get Video Mode */
X#define FONTINFO 0x1130 /* Get Font Info */
X# endif
X
X
X/*
X * Keyboard translation tables.
X */
X# ifdef TOS
X#define KEYPADLO 0x61
X#define KEYPADHI 0x71
X# else
X#define KEYPADLO 0x47
X#define KEYPADHI 0x53
X# endif
X
X#define PADKEYS (KEYPADHI - KEYPADLO + 1)
X#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
X
X/*
X * Keypad keys are translated to the normal values below.
X * When IBM_BIOS is active, shifted keypad keys are translated to the
X * shift values below.
X */
Xstatic const struct pad {
X char normal, shift, cntrl;
X} keypad[PADKEYS] = {
X# ifdef TOS
X {C('['), 'Q', C('[')}, /* UNDO */
X {'?', '/', '?'}, /* HELP */
X {'(', 'a', '('}, /* ( */
X {')', 'w', ')'}, /* ) */
X {'/', '/', '/'}, /* / */
X {C('p'), '$', C('p')}, /* * */
X# endif
X {'y', 'Y', C('y')}, /* 7 */
X {'k', 'K', C('k')}, /* 8 */
X {'u', 'U', C('u')}, /* 9 */
X# ifndef TOS
X {'m', C('p'), C('p')}, /* - */
X# endif
X {'h', 'H', C('h')}, /* 4 */
X# ifdef TOS
X {'.', '.', '.'},
X# else
X {'g', 'g', 'g'}, /* 5 */
X# endif
X {'l', 'L', C('l')}, /* 6 */
X# ifndef TOS
X {'p', 'P', C('p')}, /* + */
X# endif
X {'b', 'B', C('b')}, /* 1 */
X {'j', 'J', C('j')}, /* 2 */
X {'n', 'N', C('n')}, /* 3 */
X {'i', 'I', C('i')}, /* Ins */
X {'.', ':', ':'} /* Del */
X}, numpad[PADKEYS] = {
X# ifdef TOS
X {C('['), 'Q', C('[')} , /* UNDO */
X {'?', '/', '?'}, /* HELP */
X {'(', 'a', '('}, /* ( */
X {')', 'w', ')'}, /* ) */
X {'/', '/', '/'}, /* / */
X {C('p'), '$', C('p')}, /* * */
X# endif
X {'7', M('7'), '7'}, /* 7 */
X {'8', M('8'), '8'}, /* 8 */
X {'9', M('9'), '9'}, /* 9 */
X# ifndef TOS
X {'m', C('p'), C('p')}, /* - */
X# endif
X {'4', M('4'), '4'}, /* 4 */
X# ifdef TOS
X {'.', '.', '.'}, /* 5 */
X# else
X {'g', 'G', 'g'}, /* 5 */
X# endif
X {'6', M('6'), '6'}, /* 6 */
X# ifndef TOS
X {'p', 'P', C('p')}, /* + */
X# endif
X {'1', M('1'), '1'}, /* 1 */
X {'2', M('2'), '2'}, /* 2 */
X {'3', M('3'), '3'}, /* 3 */
X {'i', 'I', C('i')}, /* Ins */
X {'.', ':', ':'} /* Del */
X};
X
X/*
X * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
X * meaning unless assigned one by a keyboard conversion table, so the
X * keyboard BIOS normally does not return a character code when Alt-letter
X * is pressed. So, to interpret unassigned Alt-letters, we must use a
X * scan code table to translate the scan code into a letter, then set the
X * "meta" bit for it. -3.
X */
X#define SCANLO 0x10
X#define SCANHI 0x32
X#define SCANKEYS (SCANHI - SCANLO + 1)
X#define inmap(x) (SCANLO <= (x) && (x) <= SCANHI)
X
Xstatic const char scanmap[SCANKEYS] = { /* ... */
X 'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
X 0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
X 0, '\\', 'z','x','c','v','b','N','m' /* ... */
X};
X
X# ifdef DGK
X/*
X * BIOSgetch gets keys directly with a BIOS call.
X */
X#define SHIFT (0x1 | 0x2)
X#define CTRL 0x4
X#define ALT 0x8
X
Xstatic char
XBIOSgetch() {
X unsigned char scan, shift, ch;
X const struct pad *kpad;
X
X# ifdef OS2
X KBDKEYINFO CharData;
X USHORT IOWait = 0;
X HKBD KbdHandle = 0;
X
X KbdCharIn(&CharData,IOWait,KbdHandle);
X ch = CharData.chChar;
X scan = CharData.chScan;
X shift = CharData.fsState;
X# else /* OS2 */
X# ifdef TOS
X long x;
X# else
X union REGS regs;
X# endif
X
X /* Get scan code.
X */
X# ifdef TOS
X x = Crawcin();
X ch = x & 0x0ff;
X scan = (x & 0x00ff0000L) >> 16;
X# else
X regs.h.ah = READCHAR;
X int86(KEYBRD_BIOS, ®s, ®s);
X ch = regs.h.al;
X scan = regs.h.ah;
X# endif
X /* Get shift status.
X */
X# ifdef TOS
X shift = Kbshift(-1);
X# else
X regs.h.ah = GETKEYFLAGS;
X int86(KEYBRD_BIOS, ®s, ®s);
X shift = regs.h.al;
X# endif
X# endif /* OS2 */
X
X /* Translate keypad keys */
X if (iskeypad(scan)) {
X kpad = flags.num_pad ? numpad : keypad;
X if (shift & SHIFT)
X ch = kpad[scan - KEYPADLO].shift;
X else if (shift & CTRL)
X ch = kpad[scan - KEYPADLO].cntrl;
X else
X ch = kpad[scan - KEYPADLO].normal;
X }
X /* Translate unassigned Alt-letters */
X if ((shift & ALT) && !ch) {
X if (inmap(scan))
X ch = scanmap[scan - SCANLO];
X return (isprint(ch) ? M(ch) : ch);
X }
X return ch;
X}
X
Xstatic char
XDOSgetch() {
X# ifdef TOS
X return (Crawcin() & 0x007f);
X# else
X# ifdef OS2
X KBDKEYINFO CharData;
X USHORT IOWait = 0;
X HKBD KbdHandle = 0;
X
X KbdCharIn(&CharData,IOWait,KbdHandle);
X if (CharData.chChar == 0) { /* an extended code -- not yet supported */
X KbdCharIn(&CharData,IOWait,KbdHandle); /* eat the next character */
X CharData.chChar = 0; /* and return a 0 */
X }
X return (CharData.chChar);
X# else
X union REGS regs;
X char ch;
X struct pad (*kpad)[PADKEYS];
X
X regs.h.ah = DIRECT_INPUT;
X intdos(®s, ®s);
X ch = regs.h.al;
X
X /*
X * The extended codes for Alt-shifted letters, and unshifted keypad
X * and function keys, correspond to the scan codes. So we can still
X * translate the unshifted cursor keys and Alt-letters. -3.
X */
X if (ch == 0) { /* an extended key */
X regs.h.ah = DIRECT_INPUT;
X intdos(®s, ®s); /* get the extended key code */
X ch = regs.h.al;
X
X if (iskeypad(ch)) { /* unshifted keypad keys */
X kpad = (void *)(flags.num_pad ? numpad : keypad);
X ch = (*kpad)[ch - KEYPADLO].normal;
X } else if (inmap(ch)) { /* Alt-letters */
X ch = scanmap[ch - SCANLO];
X if (isprint(ch)) ch = M(ch);
X } else ch = 0; /* munch it */
X }
X return (ch);
X# endif /* OS2 */
X# endif /* TOS */
X}
X
X
X# ifndef TOS
X
X# ifdef __TURBOC__
X#define switchar() (char)getswitchar()
X# else
X# ifndef OS2
Xstatic char
Xswitchar()
X{
X union REGS regs;
X
X regs.x.ax = GETSWITCHAR;
X intdos(®s, ®s);
X return regs.h.dl;
X}
X# endif /* OS2 */
X# endif /* __TURBOC__ */
X# endif /* TOS */
X
Xstatic const char *COMSPEC =
X# ifdef TOS
X"SHELL";
X# else
X"COMSPEC";
X# endif
X
X#define getcomspec() getenv(COMSPEC)
X
X# ifdef SHELL
Xint
Xdosh() {
X extern char orgdir[];
X char *comspec;
X
X if (comspec = getcomspec()) {
X# if defined(DGK) && !defined(TOS) /* TOS has a variety of shells */
X settty("To return to NetHack, enter \"exit\" at the DOS prompt.\n");
X# else
X settty((char *)0);
X# endif /* DGK */
X chdirx(orgdir, 0);
X if (spawnl(P_WAIT, comspec, comspec, NULL) < 0) {
X Printf("\nCan't spawn \"%s\"!\n", comspec);
X flags.toplin = 0;
X more();
X }
X#ifdef TOS
X/* Some shells (e.g. Gulam) turn the cursor off when they exit */
X if (flags.IBMBIOS) {
X (void)Cursconf(1, -1);
X get_scr_size(); /* maybe they changed the screen */
X }
X#else
X gettty(); /* ctrl-P might get turned back on (TH) */
X get_scr_size(); /* maybe the screen mode changed (TH) */
X#endif
X chdirx(hackdir, 0);
X start_screen();
X docrt();
X } else
X# ifdef OS2
X pline("Can't execute CMD.EXE");
X# else
X# ifdef TOS
X pline("Can't find SHELL.");
X# else
X pline("Can't find COMSPEC.");
X# endif
X# endif /* OS2 */
X return 0;
X}
X# endif /* SHELL */
X
X#ifndef TOS
X
Xlong
Xfreediskspace(path)
Xchar *path;
X{
X# ifdef OS2
X struct {
X ULONG idFileSystem;
X ULONG cSectorUnit;
X ULONG cUnit;
X ULONG cUnitAvail;
X USHORT cbSector;
X } FSInfoBuf;
X USHORT DriveNumber, FSInfoLevel = 1, res;
X
X if (path[0] && path[1] == ':')
X DriveNumber = (toupper(path[0]) - 'A') + 1;
X else
X DriveNumber = 0;
X res = DosQFSInfo(DriveNumber,FSInfoLevel,(PBYTE)&FSInfoBuf,sizeof(FSInfoBuf));
X if (res)
X return -1L; /* error */
X else
X return ((long) FSInfoBuf.cSectorUnit * FSInfoBuf.cUnitAvail *
X FSInfoBuf.cbSector);
X# else /* OS2 */
X union REGS regs;
X
X regs.h.ah = FREESPACE;
X if (path[0] && path[1] == ':')
X regs.h.dl = (toupper(path[0]) - 'A') + 1;
X else
X regs.h.dl = 0;
X intdos(®s, ®s);
X if (regs.x.ax == 0xFFFF)
X return -1L; /* bad drive number */
X else
X return ((long) regs.x.bx * regs.x.cx * regs.x.ax);
X# endif /* OS2 */
X}
X
X# ifdef OS2
XFILEFINDBUF ResultBuf;
XHDIR DirHandle;
X# endif
X
X/* Functions to get filenames using wildcards
X */
Xstatic int
Xfindfirst(path)
Xchar *path;
X{
X# ifdef OS2
X USHORT res, SearchCount = 1;
X
X DirHandle = 1;
X res = DosFindFirst((PSZ)path,&DirHandle,0,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount,0L);
X return(!res);
X# else
X union REGS regs;
X struct SREGS sregs;
X
X regs.h.ah = FINDFIRST;
X regs.x.cx = 0; /* attribute: normal files */
X regs.x.dx = FP_OFF(path);
X sregs.ds = FP_SEG(path);
X intdosx(®s, ®s, &sregs);
X return !regs.x.cflag;
X# endif /* OS2 */
X}
X
Xstatic int
Xfindnext() {
X# ifdef OS2
X USHORT res, SearchCount = 1;
X
X res = DosFindNext(DirHandle,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount);
X return(!res);
X# else
X union REGS regs;
X
X regs.h.ah = FINDNEXT;
X intdos(®s, ®s);
X return !regs.x.cflag;
X# endif /* OS2 */
X}
X
X# ifndef OS2
X/* Get disk transfer area, Turbo C already has getdta */
Xstatic char *
Xgetdta() {
X union REGS regs;
X struct SREGS sregs;
X char *ret;
X
X regs.h.ah = GETDTA;
X intdosx(®s, ®s, &sregs);
X# ifdef MK_FP
X ret = MK_FP(sregs.es, regs.x.bx);
X# else
X FP_OFF(ret) = regs.x.bx;
X FP_SEG(ret) = sregs.es;
X# endif
X return ret;
X}
X# endif /* OS2 */
X
X# else /* TOS */
X
Xlong
Xfreediskspace(path)
Xchar *path;
X{
X int drive = 0;
X struct {
X long freal; /*free allocation units*/
X long total; /*total number of allocation units*/
X long bps; /*bytes per sector*/
X long pspal; /*physical sectors per allocation unit*/
X } freespace;
X if (path[0] && path[1] == ':')
X drive = (toupper(path[0]) - 'A') + 1;
X if (Dfree(&freespace,drive)<0) return -1;
X return freespace.freal*freespace.bps*freespace.pspal;
X}
X
Xstatic int
Xfindfirst(path)
Xchar *path;
X{
X return (Fsfirst(path, 0) == 0);
X}
X
Xstatic int findnext() {
X return (Fsnext() == 0);
X}
X
Xstatic char *
Xgetdta() {
X return (char *) Fgetdta();
X}
X
X# endif /* TOS */
X
Xlong
Xfilesize(file)
Xchar *file;
X{
X# ifndef OS2
X char *dta;
X# endif
X
X if (findfirst(file)) {
X# ifdef OS2
X return (* (long *) (ResultBuf.cbFileAlloc));
X# else
X dta = getdta();
X return (* (long *) (dta + 26));
X# endif
X } else
X return -1L;
X}
X
Xvoid
Xeraseall(path, files)
Xconst char *path, *files;
X{
X# ifndef OS2
X char *dta;
X# endif
X char buf[PATHLEN];
X
X# ifndef OS2
X dta = getdta();
X# endif
X Sprintf(buf, "%s%s", path, files);
X if (findfirst(buf))
X do {
X Sprintf(buf, "%s%s", path,
X# ifdef OS2
X ResultBuf.achName
X# else
X dta + 30
X# endif
X );
X (void) unlink(buf);
X } while (findnext());
X return;
X}
X
X/* Rewritten for version 3.3 to be faster
X */
Xvoid
Xcopybones(mode)
Xint mode;
X{
X char from[PATHLEN], to[PATHLEN], last[13];
X char *frompath, *topath;
X# ifndef OS2
X char *dta;
X# endif
X# ifndef TOS
X int status;
X char copy[8], *comspec;
X extern saveprompt;
X# endif
X
X if (!ramdisk)
X return;
X
X /* Find the name of the last file to be transferred
X */
X frompath = (mode != TOPERM) ? permbones : levels;
X# ifndef OS2
X dta = getdta();
X# endif
X last[0] = '\0';
X Sprintf(from, "%s%s", frompath, allbones);
X topath = (mode == TOPERM) ? permbones : levels;
X# ifdef TOS
X eraseall(topath, allbones);
X# endif
X if (findfirst(from))
X do {
X# ifdef TOS
X Sprintf(from, "%s%s", frompath, dta+30);
X Sprintf(to, "%s%s", topath, dta+30);
X if (_copyfile(from, to))
X goto error_copying;
X# endif
X Strcpy(last,
X# ifdef OS2
X ResultBuf.achName
X# else
X dta + 30
X# endif
X );
X } while (findnext());
X# ifdef TOS
X else
X return;
X# else
X if (last[0]) {
X Sprintf(copy, "%cC copy",
X# ifdef OS2
X '/'
X# else
X switchar()
X# endif
X );
X
X /* Remove any bones files in `to' directory.
X */
X eraseall(topath, allbones);
X
X /* Copy `from' to `to' */
X Sprintf(to, "%s%s", topath, allbones);
X comspec = getcomspec();
X status =spawnl(P_WAIT, comspec, comspec, copy, from,
X to, "> nul", NULL);
X } else
X return;
X# endif /* TOS */
X
X /* See if the last file got there. If so, remove the ramdisk bones
X * files.
X */
X Sprintf(to, "%s%s", topath, last);
X if (findfirst(to)) {
X if (mode == TOPERM)
X eraseall(frompath, allbones);
X return;
X }
X
X# ifdef TOS
Xerror_copying:
X# endif
X /* Last file didn't get there.
X */
X Sprintf(to, "%s%s", topath, allbones);
X msmsg("Can't copy \"%s\" to \"%s\" -- ", from, to);
X# ifndef TOS
X if (status < 0)
X msmsg("can't spawn \"%s\"!", comspec);
X else
X# endif
X msmsg((freediskspace(topath) < filesize(from)) ?
X "insufficient disk space." : "bad path(s)?");
X if (mode == TOPERM) {
X msmsg("Bones will be left in \"%s\"\n",
X *levels ? levels : hackdir);
X } else {
X /* Remove all bones files on the RAMdisk */
X eraseall(levels, allbones);
X playwoRAMdisk();
X }
X return;
X}
X
X#if 0 /* defined(MSDOS) && !defined(TOS) && !defined(OS2) */
Xboolean
Xremoveable_drive(drive)
Xchar drive;
X/* check whether current drive is a fixed disk,
X so we don't ask the player to insert one */
X{
X union REGS regs;
X char *fat_id;
X
X regs.h.ah = FATINFO;
X intdos(®s, ®s);
X /* also returns size info, as
X AL (sectors/cluster) * CX (bytes/sector) * DX (clusters/disk) */
X# ifdef MK_FP
X fat_id = MK_FP(sregs.ds, regs.x.bx);
X# else
X FP_OFF(fat_id) = regs.x.bx;
X FP_SEG(fat_id) = sregs.ds;
X# endif
X return (*fat_id != 0xF8);
X}
X#endif /* 0 */
X
Xvoid
XplaywoRAMdisk() {
X msmsg("Do you wish to play without a RAMdisk? ");
X
X /* Set ramdisk false *before* exit-ing (because msexit calls
X * copybones)
X */
X ramdisk = FALSE;
X if (yn() != 'y') {
X settty("Be seeing you...\n");
X exit(0);
X }
X set_lock_and_bones();
X return;
X}
X
Xint
XsaveDiskPrompt(start)
Xint start;
X{
X extern saveprompt;
X char buf[BUFSIZ], *bp;
X int fd;
X
X if (saveprompt) {
X /* Don't prompt if you can find the save file */
X if ((fd = open(SAVEF, 0)) >= 0) {
X (void) close(fd);
X return 1;
X }
X remember_topl();
X home();
X cl_end();
X msmsg("If save file is on a save disk, insert that disk now.\n");
X cl_end();
X msmsg("File name (default \"%s\"%s) ? ", SAVEF,
X start ? "" : ", <Esc> cancels save");
X getlin(buf);
X home();
X cl_end();
X curs(1, 2);
X cl_end();
X if (!start && *buf == '\033')
X return 0;
X
X /* Strip any whitespace. Also, if nothing was entered except
X * whitespace, do not change the value of SAVEF.
X */
X for (bp = buf; *bp; bp++)
X if (!isspace(*bp)) {
X strncpy(SAVEF, bp, PATHLEN);
X break;
X }
X }
X return 1;
X}
X
X/* Return 1 if the record file was found */
Xstatic boolean
Xrecord_exists() {
X int fd;
X# ifdef OS2_CODEVIEW
X char tmp[PATHLEN];
X
X Strcpy(tmp,hackdir);
X append_slash(tmp);
X Strcat(tmp,RECORD);
X if ((fd = open(tmp, 0)) >= 0) {
X# else
X if ((fd = open(RECORD, 0)) >= 0) {
X# endif
X (void) close(fd);
X return TRUE;
X }
X return FALSE;
X}
X
X# ifdef TOS
X#define comspec_exists() 1
X# else
X/* Return 1 if the comspec was found */
Xstatic boolean
Xcomspec_exists() {
X int fd;
X char *comspec;
X
X if (comspec = getcomspec())
X if ((fd = open(comspec, 0)) >= 0) {
X (void) close(fd);
X return TRUE;
X }
X return FALSE;
X}
X# endif
X
X/* Prompt for game disk, then check for record file.
X */
Xvoid
XgameDiskPrompt() {
X extern int saveprompt;
X
X if (saveprompt) {
X if (record_exists() && comspec_exists())
X return;
X (void) putchar('\n');
X getreturn("when the game disk has been inserted");
X }
X if (comspec_exists() && record_exists())
X return;
X
X if (!comspec_exists())
X msmsg("\n\nWARNING: can't find command processor \"%s\"!\n", getcomspec());
X if (!record_exists())
X msmsg("\n\nWARNING: can't find record file \"%s\"!\n", RECORD);
X msmsg("If the game disk is not in, insert it now.\n");
X getreturn("to continue");
X return;
X}
X
X# endif /* DGK */
X
X/* Read configuration */
Xvoid
Xread_config_file() {
X# ifdef DGK
X char tmp_ramdisk[PATHLEN];
X extern int saveprompt;
X# else
X#define fopenp fopen
X# endif
X char tmp_levels[PATHLEN];
X char buf[BUFSZ], *bufp;
X FILE *fp;
X extern char plname[];
X
X# ifdef DGK
X tmp_ramdisk[0] = 0;
X# endif
X tmp_levels[0] = 0;
X if ((fp = fopenp(configfile, "r")) == (FILE *)0) {
X msmsg("Warning: no configuration file!\n");
X getreturn("to continue");
X return;
X }
X while (fgets(buf, BUFSZ, fp)) {
X if (*buf == '#')
X continue;
X
X /* remove trailing whitespace
X */
X bufp = index(buf, '\n');
X while (bufp > buf && isspace(*bufp))
X bufp--;
X if (bufp == buf)
X continue; /* skip all-blank lines */
X else
X *(bufp + 1) = 0; /* 0 terminate line */
X
X /* find the '=' */
X if (!(bufp = strchr(buf, '='))) {
X msmsg("Bad option line: \"%s\"\n", buf);
X getreturn("to continue");
X continue;
X }
X
X /* skip whitespace between '=' and value */
X while (isspace(*++bufp))
X ;
X
X /* Go through possible variables */
X if (!strncmp(buf, "HACKDIR", 4)) {
X strncpy(hackdir, bufp, PATHLEN);
X
X# ifdef DGK
X } else if (!strncmp(buf, "RAMDISK", 3)) {
X strncpy(tmp_ramdisk, bufp, PATHLEN);
X# endif
X
X } else if (!strncmp(buf, "LEVELS", 4)) {
X strncpy(tmp_levels, bufp, PATHLEN);
X
X } else if (!strncmp(buf, "OPTIONS", 4)) {
X parseoptions(bufp, TRUE);
X if (plname[0]) /* If a name was given */
X plnamesuffix(); /* set the character class */
X
X } else if (!strncmp(buf, "SAVE", 4)) {
X# ifdef DGK
X char *ptr;
X if (ptr = index(bufp, ';')) {
X *ptr = '\0';
X if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
X saveprompt = FALSE;
X }
X# endif /* DGK */
X (void) strncpy(SAVEF, bufp, PATHLEN);
X (void) strncpy(SAVEP, bufp, PATHLEN);
X append_slash(SAVEF);
X append_slash(SAVEP);
X } else if (!strncmp(buf, "GRAPHICS", 4)) {
X unsigned int translate[MAXPCHARS+1];
X int lth;
X#ifdef OVERLAY
X /* THIS is what I call a stupid hack, but MSC cannot survive
X the overlays without it (TH) */
X lth = sscanf(bufp,
X "%d%d%d%d%d%d%d%d%d%d%d%d",
X &translate[0], &translate[1], &translate[2],
X &translate[3], &translate[4], &translate[5],
X &translate[6], &translate[7], &translate[8],
X &translate[9], &translate[10], &translate[11]);
X lth += sscanf(bufp,
X "%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%d%d%d%d%d%d%d%d%d%d%d%d",
X &translate[12], &translate[13], &translate[14],
X &translate[15], &translate[16], &translate[17],
X &translate[18], &translate[19], &translate[20],
X &translate[21], &translate[22], &translate[23]);
X lth += sscanf(bufp,
X "%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%d%d%d%d%d%d%d%d%d%d%d",
X &translate[24], &translate[25], &translate[26],
X &translate[27], &translate[28], &translate[29],
X &translate[30], &translate[31], &translate[32],
X &translate[33], &translate[34]);
X#else
X lth = sscanf(bufp,
X "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
X &translate[0], &translate[1], &translate[2],
X &translate[3], &translate[4], &translate[5],
X &translate[6], &translate[7], &translate[8],
X &translate[9], &translate[10], &translate[11],
X &translate[12], &translate[13], &translate[14],
X &translate[15], &translate[16], &translate[17],
X &translate[18], &translate[19], &translate[20],
X &translate[21], &translate[22], &translate[23],
X &translate[24], &translate[25], &translate[26],
X &translate[27], &translate[28], &translate[29],
X &translate[30], &translate[31], &translate[32],
X &translate[33], &translate[34]);
X#endif /* OVERLAY */
X if (lth <= 0) {
X msmsg ("Syntax error in GRAPHICS\n");
X getreturn("to continue");
X }
X assign_graphics(translate, lth);
X } else {
X msmsg("Bad option line: \"%s\"\n", buf);
X getreturn("to continue");
X }
X }
X (void) fclose(fp);
X
X# ifdef DGK
X Strcpy(permbones, tmp_levels);
X if (tmp_ramdisk[0]) {
X Strcpy(levels, tmp_ramdisk);
X if (strcmp(permbones, levels)) /* if not identical */
X ramdisk = TRUE;
X } else
X# endif /* DGK */
X Strcpy(levels, tmp_levels);
X Strcpy(bones, levels);
X return;
X}
X
X# ifdef DGK
X/* Set names for bones[] and lock[]
X */
Xvoid
Xset_lock_and_bones() {
X if (!ramdisk) {
X Strcpy(levels, permbones);
X Strcpy(bones, permbones);
X }
X append_slash(permbones);
X append_slash(levels);
X append_slash(bones);
X Strcat(bones, allbones);
X Strcpy(lock, levels);
X Strcat(lock, alllevels);
X return;
X}
X# endif /* DGK */
X
X/* Add a backslash to any name not ending in /, \ or : There must
X * be room for the \
X */
Xvoid
Xappend_slash(name)
Xchar *name;
X{
X char *ptr;
X
X if (!*name)
X return;
X ptr = name + (strlen(name) - 1);
X if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
X *++ptr = '\\';
X *++ptr = '\0';
X }
X return;
X}
X
Xvoid
Xgetreturn(str)
Xconst char *str;
X{
X# ifdef TOS
X msmsg("Hit <Return> %s.", str);
X# else
X msmsg("Hit <Enter> %s.", str);
X# endif
X while (Getchar() != '\n') ;
X return;
X}
X
Xvoid
Xmsmsg VA_DECL(const char *, fmt)
X VA_START(fmt);
X VA_INIT(fmt, const char *);
X Vprintf(fmt, VA_ARGS);
X flushout();
X VA_END();
X return;
X}
X
X/* Chdrive() changes the default drive.
X */
X# ifndef __TURBOC__
X# ifndef OS2
X#define SELECTDISK 0x0E
X# endif
Xvoid
Xchdrive(str)
Xchar *str;
X{
X char *ptr;
X# ifndef TOS
X# ifndef OS2
X union REGS inregs;
X# endif
X# endif
X char drive;
X
X if ((ptr = index(str, ':')) != NULL) {
X drive = toupper(*(ptr - 1));
X# ifdef TOS
X (void)Dsetdrv(drive - 'A');
X# else
X# ifdef OS2
X DosSelectDisk((USHORT)(drive - 'A' + 1));
X# else
X inregs.h.ah = SELECTDISK;
X inregs.h.dl = drive - 'A';
X intdos(&inregs, &inregs);
X# endif
X# endif
X }
X return;
X}
X# else
Xextern int setdisk(int);
X
Xvoid
Xchdrive(str)
Xchar *str;
X{
X if (str[1] == ':')
X (void)setdisk((int)(toupper(str[0]) - 'A'));
X return;
X}
X# endif
X
X# ifndef TOS
X/* Use the IOCTL DOS function call to change stdin and stdout to raw
X * mode. For stdin, this prevents MSDOS from trapping ^P, thus
X * freeing us of ^P toggling 'echo to printer'.
X * Thanks to Mark Zbikowski (markz@microsoft.UUCP).
X */
X
X# ifndef OS2
X#define DEVICE 0x80
X#define RAW 0x20
X#define IOCTL 0x44
X#define STDIN fileno(stdin)
X#define STDOUT fileno(stdout)
X#define GETBITS 0
X#define SETBITS 1
X# endif
X
Xstatic unsigned int old_stdin, old_stdout;
X
Xvoid
Xdisable_ctrlP() {
X# ifdef OS2
X KBDINFO KbdInfo;
X HKBD KbdHandle = 0;
X# endif
X
X# ifdef DGK
X if (!flags.rawio) return;
X# endif
X# ifdef OS2
X KbdInfo.cb = sizeof(KbdInfo);
X KbdGetStatus(&KbdInfo,KbdHandle);
X KbdInfo.fsMask &= 0xFFF7; /* ASCII off */
X KbdInfo.fsMask |= 0x0004; /* BINARY on */
X KbdSetStatus(&KbdInfo,KbdHandle);
X# else
X old_stdin = ioctl(STDIN, GETBITS, 0);
X old_stdout = ioctl(STDOUT, GETBITS, 0);
X if (old_stdin & DEVICE)
X ioctl(STDIN, SETBITS, old_stdin | RAW);
X if (old_stdout & DEVICE)
X ioctl(STDOUT, SETBITS, old_stdout | RAW);
X# endif /* OS2 */
X return;
X}
X
Xvoid
Xenable_ctrlP() {
X# ifdef OS2
X KBDINFO KbdInfo;
X HKBD KbdHandle = 0;
X# endif
X
X# ifdef DGK
X if (!flags.rawio) return;
X# endif
X# ifdef OS2
X KbdInfo.cb = sizeof(KbdInfo);
X KbdGetStatus(&KbdInfo,KbdHandle);
X KbdInfo.fsMask &= 0xFFFB; /* BINARY off */
X KbdInfo.fsMask |= 0x0008; /* ASCII on */
X KbdSetStatus(&KbdInfo,KbdHandle);
X# else
X if (old_stdin)
X (void) ioctl(STDIN, SETBITS, old_stdin);
X if (old_stdout)
X (void) ioctl(STDOUT, SETBITS, old_stdout);
X# endif
X return;
X}
X
X# ifndef OS2
Xstatic unsigned int
Xioctl(handle, mode, setvalue)
Xint handle, mode;
Xunsigned setvalue;
X{
X union REGS regs;
X
X regs.h.ah = IOCTL;
X regs.h.al = mode;
X regs.x.bx = handle;
X regs.h.dl = setvalue;
X regs.h.dh = 0; /* Zero out dh */
X intdos(®s, ®s);
X return (regs.x.dx);
X}
X# endif /* OS2 */
X# endif /* TOS */
X
X# ifdef DGK
X/* Follow the PATH, trying to fopen the file.
X */
X# ifdef TOS
X#define PATHSEP ','
X# else
X#define PATHSEP ';'
X# endif
X
XFILE *
Xfopenp(name, mode)
Xconst char *name, *mode;
X{
X char buf[BUFSIZ], *bp, *pp, lastch = 0;
X FILE *fp;
X
X /* Try the default directory first. Then look along PATH.
X */
X Strcpy(buf, name);
X if (fp = fopen(buf, mode))
X return fp;
X else {
X pp = getenv("PATH");
X while (pp && *pp) {
X bp = buf;
X while (*pp && *pp != PATHSEP)
X lastch = *bp++ = *pp++;
X if (lastch != '\\' && lastch != '/')
X *bp++ = '\\';
X Strcpy(bp, name);
X if (fp = fopen(buf, mode))
X return fp;
X if (*pp)
X pp++;
X }
X }
X# ifdef OS2_CODEVIEW /* one more try for hackdir */
X Strcpy(buf,hackdir);
X append_slash(buf);
X Strcat(buf,name);
X if(fp = fopen(buf,mode))
X return fp;
X# endif
X return (FILE *)0;
X}
X# endif /* DGK */
X
X/* Chdir back to original directory
X */
X#undef exit
X# ifdef TOS
Xextern boolean run_from_desktop; /* set in pcmain.c */
X# endif
X
Xvoid exit(int);
Xvoid
Xmsexit(code)
Xint code;
X{
X# ifdef CHDIR
X extern char orgdir[];
X# endif
X
X flushout();
X# ifndef TOS
X enable_ctrlP(); /* in case this wasn't done */
X# endif
X# ifdef DGK
X if (ramdisk) copybones(TOPERM);
X# endif
X# ifdef CHDIR
X chdir(orgdir); /* chdir, not chdirx */
X chdrive(orgdir);
X# endif
X# ifdef TOS
X if (run_from_desktop)
X getreturn("to continue"); /* so the user can read the score list */
X# ifdef TEXTCOLOR
X if (flags.IBMBIOS && flags.use_color)
X restore_colors();
X# endif
X# endif
X exit(code);
X return;
X}
X
X# ifdef DGK /* for flags.IBMBIOS */
Xvoid
Xget_scr_size()
X{
X# ifdef OS2
X VIOMODEINFO ModeInfo;
X HVIO VideoHandle = 0;
X
X ModeInfo.cb = sizeof(ModeInfo);
X
X (void) VioGetMode(&ModeInfo,VideoHandle);
X
X CO = ModeInfo.col;
X LI = ModeInfo.row;
X# else
X# ifndef TOS
X union REGS regs;
X
X if (!flags.IBMBIOS) { /* assume standard screen size */
X CO = 80;
X LI = 24;
X return;
X }
X
X regs.x.ax = FONTINFO;
X regs.x.bx = 0; /* current ROM BIOS font */
X regs.h.dl = 24; /* default row count */
X /* in case no EGA/MCGA/VGA */
X int86(VIDEO_BIOS, ®s, ®s); /* Get Font Information */
X
X /* MDA/CGA/PCjr ignore INT 10h, Function 11h, but since we
X * cleverly loaded up DL with the default, everything's fine.
X *
X * Otherwise, DL now contains rows - 1. Also, CX contains the
X * points (bytes per character) and ES:BP points to the font
X * table. -3.
X */
X
X regs.h.ah = GETMODE;
X int86(VIDEO_BIOS, ®s, ®s); /* Get Video Mode */
X
X /* This goes back all the way to the original PC. Completely
X * safe. AH contains # of columns, AL contains display mode,
X * and BH contains the active display page.
X */
X
X LI = regs.h.dl + 1;
X CO = regs.h.ah;
X# else /* TOS */
X init_aline();
X LI = (*((WORD *)(_a_line + -42L))) + 1;
X CO = (*((WORD *)(_a_line + -44L))) + 1;
X# endif /* TOS */
X# endif /* OS2 */
X}
X
X# ifndef TOS
Xvoid
Xgotoxy(x,y)
Xint x,y;
X{
X# ifdef OS2
X HVIO VideoHandle = 0;
X
X x--; y--; /* (0,0) is upper right corner */
X
X (void) VioSetCurPos(x, y, VideoHandle);
X# else
X union REGS regs;
X
X x--; y--; /* (0,0) is upper right corner */
X
X regs.h.ah = SETCURPOS;
X regs.h.bh = 0; /* display page */
X regs.h.dh = y; /* row */
X regs.h.dl = x; /* column */
X int86(VIDEO_BIOS, ®s, ®s); /* Set Cursor Position */
X
X /* This, too, goes back all the way to the original PC. If
X * we ever get so fancy as to swap display pages (i doubt it),
X * then we'll need to set BH appropriately. This function
X * returns nothing. -3.
X */
X# endif /* OS2 */
X}
X# endif /* TOS */
X# endif /* DGK */
X
X#endif /* MSDOS */
X
X
X#ifdef TOS
X# define BIGBUF 8192
X
Xint
X_copyfile(from, to)
Xchar *from, *to;
X{
X int fromfd, tofd, r;
X char *buf;
X
X if ((fromfd = open(from, O_RDONLY|O_BINARY, 0)) < 0)
X return -1;
X if ((tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, FCMASK)) < 0)
X return -1;
X if (!(buf = (char *)malloc((size_t)BIGBUF)))
X return -1;
X while ( (r = read(fromfd, buf, BIGBUF)) > 0)
X write(tofd, buf, r);
X close(fromfd);
X close(tofd);
X free(buf);
X return 0; /* successful */
X}
X
Xint kbhit()
X{
X return Cconis();
X}
X
Xstatic void
Xinit_aline()
X{
X# ifdef __GNUC__
X asm(" .word 0xa000; movel d0, __a_line");
X# else
X asm(" .dc.w 0xa000"); /* tweak as necessary for your compiler */
X asm(" move.l d0, __a_line");
X# endif
X}
X
X# ifdef TEXTCOLOR
Xstatic unsigned orig_color[4] = {-1, -1, -1, -1};
Xstatic unsigned new_color[4] = { 0x0, 0x730, 0x047, 0x555 };
Xstatic int numcolors = 2;
X
Xvoid set_colors()
X{
X int i;
X char *s;
X static char newhe[] = "\033q\033b\017\033c0";
X
X if (!flags.IBMBIOS)
X return;
X init_aline();
X numcolors = 1 << (((unsigned char *) _a_line)[1]);
X if (numcolors == 2) { /* mono */
X flags.use_color = FALSE;
X return;
X }
X else if (numcolors == 4) {
X for (i = 0; i < 4; i++)
X orig_color[i] = Setcolor(i, new_color[i]);
X }
X else {
X orig_color[0] = Setcolor(0, new_color[0]);
X orig_color[1] = Setcolor(15, 0x777);
X hilites[0] = "";
X for (i = 1; i < 16; i++) {
X s = (char *) alloc(sizeof("\033b0"));
X sprintf(s, "\033b%c", '0'+i);
X hilites[i] = s;
X }
X HE = newhe;
X }
X}
X
Xvoid restore_colors()
X{
X int i;
X
X if (numcolors == 2)
X return;
X else if (numcolors == 4)
X for (i = 0; i < 4; i++)
X (void) Setcolor(i, orig_color[i]);
X else {
X (void) Setcolor(0, orig_color[0]);
X (void) Setcolor(15, orig_color[1]);
X }
X}
X# endif /* TEXTCOLOR */
X#endif /* TOS */
END_OF_FILE
if test 30281 -ne `wc -c <'others/msdos.c'`; then
echo shar: \"'others/msdos.c'\" unpacked with wrong size!
fi
# end of 'others/msdos.c'
fi
if test -f 'src/restore.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/restore.c'\"
else
echo shar: Extracting \"'src/restore.c'\" \(25217 characters\)
sed "s/^X//" >'src/restore.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)restore.c 3.0 88/10/25
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#include "lev.h"
X
X#ifdef WORM
X#include "wseg.h"
X#endif
X
Xstatic void FDECL(stuff_objs, (struct obj *));
Xstatic void NDECL(find_lev_obj);
X#ifndef NO_SIGNAL
Xstatic void NDECL(inven_inuse);
X#endif
Xstatic struct obj * FDECL(restobjchn, (int,BOOLEAN_P));
Xstatic struct monst * FDECL(restmonchn, (int,BOOLEAN_P));
Xstatic void FDECL(restgenoinfo, (int));
X
Xboolean restoring = FALSE;
X#ifdef TUTTI_FRUTTI
Xstatic struct fruit NEARDATA *oldfruit;
X#endif
Xstatic long NEARDATA omoves;
X
X/*
X * "stuff" objects back into containers (relink the fcobj list).
X */
Xstatic void
Xstuff_objs(cobj)
Xregister struct obj *cobj;
X{
X register struct obj *otmp, *otmp2;
X
X for(; cobj; cobj = cobj->nobj)
X if(Is_container(cobj))
X
X for(otmp = cobj->nobj;
X otmp && otmp->cobj == (struct obj *) -1; otmp = otmp2) {
X
X otmp2 = otmp->nobj;
X
X otmp->cobj = cobj;
X cobj->nobj = otmp2;
X otmp->nobj = fcobj;
X fcobj = otmp;
X }
X}
X
X/* Recalculate level.objects[x][y], since this info was not saved. */
Xstatic void
Xfind_lev_obj()
X{
X register struct obj *fobjtmp = (struct obj *)0;
X register struct obj *otmp;
X int x,y;
X
X for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
X level.objects[x][y] = (struct obj *)0;
X
X /* Reverse the entire fobj chain, which is necessary so that we can
X * place the objects in the proper order.
X */
X while(otmp = fobj) {
X fobj = otmp->nobj;
X otmp->nobj = fobjtmp;
X fobjtmp = otmp;
X }
X /* Set level.objects (as well as reversing the chain back again) */
X while(otmp = fobjtmp) {
X place_object(otmp, otmp->ox, otmp->oy);
X fobjtmp = otmp->nobj;
X otmp->nobj = fobj;
X fobj = otmp;
X }
X}
X
X#ifndef NO_SIGNAL
Xstatic void
Xinven_inuse()
X/* Things that were marked "in_use" when the game was saved (ex. via the
X * infamous "HUP" cheat) get used up here.
X */
X{
X register struct obj *otmp, *otmp2;
X
X for(otmp = invent; otmp; otmp = otmp2) {
X otmp2 = otmp->nobj;
X if(otmp->olet != ARMOR_SYM && otmp->olet != WEAPON_SYM
X && otmp->otyp != PICK_AXE && otmp->otyp != UNICORN_HORN
X && otmp->in_use) {
X pline("Finishing off %s...", xname(otmp));
X useup(otmp);
X }
X }
X}
X#endif
X
Xstatic struct obj *
Xrestobjchn(fd, ghostly)
Xregister int fd;
Xboolean ghostly;
X{
X register struct obj *otmp, *otmp2;
X register struct obj *first = 0;
X#ifdef TUTTI_FRUTTI
X register struct fruit *oldf;
X#endif
X int xl;
X#if defined(LINT) || defined(__GNULINT__)
X /* suppress "used before set" warning from lint */
X otmp2 = 0;
X#endif
X while(1) {
X mread(fd, (genericptr_t) &xl, sizeof(xl));
X if(xl == -1) break;
X otmp = newobj(xl);
X if(!first) first = otmp;
X else otmp2->nobj = otmp;
X mread(fd, (genericptr_t) otmp, (unsigned) xl + sizeof(struct obj));
X if(!otmp->o_id) otmp->o_id = flags.ident++;
X#ifdef TUTTI_FRUTTI
X if(ghostly && otmp->otyp == SLIME_MOLD) {
X for(oldf=oldfruit; oldf; oldf=oldf->nextf)
X if (oldf->fid == otmp->spe) break;
X if(!oldf) impossible("no old fruit?");
X else otmp->spe = fruitadd(oldf->fname);
X }
X#endif
X /* Ghost levels get object age shifted from old player's clock to
X * new player's clock. Assumption: new player arrived immediately
X * after old player died.
X */
X if (ghostly) otmp->age = monstermoves-omoves+otmp->age;
X otmp2 = otmp;
X }
X if(first && otmp2->nobj){
X impossible("Restobjchn: error reading objchn.");
X otmp2->nobj = 0;
X }
X
X stuff_objs(first);
X return(first);
X}
X
Xstatic struct monst *
Xrestmonchn(fd, ghostly)
Xregister int fd;
Xboolean ghostly;
X{
X register struct monst *mtmp, *mtmp2;
X register struct monst *first = 0;
X int xl;
X
X struct permonst *monbegin;
X off_t differ;
X
X mread(fd, (genericptr_t)&monbegin, sizeof(monbegin));
X#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX) && !defined(VAXC)
X differ = (genericptr_t)(&mons[0]) - (genericptr_t)(monbegin);
X#else
X differ = (long)(&mons[0]) - (long)(monbegin);
X#endif
X
X#if defined(LINT) || defined(__GNULINT__)
X /* suppress "used before set" warning from lint */
X mtmp2 = 0;
X#endif
X while(1) {
X mread(fd, (genericptr_t) &xl, sizeof(xl));
X if(xl == -1) break;
X mtmp = newmonst(xl);
X if(!first) first = mtmp;
X else mtmp2->nmon = mtmp;
X mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst));
X if(!mtmp->m_id)
X mtmp->m_id = flags.ident++;
X#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX) && !defined(VAXC)
X /* ANSI type for differ is ptrdiff_t --
X * long may be wrong for segmented architecture --
X * may be better to cast pointers to (struct permonst *)
X * rather than (genericptr_t)
X * this code handles save file -- so any bug should glow
X * probably best not to keep lint from complaining
X */
X/*#ifdef LINT /* possible compiler/hardware dependency - */
X/* if (differ) mtmp->data = NULL;*/
X/*#else*/
X mtmp->data = (struct permonst *)
X ((genericptr_t)mtmp->data + differ);
X/*#endif /*LINT*/
X#else
X mtmp->data = (struct permonst *)
X ((long) mtmp->data + differ);
X#endif
X if(mtmp->minvent)
X mtmp->minvent = restobjchn(fd, ghostly);
X mtmp2 = mtmp;
X }
X if(first && mtmp2->nmon){
X impossible("Restmonchn: error reading monchn.");
X mtmp2->nmon = 0;
X }
X return(first);
X}
X
Xstatic void
Xrestgenoinfo(fd)
Xregister int fd;
X{
X register int i;
X
X for (i = 0; i < NUMMONS; i++)
X mread(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned));
X}
X
Xint
Xdorecover(fd)
Xregister int fd;
X{
X register int nfd;
X int tmp; /* not a register ! */
X xchar ltmp;
X unsigned int mid; /* idem */
X struct obj *otmp;
X#ifdef TUTTI_FRUTTI
X struct fruit *fruit;
X#endif
X struct flag oldflags;
X
X oldflags = flags;
X
X#ifdef ZEROCOMP
X minit();
X#endif
X restoring = TRUE;
X getlev(fd, 0, (xchar)0, FALSE);
X invent = restobjchn(fd, FALSE);
X for(otmp = invent; otmp; otmp = otmp->nobj)
X if(otmp->owornmask)
X setworn(otmp, otmp->owornmask);
X fallen_down = restmonchn(fd, FALSE);
X restgenoinfo(fd);
X mread(fd, (genericptr_t) &tmp, sizeof tmp);
X#ifdef WIZARD
X if(!wizard)
X#endif
X if(tmp != getuid()) { /* strange ... */
X (void) close(fd);
X (void) unlink(SAVEF);
X#ifdef AMIGA_WBENCH
X ami_wbench_unlink(SAVEF);
X#endif
X (void) puts("Saved game was not yours.");
X restoring = FALSE;
X return(0);
X }
X mread(fd, (genericptr_t) &flags, sizeof(struct flag));
X /* Some config file and command line OPTIONS take precedence over
X * those in save file.
X */
X flags.DECgraphics = oldflags.DECgraphics;
X flags.IBMgraphics = oldflags.IBMgraphics;
X#if defined(MSDOS) && defined(DGK)
X flags.rawio = oldflags.rawio;
X flags.IBMBIOS = oldflags.IBMBIOS;
X#endif
X#ifdef TEXTCOLOR
X flags.use_color = oldflags.use_color;
X#endif
X /* these come from the current environment; ignore saved values */
X flags.echo = oldflags.echo;
X flags.cbreak = oldflags.cbreak;
X
X mread(fd, (genericptr_t) &dlevel, sizeof dlevel);
X mread(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel);
X mread(fd, (genericptr_t) &moves, sizeof moves);
X mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
X mread(fd, (genericptr_t) &wiz_level, sizeof wiz_level);
X mread(fd, (genericptr_t) &medusa_level, sizeof medusa_level);
X mread(fd, (genericptr_t) &bigroom_level, sizeof bigroom_level);
X#ifdef ORACLE
X mread(fd, (genericptr_t) &oracle_level, sizeof oracle_level);
X#endif
X#ifdef REINCARNATION
X mread(fd, (genericptr_t) &rogue_level, sizeof rogue_level);
X if (dlevel==rogue_level)
X (void) memcpy((genericptr_t)savesyms,
X (genericptr_t)showsyms, sizeof savesyms);
X#endif
X#ifdef STRONGHOLD
X mread(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level);
X mread(fd, (genericptr_t) &tower_level, sizeof tower_level);
X mread(fd, (genericptr_t) tune, sizeof tune);
X# ifdef MUSIC
X mread(fd, (genericptr_t) &music_heard, sizeof music_heard);
X# endif
X#endif
X mread(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev);
X mread(fd, (genericptr_t) &u, sizeof(struct you));
X if(u.uhp <= 0) {
X (void) close(fd);
X (void) unlink(SAVEF);
X#ifdef AMIGA_WBENCH
X ami_wbench_unlink(SAVEF);
X#endif
X (void) puts("You were not healthy enough to survive restoration.");
X restoring = FALSE;
X return(0);
X }
X#ifdef SPELLS
X mread(fd, (genericptr_t) spl_book,
X sizeof(struct spell) * (MAXSPELL + 1));
X#endif
X#ifdef NAMED_ITEMS
X mread(fd, (genericptr_t) artiexist,
X (unsigned int)(sizeof(boolean) * artifact_num));
X#endif
X if(u.ustuck)
X mread(fd, (genericptr_t) &mid, sizeof mid);
X mread(fd, (genericptr_t) pl_character, sizeof pl_character);
X#ifdef TUTTI_FRUTTI
X mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
X mread(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit);
X ffruit = 0;
X while (fruit = newfruit(),
X mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
X fruit->fid) {
X fruit->nextf = ffruit;
X ffruit = fruit;
X }
X free((genericptr_t) fruit);
X#endif
X
X restnames(fd);
X#if defined(DGK) || defined(MACOS)
X# ifdef MACOS
X#define msmsg printf
X# endif
X msmsg("\n");
X cl_end();
X msmsg("You got as far as level %d%s.\n", maxdlevel,
X flags.debug ? " in WIZARD mode" :
X flags.explore ? " in discovery mode" : "");
X cl_end();
X msmsg("Restoring: ");
X#endif
X while(1) {
X#ifdef ZEROCOMP
X if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0)
X#else
X if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp)
X#endif
X break;
X getlev(fd, 0, ltmp, FALSE);
X glo(ltmp);
X#if defined(DGK) || defined(MACOS)
X msmsg(".");
X#endif
X#if defined(MSDOS) && !defined(TOS)
X nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
X#else
X# ifdef MACOS
X {
X Str255 fileName;
X OSErr er;
X struct term_info *t;
X short oldVolume;
X extern WindowPtr HackWindow;
X
X t = (term_info *)GetWRefCon(HackWindow);
X (void)GetVol(&fileName, &oldVolume);
X (void)SetVol(0L, t->system.sysVRefNum);
X fileName[0] = (uchar)strlen(lock);
X Strcpy((char *)&fileName[1], lock);
X
X if (er = Create(&fileName, 0, CREATOR, LEVEL_TYPE))
X SysBeep(1);
X msmsg(".");
X nfd = open(lock, O_WRONLY | O_BINARY);
X (void)SetVol(0L, oldVolume);
X }
X# else
X nfd = creat(lock, FCMASK);
X# endif /* MACOS */
X#endif
X if (nfd < 0) panic("Cannot open temp file %s!\n", lock);
X#if defined(DGK)
X if (!savelev(nfd, ltmp, COUNT | WRITE)) {
X
X /* The savelev can't proceed because the size required
X * is greater than the available disk space.
X */
X msmsg("\nNot enough space on `%s' to restore your game.\n",
X levels);
X
X /* Remove levels and bones that may have been created.
X */
X (void) close(nfd);
X eraseall(levels, alllevels);
X eraseall(levels, allbones);
X
X /* Perhaps the person would like to play without a
X * RAMdisk.
X */
X if (ramdisk) {
X /* PlaywoRAMdisk may not return, but if it does
X * it is certain that ramdisk will be 0.
X */
X playwoRAMdisk();
X /* Rewind save file and try again */
X (void) lseek(fd, (off_t)0, 0);
X return dorecover(fd);
X } else {
X msmsg("Be seeing you...\n");
X exit(0);
X }
X }
X#else
X savelev(nfd, ltmp);
X#endif
X#ifdef ZEROCOMP
X bflush(nfd);
X#endif
X (void) close(nfd);
X }
X#ifdef BSD
X (void) lseek(fd, 0L, 0);
X#else
X (void) lseek(fd, (off_t)0, 0);
X#endif
X#ifdef ZEROCOMP
X minit();
X#endif
X getlev(fd, 0, (xchar)0, FALSE);
X (void) close(fd);
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X if(
X# ifdef WIZARD
X !wizard
X# ifdef EXPLORE_MODE
X &&
X# endif
X# endif
X# ifdef EXPLORE_MODE
X !discover
X# endif
X )
X#endif
X (void) unlink(SAVEF);
X#ifdef AMIGA_WBENCH
X ami_wbench_unlink(SAVEF);
X#endif
X#ifdef REINCARNATION
X /* this can't be done earlier because we need to check the initial
X * showsyms against the one saved in each of the non-rogue levels */
X if (dlevel==rogue_level) {
X (void) memcpy((genericptr_t)showsyms,
X (genericptr_t)defsyms, sizeof showsyms);
X showsyms[S_ndoor] = showsyms[S_vodoor] =
X showsyms[S_hodoor] = '+';
X }
X#endif
X if(u.ustuck) {
X register struct monst *mtmp;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(mtmp->m_id == mid) goto monfnd;
X panic("Cannot find the monster ustuck.");
X monfnd:
X u.ustuck = mtmp;
X }
X setsee(); /* only to recompute seelx etc. - these weren't saved */
X#ifdef DGK
X gameDiskPrompt();
X#endif
X max_rank_sz(); /* to recompute mrank_sz (pri.c) */
X#ifdef POLYSELF
X set_uasmon();
X#endif
X /* take care of iron ball & chain */
X for(otmp = fobj; otmp; otmp = otmp->nobj)
X if(otmp->owornmask)
X setworn(otmp, otmp->owornmask);
X#ifndef NO_SIGNAL
X /* in_use processing must be after:
X * inven has been read so fcobj has been built and freeinv() works
X * current level has been restored so billing information is available
X */
X inven_inuse();
X#endif
X docrt();
X restoring = FALSE;
X return(1);
X}
X
Xvoid
Xgetlev(fd, pid, lev, ghostly)
Xint fd, pid;
Xxchar lev;
Xboolean ghostly;
X{
X register struct gold *gold;
X register struct trap *trap;
X register struct monst *mtmp;
X#ifdef WORM
X register struct wseg *wtmp;
X register int tmp;
X#endif
X long nhp;
X int hpid;
X xchar dlvl;
X symbol_array osymbol;
X int x, y;
X uchar osym, nsym;
X#ifdef TOS
X short tlev;
X#endif
X
X#if defined(MSDOS) && !defined(TOS) && !defined(LATTICE) && !defined(AZTEC_C)
X setmode(fd, O_BINARY); /* is this required for TOS??? NO --ERS */
X#endif
X#ifdef TUTTI_FRUTTI
X /* Load the old fruit info. We have to do it first, so the infor-
X * mation is available when restoring the objects.
X */
X if (ghostly) {
X struct fruit *fruit;
X
X oldfruit = 0;
X while (fruit = newfruit(),
X mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
X fruit->fid) {
X fruit->nextf = oldfruit;
X oldfruit = fruit;
X }
X free((genericptr_t) fruit);
X }
X#endif
X
X /* First some sanity checks */
X mread(fd, (genericptr_t) &hpid, sizeof(hpid));
X#ifdef TOS
X mread(fd, (genericptr_t) &tlev, sizeof(tlev));
X dlvl=tlev&0x00ff;
X#else
X mread(fd, (genericptr_t) &dlvl, sizeof(dlvl));
X#endif
X if((pid && pid != hpid) || (lev && dlvl != lev)) {
X#ifdef WIZARD
X if (wizard) {
X if (pid && pid != hpid)
X pline("PID (%d) doesn't match saved PID (%d)!", hpid, pid);
X else if (lev && dlvl != lev)
X pline("This is level %d, not %d!", dlvl, lev);
X }
X#endif
X pline("Strange, this map is not as I remember it.");
X pline("Somebody is trying some trickery here...");
X pline("This game is void.");
X done(TRICKED);
X }
X
X#if defined(SMALLDATA) && defined(MACOS)
X {
X /* this assumes that the size of a row of struct rm's is <128 */
X short i, length, j;
X char *ptr, *src, *p, *d;
X
X d = calloc(ROWNO*COLNO, sizeof(struct rm));
X p = d;
X mread(fd, (genericptr_t)&j, sizeof(short));
X mread(fd, (genericptr_t)d, j);
X for (i = 0; i < COLNO; i++) {
X length = (short)(*p++);
X ptr = p;
X src = (char *)&levl[i][0];
X UnpackBits(&ptr, &src, ROWNO * sizeof(struct rm));
X if ((ptr - p) != length)
X panic("restore - corrupted file on unpacking\n");
X p = ptr;
X }
X free(d);
X }
X#else
X mread(fd, (genericptr_t) levl, sizeof(levl));
X#endif
X mread(fd, (genericptr_t) osymbol, sizeof(osymbol));
X#ifdef REINCARNATION
X if (memcmp((genericptr_t) osymbol, ((dlevel==rogue_level)
X ? (genericptr_t)savesyms : (genericptr_t)showsyms),
X sizeof (osymbol))
X && dlvl != rogue_level) {
X /* rogue level always uses default syms. Although showsyms
X * will be properly initialized from environment when restoring
X * a game, this routine is called upon saving as well as
X * restoring; when saving on the Rogue level, showsyms will
X * be wrong, so use savesyms (which is always right, both on
X * saving and restoring).
X */
X#else
X if (memcmp((genericptr_t) osymbol,
X (genericptr_t) showsyms, sizeof (showsyms))) {
X#endif
X for (x = 0; x < COLNO; x++)
X for (y = 0; y < ROWNO; y++) {
X osym = levl[x][y].scrsym;
X nsym = 0;
X switch (levl[x][y].typ) {
X case STONE:
X case SCORR:
X if (osym == osymbol[S_stone])
X nsym = showsyms[S_stone];
X break;
X case ROOM:
X#ifdef STRONGHOLD
X case DRAWBRIDGE_DOWN:
X#endif /* STRONGHOLD /**/
X if (osym == osymbol[S_room])
X nsym = showsyms[S_room];
X break;
X case DOOR:
X if (osym == osymbol[S_ndoor])
X nsym = showsyms[S_ndoor];
X else if (osym == osymbol[S_vodoor])
X nsym = showsyms[S_vodoor];
X else if (osym == osymbol[S_hodoor])
X nsym = showsyms[S_hodoor];
X else if (osym == osymbol[S_cdoor])
X nsym = showsyms[S_cdoor];
X break;
X case CORR:
X if (osym == osymbol[S_corr])
X nsym = showsyms[S_corr];
X break;
X case VWALL:
X if (osym == osymbol[S_vwall])
X nsym = showsyms[S_vwall];
X#ifdef STRONGHOLD
X else if (osym == osymbol[S_dbvwall])
X nsym = showsyms[S_dbvwall];
X#endif
X break;
X case HWALL:
X if (osym == osymbol[S_hwall])
X nsym = showsyms[S_hwall];
X#ifdef STRONGHOLD
X else if (osym == osymbol[S_dbhwall])
X nsym = showsyms[S_dbhwall];
X#endif
X break;
X case TLCORNER:
X if (osym == osymbol[S_tlcorn])
X nsym = showsyms[S_tlcorn];
X break;
X case TRCORNER:
X if (osym == osymbol[S_trcorn])
X nsym = showsyms[S_trcorn];
X break;
X case BLCORNER:
X if (osym == osymbol[S_blcorn])
X nsym = showsyms[S_blcorn];
X break;
X case BRCORNER:
X if (osym == osymbol[S_brcorn])
X nsym = showsyms[S_brcorn];
X break;
X case SDOOR:
X if (osym == osymbol[S_vwall])
X nsym = showsyms[S_vwall];
X else if (osym == osymbol[S_hwall])
X nsym = showsyms[S_hwall];
X break;
X case CROSSWALL:
X if (osym == osymbol[S_crwall])
X nsym = showsyms[S_crwall];
X break;
X case TUWALL:
X if (osym == osymbol[S_tuwall])
X nsym = showsyms[S_tuwall];
X break;
X case TDWALL:
X if (osym == osymbol[S_tdwall])
X nsym = showsyms[S_tdwall];
X break;
X case TLWALL:
X if (osym == osymbol[S_tlwall])
X nsym = showsyms[S_tlwall];
X break;
X case TRWALL:
X if (osym == osymbol[S_trwall])
X nsym = showsyms[S_trwall];
X break;
X case STAIRS:
X if (osym == osymbol[S_upstair])
X nsym = showsyms[S_upstair];
X else if (osym == osymbol[S_dnstair])
X nsym = showsyms[S_dnstair];
X break;
X#ifdef STRONGHOLD
X case LADDER:
X if (osym == osymbol[S_upladder])
X nsym = showsyms[S_upladder];
X else if (osym == osymbol[S_dnladder])
X nsym = showsyms[S_dnladder];
X break;
X#endif /* STRONGHOLD /**/
X case POOL:
X case MOAT:
X#ifdef STRONGHOLD
X case DRAWBRIDGE_UP:
X#endif /* STRONGHOLD /**/
X if (osym == osymbol[S_pool])
X nsym = showsyms[S_pool];
X break;
X#ifdef FOUNTAINS
X case FOUNTAIN:
X if (osym == osymbol[S_fountain])
X nsym = showsyms[S_fountain];
X break;
X#endif /* FOUNTAINS /**/
X#ifdef THRONES
X case THRONE:
X if (osym == osymbol[S_throne])
X nsym = showsyms[S_throne];
X break;
X#endif /* THRONES /**/
X#ifdef SINKS
X case SINK:
X if (osym == osymbol[S_sink])
X nsym = showsyms[S_sink];
X break;
X#endif /* SINKS /**/
X#ifdef ALTARS
X case ALTAR:
X if (osym == osymbol[S_altar])
X nsym = showsyms[S_altar];
X break;
X#endif /* ALTARS /**/
X default:
X break;
X }
X if (nsym)
X levl[x][y].scrsym = nsym;
X }
X }
X
X mread(fd, (genericptr_t)&omoves, sizeof(omoves));
X mread(fd, (genericptr_t)&xupstair, sizeof(xupstair));
X mread(fd, (genericptr_t)&yupstair, sizeof(yupstair));
X mread(fd, (genericptr_t)&xdnstair, sizeof(xdnstair));
X mread(fd, (genericptr_t)&ydnstair, sizeof(ydnstair));
X#ifdef STRONGHOLD
X mread(fd, (genericptr_t)&xupladder, sizeof(xupladder));
X mread(fd, (genericptr_t)&yupladder, sizeof(yupladder));
X mread(fd, (genericptr_t)&xdnladder, sizeof(xdnladder));
X mread(fd, (genericptr_t)&ydnladder, sizeof(ydnladder));
X#endif
X mread(fd, (genericptr_t)&fountsound, sizeof(fountsound));
X mread(fd, (genericptr_t)&sinksound, sizeof(sinksound));
X fmon = restmonchn(fd, ghostly);
X
X /* regenerate animals while on another level */
X { long tmoves = (monstermoves > omoves) ? monstermoves-omoves : 0;
X register struct monst *mtmp2;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp2) {
X
X mtmp2 = mtmp->nmon;
X if((mtmp->data->geno&G_GENOD) && !(mtmp->data->geno&G_UNIQ)) {
X /* mondead() would try to link the monster's objects
X * into fobj and the appropriate nexthere chain.
X * unfortunately, such things will not have sane
X * values until after find_lev_obj() well below
X * here, so we'd go chasing random pointers if we
X * tried that. we could save the monster's objects
X * in another chain and insert them in the level
X * later, but that's a lot of work for very little
X * gain. hence, just throw the objects away via
X * mongone() and pretend the monster wandered off
X * somewhere private before the genocide.
X */
X mongone(mtmp);
X continue;
X }
X
X if (ghostly) {
X /* reset peaceful/malign relative to new character */
X if(!mtmp->isshk)
X /* shopkeepers will reset based on name */
X mtmp->mpeaceful = peace_minded(mtmp->data);
X set_malign(mtmp);
X } else if (mtmp->mtame && tmoves > 250)
X mtmp->mtame = mtmp->mpeaceful = 0;
X
X /* restore shape changers - Maarten Jan Huisjes */
X if (mtmp->data == &mons[PM_CHAMELEON]
X && !Protection_from_shape_changers
X && !mtmp->cham)
X mtmp->cham = 1;
X else if(Protection_from_shape_changers) {
X if (mtmp->cham) {
X mtmp->cham = 0;
X (void) newcham(mtmp, &mons[PM_CHAMELEON]);
X } else if(is_were(mtmp->data) && !is_human(mtmp->data))
X (void) new_were(mtmp);
X }
X
X if (!ghostly) {
X nhp = mtmp->mhp +
X (regenerates(mtmp->data) ? tmoves : tmoves/20);
X if(!mtmp->mcansee && mtmp->mblinded) {
X if (mtmp->mblinded < tmoves) mtmp->mblinded = 0;
X else mtmp->mblinded -= tmoves;
X }
X if(!mtmp->mcanmove && mtmp->mfrozen) {
X if (mtmp->mfrozen < tmoves) mtmp->mfrozen = 0;
X else mtmp->mfrozen -= tmoves;
X }
X if(nhp > mtmp->mhpmax)
X mtmp->mhp = mtmp->mhpmax;
X else
X#ifdef LINT /* (long)newhp -> (schar = short int) mhp; ok in context of text above */
X mtmp->mhp = 0;
X#else
X mtmp->mhp = nhp;
X#endif
X }
X }
X }
X
X fgold = 0;
X while(gold = newgold(),
X mread(fd, (genericptr_t)gold, sizeof(struct gold)),
X gold->gx) {
X gold->ngold = fgold;
X fgold = gold;
X }
X free((genericptr_t) gold);
X ftrap = 0;
X while (trap = newtrap(),
X mread(fd, (genericptr_t)trap, sizeof(struct trap)),
X trap->tx) {
X trap->ntrap = ftrap;
X ftrap = trap;
X }
X free((genericptr_t) trap);
X fobj = restobjchn(fd, ghostly);
X find_lev_obj();
X billobjs = restobjchn(fd, ghostly);
X rest_engravings(fd);
X mread(fd, (genericptr_t)rooms, sizeof(rooms));
X mread(fd, (genericptr_t)doors, sizeof(doors));
X#ifdef WORM
X mread(fd, (genericptr_t)wsegs, sizeof(wsegs));
X for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){
X wheads[tmp] = wsegs[tmp] = wtmp = newseg();
X while(1) {
X mread(fd, (genericptr_t)wtmp, sizeof(struct wseg));
X if(!wtmp->nseg) break;
X wheads[tmp]->nseg = wtmp = newseg();
X wheads[tmp] = wtmp;
X }
X }
X mread(fd, (genericptr_t)wgrowtime, sizeof(wgrowtime));
X#endif
X
X /* reset level.monsters for new level */
X for (x = 0; x < COLNO; x++)
X for (y = 0; y < ROWNO; y++)
X level.monsters[x][y] = (struct monst *) 0;
X for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon)
X place_monster(mtmp, mtmp->mx, mtmp->my);
X
X#ifdef TUTTI_FRUTTI
X /* Now get rid of all the temp fruits... */
X if (ghostly) {
X struct fruit *fruit;
X
X while(oldfruit) {
X fruit = oldfruit->nextf;
X free((genericptr_t) oldfruit);
X oldfruit = fruit;
X }
X }
X#endif
X if(ghostly && lev > medusa_level && lev < stronghold_level &&
X xdnstair == 0) {
X coord cc;
X
X mazexy(&cc);
X xdnstair = cc.x;
X ydnstair = cc.y;
X levl[cc.x][cc.y].typ = STAIRS;
X }
X}
X
X#ifdef ZEROCOMP
X#define RLESC '\0' /* Leading character for run of RLESC's */
X
Xstatic unsigned char NEARDATA inbuf[BUFSZ];
Xstatic unsigned short NEARDATA inbufp = 0;
Xstatic unsigned short NEARDATA inbufsz = 0;
Xstatic short NEARDATA inrunlength = -1;
Xstatic int NEARDATA mreadfd;
Xstatic int NDECL(mgetc);
X
Xstatic int
Xmgetc()
X{
X if (inbufp >= inbufsz) {
X inbufsz = read(mreadfd, (genericptr_t)inbuf, (int)sizeof inbuf);
X if (!inbufsz) {
X if (inbufp > sizeof inbuf)
X error("EOF on file #%d.\n", mreadfd);
X inbufp = 1 + sizeof inbuf; /* exactly one warning :-) */
X return -1;
X }
X inbufp = 0;
X }
X return inbuf[inbufp++];
X}
X
Xvoid
Xminit()
X{
X inbufsz = 0;
X inbufp = 0;
X inrunlength = -1;
X}
X
Xint
Xmread(fd, buf, len)
Xint fd;
Xgenericptr_t buf;
Xregister unsigned len;
X{
X /*register int readlen = 0;*/
X mreadfd = fd;
X while (len--) {
X if (inrunlength > 0) {
X inrunlength--;
X *(*((char **)&buf))++ = '\0';
X } else {
X register short ch = mgetc();
X if (ch < 0) return -1; /*readlen;*/
X if ((*(*(char **)&buf)++ = ch) == RLESC) {
X inrunlength = mgetc();
X }
X }
X /*readlen++;*/
X }
X return 0; /*readlen;*/
X}
X
X#else /* ZEROCOMP */
X
Xvoid
Xmread(fd, buf, len)
Xregister int fd;
Xregister genericptr_t buf;
Xregister unsigned int len;
X{
X register int rlen;
X
X#if defined(BSD) || defined(ULTRIX)
X rlen = read(fd, buf, (int) len);
X if(rlen != len){
X#else /* e.g. SYSV, __TURBOC__ */
X rlen = read(fd, buf, (unsigned) len);
X if((unsigned)rlen != len){
X#endif
X pline("Read %d instead of %u bytes.\n", rlen, len);
X if(restoring) {
X (void) unlink(SAVEF);
X#ifdef AMIGA_WBENCH
X ami_wbench_unlink(SAVEF);
X#endif
X error("Error restoring old game.");
X }
X panic("Error reading level file.");
X }
X}
X#endif /* ZEROCOMP */
END_OF_FILE
if test 25217 -ne `wc -c <'src/restore.c'`; then
echo shar: \"'src/restore.c'\" unpacked with wrong size!
fi
# end of 'src/restore.c'
fi
echo shar: End of archive 27 \(of 56\).
cp /dev/null ark27isdone
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 56 archives.
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