billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 77
Archive-name: NetHack3/Part22
#! /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 22 (of 38)."
# Contents: amiga/amidos.c include/mkroom.h others/msdos.c
# others/tos.c
# Wrapped by billr@saab on Sun Jul 23 21:33:05 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'amiga/amidos.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'amiga/amidos.c'\"
else
echo shar: Extracting \"'amiga/amidos.c'\" \(16238 characters\)
sed "s/^X//" >'amiga/amidos.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)amidos.c msdos.c - Amiga version 3.0 89/05/01
X/* NetHack may be freely redistributed. See license for details. */
X/* An assortment of imitations of cheap plastic MSDOS functions.
X */
X
X#include <libraries/dos.h>
X
X#undef TRUE
X#undef FALSE
X#undef COUNT
X#undef NULL
X
X#include "hack.h"
X
Xextern char Initialized;
X
Xstruct FileLock *Lock(), *CurrentDir(); /* Cheating - BCPL pointers */
Xstruct FileHandle *Open(); /* Cheating - BCPL pointer */
Xlong Read(), Write(), IoErr(), AvailMem();
Xvoid *malloc();
Xchar *rindex(), *index();
X
Xint Enable_Abort = 0; /* for stdio package */
X
X/* Initial path, so we can find NetHack.cnf */
X
Xchar PATH[PATHLEN] = "Ram:;df0:;NetHack:";
X
Xvoid
Xflushout()
X{
X (void) fflush(stdout);
X}
X
X#ifndef getuid
Xgetuid()
X{
X return 1;
X}
X#endif
X
X/*
X * Actually make up a process id.
X * Makes sure one can mess less with saved levels...
X */
X
Xint getpid()
X{
X static short pid;
X
X while (pid == 0) {
X struct DateStamp dateStamp;
X pid = rnd(30000);
X pid += DateStamp(&dateStamp); /* More or less random */
X pid ^= (short) (dateStamp.ds_Days >> 16) ^
X (short) (dateStamp.ds_Days) ^
X (short) (dateStamp.ds_Minute) +
X (short) (dateStamp.ds_Tick);
X pid %= 30000;
X }
X
X return pid;
X}
X
X#ifndef getlogin
Xchar *
Xgetlogin()
X{
X return ((char *) NULL);
X}
X#endif
X
Xint
Xabs(x)
Xint x;
X{
X return x < 0? -x: x;
X}
X
X#ifdef REDO
X
Xint
Xtgetch()
X{
X char ch, popch();
X
X if (!(ch = popch())) {
X ch = WindowGetchar();
X }
X return ((ch == '\r') ? '\n' : ch);
X}
X#else /* REDO /**/
Xint
Xtgetch() {
X char ch;
X
X ch = WindowGetchar();
X return ((ch == '\r') ? '\n' : ch);
X}
X#endif /* REDO /**/
X
X
X#ifdef DGK
X# include <ctype.h>
X/* # include <fcntl.h> */
X
X# define Sprintf (void) sprintf
X
X# ifdef SHELL
Xint
Xdosh()
X{
X pline("No mysterious force prevented you from using multitasking.");
X return 0;
X}
X# endif /* SHELL */
X
X#define ID_DOS1_DISK 'DOS\1'
X#define EXTENSION 72
X
X/*
X * This routine uses an approximation of the free bytes on a disk.
X * How large a file you can actually write depends on the number of
X * extension blocks you need for it.
X * In each extenstion block there are maximum 72 pointers to blocks,
X * so every 73 disk blocks have only 72 available for data.
X * The (necessary) file header is also good for 72 data block pointers.
X */
Xlong
Xfreediskspace(path)
Xchar *path;
X{
X register long freeBytes = 0;
X register struct InfoData *infoData; /* Remember... longword aligned */
X char fileName[32];
X
X /*
X * Find a valid path on the device of which we want the free space.
X * If there is a colon in the name, it is an absolute path
X * and all up to the colon is everything we need.
X * Remember slashes in a volume name are allowed!
X * If there is no colon, it is relative to the current directory,
X * so must be on the current device, so "" is enough...
X */
X {
X register char *colon;
X
X strncpy(fileName, path, sizeof(fileName)-1);
X fileName[31] = 0;
X if (colon = index(fileName, ':'))
X colon[1] = '\0';
X else
X fileName[0] = '\0';
X }
X
X if (infoData = malloc(sizeof(*infoData))) {
X struct FileLock *fileLock; /* Cheating */
X if (fileLock = Lock(fileName, SHARED_LOCK)) {
X if (Info(fileLock, infoData)) {
X /* We got a kind of DOS volume, since we can Lock it. */
X /* Calculate number of blocks available for new file */
X /* Kludge for the ever-full VOID: (oops RAM:) device */
X if (infoData->id_UnitNumber == -1 &&
X infoData->id_NumBlocks == infoData->id_NumBlocksUsed) {
X freeBytes = AvailMem(0L) - 64 * 1024L;
X /* Just a stupid guess at the */
X /* Ram-Handler overhead per block: */
X freeBytes -= freeBytes/16;
X } else {
X /* Normal kind of DOS file system device/volume */
X freeBytes = infoData->id_NumBlocks -
X infoData->id_NumBlocksUsed;
X freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1);
X freeBytes *= infoData->id_BytesPerBlock;
X }
X if (freeBytes < 0)
X freeBytes = 0;
X }
X UnLock(fileLock);
X }
X free(infoData);
X }
X return freeBytes;
X}
X
X
Xlong
Xfilesize(file)
Xchar *file;
X{
X register struct FileLock *fileLock;
X register struct FileInfoBlock *fileInfoBlock;
X register long size = 0;
X
X if (fileInfoBlock = malloc(sizeof(*fileInfoBlock))) {
X if (fileLock = Lock(file, SHARED_LOCK)) {
X if (Examine(fileLock, fileInfoBlock)) {
X size = fileInfoBlock->fib_Size;
X }
X UnLock(fileLock);
X }
X free(fileInfoBlock);
X }
X return size;
X}
X
X/*
X * On the Amiga, looking if a specific file exists is much faster
X * than sequentially reading a directory.
X */
X
Xvoid
Xeraseall(path, files)
Xchar *path, *files;
X{
X char buf[FILENAME];
X short i;
X struct FileLock *fileLock, *dirLock;
X
X if (dirLock = Lock(path)) {
X dirLock = CurrentDir(dirLock);
X
X strcpy(buf, files);
X for (i = 0; i < MAXLEVEL; i++) {
X name_file(buf, i);
X if (fileLock = Lock(buf, SHARED_LOCK)) {
X UnLock(fileLock);
X DeleteFile(buf);
X }
X }
X
X UnLock(CurrentDir(dirLock));
X }
X}
X
X/* This size makes that most files can be copied with two Read()/Write()s */
X
X#define COPYSIZE 4096
X
Xchar *CopyFile(from, to)
Xchar *from, *to;
X{
X register struct FileHandle *fromFile, *toFile;
X register char *buffer;
X register long size;
X char *error = NULL;
X
X if (buffer = malloc(COPYSIZE)) {
X if (fromFile = Open(from, MODE_OLDFILE)) {
X if (toFile = Open(to, MODE_NEWFILE)) {
X while (size = Read(fromFile, buffer, (long)COPYSIZE)) {
X if (size != Write(toFile, buffer, size)) {
X error = "Write error";
X break;
X }
X }
X Close(toFile);
X } else /* Can't open destination file */
X error = "Cannot open destination";
X Close(fromFile);
X } else /* Cannot open source file. Should not happen. */
X error = "Huh?? Cannot open source??";
X free(buffer);
X return error;
X } else /* Cannot obtain buffer for copying */
X return "No Memory !";
X}
X
Xvoid
Xcopybones(mode)
Xint mode;
X{
X struct FileLock *fileLock;
X char from[FILENAME], to[FILENAME];
X char *frompath, *topath, *status;
X short i;
X extern int saveprompt;
X
X if (!ramdisk)
X return;
X
X frompath = (mode != TOPERM) ? permbones : levels;
X topath = (mode == TOPERM) ? permbones : levels;
X
X /* Remove any bones files in `to' directory. */
X eraseall(topath, allbones);
X
X /* Copy `from' to `to' */
X strcpy(from, frompath);
X strcat(from, allbones);
X strcpy(to, topath);
X strcat(to, allbones);
X
X for (i = 1; i < MAXLEVEL; i++) {
X name_file(from, i);
X name_file(to, i);
X if (fileLock = Lock(from, SHARED_LOCK)) {
X UnLock(fileLock);
X if (status = CopyFile(from, to))
X goto failed;
X }
X }
X
X /*
X * The last file got there. Remove the ramdisk bones files.
X */
X if (mode == TOPERM)
X eraseall(frompath, allbones);
X return;
X
X /* Last file didn't get there. */
X
Xfailed:
X msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status);
X
X if (mode == TOPERM) {
X msmsg("Bones will be left in `%s'\n",
X *frompath ? frompath : hackdir);
X return;
X } else {
X /* Remove all bones files on the RAMdisk */
X eraseall(levels, allbones);
X playwoRAMdisk();
X }
X}
X
Xvoid
XplaywoRAMdisk()
X{
X msmsg("Do you wish to play without a RAMdisk (y/n) ? ");
X
X /* Set ramdisk false *before* exit'ing (because msexit calls
X * copybones)
X */
X ramdisk = FALSE;
X if (Getchar() != 'y') {
X settty("Be seeing you ...\n");
X exit(0);
X }
X set_lock_and_bones();
X return;
X}
X
Xint
XsaveDiskPrompt(start)
X{
X extern int saveprompt;
X char buf[BUFSIZ], *bp;
X struct FileLock *fileLock;
X
X if (saveprompt) {
X /* Don't prompt if you can find the save file */
X if (fileLock = Lock(SAVEF, SHARED_LOCK)) {
X UnLock(fileLock);
X return 1;
X }
X remember_topl();
X home();
X cl_end();
X msmsg("If save file is on a SAVE disk, put that disk in 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{
X FILE *file;
X
X if (file = fopenp(RECORD, "r")) {
X fclose(file);
X return TRUE;
X }
X return FALSE;
X}
X
X/* Prompt for game disk, then check for record file.
X */
Xvoid
XgameDiskPrompt()
X{
X extern int saveprompt;
X
X if (record_exists())
X return;
X
X if (saveprompt) {
X (void) putchar('\n');
X getreturn("when the GAME disk has been put in");
X }
X
X if (!record_exists()) {
X msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD);
X
X msmsg("If the GAME disk is not in, put it in now.\n");
X getreturn("to continue");
X }
X}
X
X/* Read configuration */
Xvoid
Xread_config_file()
X{
X char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
X char buf[BUFSZ], *bufp;
X FILE *fp, *fopenp();
X extern char plname[];
X extern int saveprompt;
X
X tmp_ramdisk[0] = 0;
X tmp_levels[0] = 0;
X if ((fp = fopenp(configfile, "r")) == NULL) {
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 = index(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 } else if (!strncmp(buf, "RAMDISK", 3)) {
X strncpy(tmp_ramdisk, bufp, PATHLEN);
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, (boolean)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 char *ptr;
X if (ptr = index(bufp, ';')) {
X *ptr = '\0';
X if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
X saveprompt = FALSE;
X }
X (void) strncpy(SAVEF, bufp, PATHLEN);
X append_slash(SAVEF);
X } else if (!strncmp(buf, "GRAPHICS", 4)) {
X unsigned int translate[28]; /* MAXPCHARS */
X int i;
X
X if ((i = 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",
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[27], &translate[28], &translate[29],
X &translate[30], &translate[31])) < 0) {
X msmsg ("Syntax error in GRAPHICS\n");
X getreturn("to continue");
X } /* Yuck! Worked only with low-byte first!!! */
X#define SETPCHAR(f, n) showsyms.f = (i > n) ? translate[n] : defsyms.f
X SETPCHAR(stone, 0);
X SETPCHAR(vwall, 1);
X SETPCHAR(hwall, 2);
X SETPCHAR(tlcorn, 3);
X SETPCHAR(trcorn, 4);
X SETPCHAR(blcorn, 5);
X SETPCHAR(brcorn, 6);
X SETPCHAR(crwall, 7);
X SETPCHAR(tuwall, 8);
X SETPCHAR(tdwall, 9);
X SETPCHAR(tlwall, 10);
X SETPCHAR(trwall, 11);
X SETPCHAR(vbeam, 12);
X SETPCHAR(hbeam, 13);
X SETPCHAR(lslant, 14);
X SETPCHAR(rslant, 15);
X SETPCHAR(door, 16);
X SETPCHAR(room, 17);
X SETPCHAR(corr, 18);
X SETPCHAR(upstair, 19);
X SETPCHAR(dnstair, 20);
X SETPCHAR(trap, 21);
X SETPCHAR(web, 22);
X SETPCHAR(pool, 23);
X#ifdef FOUNTAINS
X SETPCHAR(fountain, 24);
X#endif
X#ifdef SINKS
X SETPCHAR(sink, 25);
X#endif
X#ifdef THRONES
X SETPCHAR(throne, 26);
X#endif
X#ifdef ALTARS
X SETPCHAR(altar, 27);
X#endif
X#ifdef STRONGHOLD
X SETPCHAR(upladder, 28);
X SETPCHAR(dnladder, 29);
X SETPCHAR(dbvwall, 30);
X SETPCHAR(dbhwall, 31);
X#endif
X#undef SETPCHAR
X } else if (!strncmp(buf, "PATH", 4)) {
X strncpy(PATH, bufp, PATHLEN);
X
X } else {
X msmsg("Bad option line: '%s'\n", buf);
X getreturn("to continue");
X }
X }
X fclose(fp);
X
X strcpy(permbones, tmp_levels);
X if (tmp_ramdisk[0]) {
X strcpy(levels, tmp_ramdisk);
X if (strcmpi(permbones, levels)) /* if not identical */
X ramdisk = TRUE;
X } else
X strcpy(levels, tmp_levels);
X strcpy(bones, levels);
X}
X
X/* Set names for bones[] and lock[] */
X
Xvoid
Xset_lock_and_bones()
X{
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}
X
X/*
X * Add a slash 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 != ':') {
X *++ptr = '/';
X *++ptr = '\0';
X }
X}
X
X
Xvoid
Xgetreturn(str)
Xchar *str;
X{
X int ch;
X
X msmsg("Hit <RETURN> %s.", str);
X while ((ch = Getchar()) != '\n')
X ;
X}
X
Xvoid
Xmsmsg(fmt, a1, a2, a3)
Xchar *fmt;
Xlong a1, a2, a3;
X{
X printf(fmt, a1, a2, a3);
X (void) fflush(stdout);
X}
X
X/* Follow the PATH, trying to fopen the file.
X */
X#define PATHSEP ';'
X#undef fopen
X
XFILE *
Xfopenp(name, mode)
Xregister char *name, *mode;
X{
X char buf[BUFSIZ], *bp, *pp, lastch;
X FILE *fp;
X register struct FileLock *theLock;
X
X /* Try the default directory first. Then look along PATH.
X */
X strcpy(buf, name);
X if (theLock = Lock(buf, SHARED_LOCK)) {
X UnLock(theLock);
X if (fp = fopen(buf, mode))
X return fp;
X }
X pp = PATH;
X while (pp && *pp) {
X bp = buf;
X while (*pp && *pp != PATHSEP)
X lastch = *bp++ = *pp++;
X if (lastch != ':' && lastch != '/' && bp != buf)
X *bp++ = '/';
X strcpy(bp, name);
X if (theLock = Lock(buf, SHARED_LOCK)) {
X UnLock(theLock);
X if (fp = fopen(buf, mode))
X return fp;
X }
X if (*pp)
X pp++;
X }
X return NULL;
X}
X#endif /* DGK */
X
X#ifdef CHDIR
X
X/*
X * A not general-purpose directory changing routine.
X * Assumes you want to return to the original directory eventually,
X * by chdir()ing to orgdir.
X * Assumes -1 is not a valid lock, since 0 is valid.
X */
X
X#define NO_LOCK ((struct FileLock *) -1)
X
Xchar orgdir[1];
Xstatic struct FileLock *OrgDirLock = NO_LOCK;
X
Xchdir(dir)
Xchar *dir;
X{
X if (dir == orgdir) {
X /* We want to go back to where we came from. */
X if (OrgDirLock != NO_LOCK) {
X UnLock(CurrentDir(OrgDirLock));
X OrgDirLock = NO_LOCK;
X }
X } else {
X /*
X * Go to some new place. If still at the original
X * directory, save the FileLock.
X */
X struct FileLock *newDir;
X
X if (newDir = Lock(dir, SHARED_LOCK)) {
X if (OrgDirLock == NO_LOCK) {
X OrgDirLock = CurrentDir(newDir);
X } else {
X UnLock(CurrentDir(newDir));
X }
X } else {
X return -1; /* Failed */
X }
X }
X /* CurrentDir always succeeds if you have a lock */
X return 0;
X}
X
X#endif
X
X/* Chdir back to original directory
X */
X#undef exit
Xvoid
Xmsexit(code)
X{
X#ifdef CHDIR
X extern char orgdir[];
X#endif
X
X#ifdef DGK
X (void) fflush(stdout);
X if (ramdisk)
X copybones(TOPERM);
X#endif
X#ifdef CHDIR
X chdir(orgdir); /* chdir, not chdirx */
X#endif
X
X CleanUp();
X exit(code);
X}
X
X/*
X * Strcmp while ignoring case. Not general-purpose, so static.
X */
X
Xstatic int strcmpi(a, b)
Xregister char *a, *b;
X{
X while (tolower(*a) == tolower(*b)) {
X if (!*a) /* *a == *b, so at end of both strings */
X return 0; /* equal. */
X a++;
X b++;
X }
X return 1;
X}
X
X/*
X * memcmp - used to compare two struct symbols, in lev.c
X */
X
Xmemcmp(a, b, size)
Xregister unsigned char *a, *b;
Xregister int size;
X{
X while (size--) {
X if (*a++ != *b++)
X return 1; /* not equal */
X }
X
X return 0; /* equal */
X}
END_OF_FILE
if test 16238 -ne `wc -c <'amiga/amidos.c'`; then
echo shar: \"'amiga/amidos.c'\" unpacked with wrong size!
fi
# end of 'amiga/amidos.c'
fi
if test -f 'include/mkroom.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'include/mkroom.h'\"
else
echo shar: Extracting \"'include/mkroom.h'\" \(2288 characters\)
sed "s/^X//" >'include/mkroom.h' <<'END_OF_FILE'
X/* SCCS Id: @(#)mkroom.h 3.0 89/01/07
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#ifndef MKROOM_H
X#define MKROOM_H
X
X/* mkroom.h - types and structures for room and shop initialization */
X
Xstruct mkroom {
X schar lx,hx,ly,hy; /* usually xchar, but hx may be -1 */
X schar rtype,rlit,doorct,fdoor;
X};
X
Xstruct shclass {
X char *name; /* name of the shop type */
X char symb; /* this identifies the shop type */
X int prob; /* the shop type probability in % */
X schar dist; /* artifact placement type */
X#define D_SCATTER 0 /* normal placement */
X#define D_SHOP 1 /* shop-like placement */
X#define D_TEMPLE 2 /* temple-like placement */
X struct itp {
X int iprob; /* probability of an item type */
X int itype; /* item type: if >=0 a class, if < 0 a specific item */
X } iprobs[5];
X char **shknms; /* string list of shopkeeper names for this type */
X};
Xextern const struct shclass shtypes[]; /* defined in shknam.c */
X
Xextern struct mkroom rooms[MAXNROFROOMS+1];
X/* the normal rooms on the current level are described in rooms[0..n] for
X * some n<MAXNROFROOMS
X * the vault, if any, is described by rooms[n+1]
X * the next rooms entry has hx -1 as a flag
X * there is at most one non-vault special room on a level
X */
Xextern coord doors[DOORMAX];
X
X/* values for rtype in the room definition structure */
X#define OROOM 0 /* ordinary room */
X#define COURT 2 /* contains a throne */
X#define SWAMP 3 /* contains pools */
X#define VAULT 4 /* contains piles of gold */
X#define BEEHIVE 5 /* contains killer bees and royal jelly */
X#define MORGUE 6 /* contains corpses, undead and ghosts */
X#define BARRACKS 7 /* contains soldiers and their gear */
X#define ZOO 8 /* floor covered with treasure and monsters */
X#define DELPHI 9 /* contains Oracle and peripherals */
X#define TEMPLE 10 /* contains a shrine */
X#define SHOPBASE 11 /* everything above this is a shop */
X#define ARMORSHOP 12 /* specific shop defines for level compiler */
X#define SCROLLSHOP 13
X#define POTIONSHOP 14
X#define WEAPONSHOP 15
X#define FOODSHOP 16
X#define RINGSHOP 17
X#define WANDSHOP 18
X#define TOOLSHOP 19
X#ifdef SPELLS
X#define BOOKSHOP 20
X#endif
X
X#define IS_SHOP(x) ((x).rtype >= SHOPBASE)
X
X#endif /* MKROOM_H /**/
END_OF_FILE
if test 2288 -ne `wc -c <'include/mkroom.h'`; then
echo shar: \"'include/mkroom.h'\" unpacked with wrong size!
fi
# end of 'include/mkroom.h'
fi
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'\" \(16169 characters\)
sed "s/^X//" >'others/msdos.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)msdos.c 3.0 88/11/20
X/* NetHack may be freely redistributed. See license for details. */
X/* An assortment of MSDOS functions.
X */
X
X#ifdef MSDOS
X#include <dos.h>
X#include "hack.h"
Xstatic char DOSgetch();
X#ifdef DGK
Xstatic char BIOSgetch();
X#endif
Xstatic unsigned int ioctl();
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#define DIRECT_INPUT 0x7
Xstatic char
XDOSgetch() {
X union REGS regs;
X
X regs.h.ah = DIRECT_INPUT;
X intdos(®s, ®s);
X if (!regs.h.al) { /* an extended code -- not yet supported */
X regs.h.ah = DIRECT_INPUT;
X intdos(®s, ®s); /* eat the next character */
X regs.h.al = 0; /* and return a 0 */
X }
X return (regs.h.al);
X}
X
X#include <ctype.h>
X#include <fcntl.h>
X#include <process.h>
X
Xstatic char *COMSPEC = "COMSPEC";
X#define getcomspec() getenv(COMSPEC)
X
X#ifdef SHELL
Xint
Xdosh() {
X extern char orgdir[];
X char *comspec;
X
X if (comspec = getcomspec()) {
X#ifdef DGK
X settty("To return to NetHack, type \"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 chdirx(hackdir, 0);
X start_screen();
X docrt();
X } else
X pline("Cannot exec COMMAND.COM");
X return 0;
X}
X#endif /* SHELL */
X
X#ifdef DGK
X/* Normal characters are output when the shift key is not pushed.
X * Shift characters are output when either shift key is pushed.
X */
X#define KEYPADHI 83
X#define KEYPADLOW 71
X#define PADKEYS (KEYPADHI - KEYPADLOW + 1)
X#define iskeypad(x) (KEYPADLOW <= (x) && (x) <= KEYPADHI)
Xstatic const struct pad {
X char normal, shift;
X } keypad[PADKEYS] = {
X {'y', 'Y'}, /* 7 */
X {'k', 'K'}, /* 8 */
X {'u', 'U'}, /* 9 */
X {'m', CTRL('P')}, /* - */
X {'h', 'H'}, /* 4 */
X {'g', 'g'}, /* 5 */
X {'l', 'L'}, /* 6 */
X {'p', 'P'}, /* + */
X {'b', 'B'}, /* 1 */
X {'j', 'J'}, /* 2 */
X {'n', 'N'}, /* 3 */
X {'i', 'I'}, /* Ins */
X {'.', ':'} /* Del */
X }, numpad[PADKEYS] = {
X {'7', '7'}, /* 7 */
X {'8', '8'}, /* 8 */
X {'9', '9'}, /* 9 */
X {'m', CTRL('P')}, /* - */
X {'4', '4'}, /* 4 */
X {'g', 'G'}, /* 5 */
X {'6', '6'}, /* 6 */
X {'p', 'P'}, /* + */
X {'1', '1'}, /* 1 */
X {'2', '2'}, /* 2 */
X {'3', '3'}, /* 3 */
X {'i', 'I'}, /* Ins */
X {'.', ':'} /* Del */
X};
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#define KEYBRD_BIOS 0x16
X
Xstatic char
XBIOSgetch() {
X unsigned char scan, shift, ch;
X union REGS regs;
X struct pad (*kpad)[PADKEYS];
X
X /* Get scan code.
X */
X regs.h.ah = 0;
X int86(KEYBRD_BIOS, ®s, ®s);
X ch = regs.h.al;
X scan = regs.h.ah;
X
X /* Get shift status.
X */
X regs.h.ah = 2;
X int86(KEYBRD_BIOS, ®s, ®s);
X shift = regs.h.al;
X
X /* If scan code is for the keypad, translate it.
X */
X kpad = flags.num_pad ? numpad : keypad;
X if (iskeypad(scan)) {
X if (shift & SHIFT) {
X flags.mv = flags.run = 1;
X /* necessary if number_pad is on */
X ch = (*kpad)[scan - KEYPADLOW].shift;
X } else
X ch = (*kpad)[scan - KEYPADLOW].normal;
X }
X return ch;
X}
X
X#define FINDFIRST 0x4E00
X#define FINDNEXT 0x4F00
X#define GETDTA 0x2F00
X#define SETFILETIME 0x5701
X#define GETSWITCHAR 0x3700
X#define FREESPACE 0x36
X
X#ifdef __TURBOC__
X#define switchar() (char)getswitchar()
X#else
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
X
Xlong
Xfreediskspace(path)
Xchar *path;
X{
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}
X
X/* Functions to get filenames using wildcards
X */
Xstatic int
Xfindfirst(path)
Xchar *path;
X{
X union REGS regs;
X struct SREGS sregs;
X
X regs.x.ax = FINDFIRST;
X regs.x.cx = 0; /* 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}
X
Xstatic int
Xfindnext() {
X union REGS regs;
X
X regs.x.ax = FINDNEXT;
X intdos(®s, ®s);
X return !regs.x.cflag;
X}
X
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.x.ax = 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
Xlong
Xfilesize(file)
Xchar *file;
X{
X char *dta;
X
X if (findfirst(file)) {
X dta = getdta();
X return (* (long *) (dta + 26));
X } else
X return -1L;
X}
X
Xvoid
Xeraseall(path, files)
Xchar *path, *files;
X{
X char *dta, buf[PATHLEN];
X
X dta = getdta();
X Sprintf(buf, "%s%s", path, files);
X if (findfirst(buf))
X do {
X Sprintf(buf, "%s%s", path, dta + 30);
X (void) unlink(buf);
X } while (findnext());
X return;
X}
X
X/* Rewritten for version 3.3 to be faster
X */
Xvoid
Xcopybones(mode) {
X char from[PATHLEN], to[PATHLEN], last[13], copy[8];
X char *frompath, *topath, *dta, *comspec;
X int status;
X long fs;
X extern saveprompt;
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 dta = getdta();
X last[0] = '\0';
X Sprintf(from, "%s%s", frompath, allbones);
X if (findfirst(from))
X do {
X Strcpy(last, dta + 30);
X } while (findnext());
X
X topath = (mode == TOPERM) ? permbones : levels;
X if (last[0]) {
X Sprintf(copy, "%cC copy", switchar());
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
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 /* Last file didn't get there.
X */
X Sprintf(to, "%s%s", topath, allbones);
X msmsg("Cannot copy `%s' to `%s' -- %s\n", from, to,
X (status < 0) ? "can't spawn COMSPEC !" :
X (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
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) {
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, put that disk in 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
X if ((fd = open(RECORD, 0)) >= 0) {
X (void) close(fd);
X return TRUE;
X }
X return FALSE;
X}
X
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
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 put in");
X }
X if (comspec_exists() && record_exists())
X return;
X
X if (!comspec_exists())
X msmsg("\n\nWARNING: can't find comspec `%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, put it in now.\n");
X getreturn("to continue");
X return;
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 FILE *fopenp();
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 append_slash(SAVEF);
X } else if (!strncmp(buf, "GRAPHICS", 4)) {
X unsigned int translate[MAXPCHARS];
X int i;
X
X if ((i = 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",
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])) < 0) {
X msmsg ("Syntax error in GRAPHICS\n");
X getreturn("to continue");
X }
X#define SETPCHAR(f, n) showsyms.f = (i > n) ? translate[n] : defsyms.f
X SETPCHAR(stone, 0);
X SETPCHAR(vwall, 1);
X SETPCHAR(hwall, 2);
X SETPCHAR(tlcorn, 3);
X SETPCHAR(trcorn, 4);
X SETPCHAR(blcorn, 5);
X SETPCHAR(brcorn, 6);
X SETPCHAR(crwall, 7);
X SETPCHAR(tuwall, 8);
X SETPCHAR(tdwall, 9);
X SETPCHAR(tlwall, 10);
X SETPCHAR(trwall, 11);
X SETPCHAR(vbeam, 12);
X SETPCHAR(hbeam, 13);
X SETPCHAR(lslant, 14);
X SETPCHAR(rslant, 15);
X SETPCHAR(door, 16);
X SETPCHAR(room, 17);
X SETPCHAR(corr, 18);
X SETPCHAR(upstair, 19);
X SETPCHAR(dnstair, 20);
X SETPCHAR(trap, 21);
X SETPCHAR(web, 22);
X SETPCHAR(pool, 23);
X#ifdef FOUNTAINS
X SETPCHAR(fountain, 24);
X#endif
X#ifdef SINKS
X SETPCHAR(sink, 25);
X#endif
X#ifdef THRONES
X SETPCHAR(throne, 26);
X#endif
X#ifdef ALTARS
X SETPCHAR(altar, 27);
X#endif
X#ifdef STRONGHOLD
X SETPCHAR(upladder, 28);
X SETPCHAR(dnladder, 29);
X SETPCHAR(dbvwall, 30);
X SETPCHAR(dbhwall, 31);
X#endif
X#undef SETPCHAR
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)
Xchar *str;
X{
X msmsg("Hit <RETURN> %s.", str);
X while (Getchar() != '\n') ;
X return;
X}
X
Xvoid
Xmsmsg(fmt, a1, a2, a3)
Xchar *fmt;
Xlong a1, a2, a3;
X{
X Printf(fmt, a1, a2, a3);
X flushout();
X return;
X}
X
X/* Chdrive() changes the default drive.
X */
X#ifndef __TURBOC__
X#define SELECTDISK 0x0E
Xvoid
Xchdrive(str)
Xchar *str;
X{
X char *ptr;
X union REGS inregs;
X char drive;
X
X if ((ptr = index(str, ':')) != NULL) {
X drive = toupper(*(ptr - 1));
X inregs.h.ah = SELECTDISK;
X inregs.h.dl = drive - 'A';
X intdos(&inregs, &inregs);
X }
X return;
X}
X#else
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/* 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#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
Xstatic unsigned int old_stdin, old_stdout;
X
Xvoid
Xdisable_ctrlP() {
X#ifdef DGK
X if (!flags.rawio) return;
X#endif
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 return;
X}
X
Xvoid
Xenable_ctrlP() {
X#ifdef DGK
X if (!flags.rawio) return;
X#endif
X if (old_stdin)
X (void) ioctl(STDIN, SETBITS, old_stdin);
X if (old_stdout)
X (void) ioctl(STDOUT, SETBITS, old_stdout);
X return;
X}
X
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
X#ifdef DGK
X/* Follow the PATH, trying to fopen the file.
X */
X#define PATHSEP ';'
X
XFILE *
Xfopenp(name, mode)
Xchar *name, *mode;
X{
X char buf[BUFSIZ], *bp, *pp, lastch;
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 return (FILE *)0;
X}
X#endif /* DGK */
X
X/* Chdir back to original directory
X */
X#undef exit
Xvoid exit(int);
Xvoid
Xmsexit(code)
X{
X#ifdef CHDIR
X extern char orgdir[];
X#endif
X
X flushout();
X enable_ctrlP(); /* in case this wasn't done */
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 exit(code);
X return;
X}
X#endif /* MSDOS */
END_OF_FILE
if test 16169 -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 'others/tos.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'others/tos.c'\"
else
echo shar: Extracting \"'others/tos.c'\" \(16197 characters\)
sed "s/^X//" >'others/tos.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)tos.c 3.0 88/11/09
X * An assortment of functions for the Atari with Lattice C compiler.
X * Adapted from a similar set for MSDOS (written by Don Kneller) by
X * R. Black (Louisville, CO).
X */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#include "osbind.h"
X
Xextern int errno;
X
Xvoid
Xflushout()
X{
X (void) fflush(stdout);
X}
X
Xgetuid()
X{
X return 1;
X}
X
Xchar *
Xgetlogin()
X{
X return NULL;
X}
X
Xtgetch()
X{
X char ch;
X ch = BIOSgetch();
X return ((ch == '\r') ? '\n' : ch);
X}
X
X#ifdef exit
X#undef exit
X#endif
X
X#undef creat
X#define LEVELS "level.00"
X#define BONES "bones.00"
X
Xextern char hackdir[], levels[], SAVEF[], bones[], permbones[];
Xextern int ramdisk;
X
X#ifdef SHELL
X#ifndef UNIXDEBUG
X#include <process.h>
X#else /* null stuff for debugging purposes */
X#define P_WAIT 0
X#endif
Xdosh()
X{
X char *comspec, *getenv();
X extern char orgdir[];
X
X if (comspec = getenv("COMSPEC")) {
X end_screen();
X clear_screen();
X (void) puts("To return to HACK, type \"exit\" at the TOS prompt.");
X (void) fflush(stdout);
X chdirx(orgdir, 0);
X if (spawnl(P_WAIT, comspec, NULL)) {
X Printf("\nCan't execute COMSPEC \"%s\"!\n", comspec);
X flags.toplin = 0;
X more();
X }
X chdirx(hackdir, 0);
X start_screen();
X docrt();
X }
X return(0);
X}
X#endif SHELL
X
X/* Map the keypad to equivalent character output. If scroll lock is turned
X * on, run without stopping at interesting branches (like YUHJKLBN keys), if
X * it is off, run with stopping at branches (like ^Y^U^H^J^K^L^B^N keys).
X */
Xstatic char
XBIOSgetch()
X{
X int scan,c,result;
X char ch;
X result=Crawcin();
X scan=(result>>16)&0xff;
X c=result&0xff;
X switch (scan) {
X case 0x4a : {/*-*/
X ch=(c==0x2d) ? 'm' : '\20';
X break;
X }
X case 0x4e : {/*+*/
X ch=(c==0x2b) ? 'p' : 'P';
X break;
X }
X case 0x6d : {/*1*/
X if (flags.num_pad) ch='1';
X else ch=(c==0x31) ? 'b' : '\2';
X break;
X }
X case 0x6e : {/*2*/
X if (flags.num_pad) ch='2';
X else ch=(c==0x32) ? 'j' : '\12';
X break;
X }
X case 0x6f : {/*3*/
X if (flags.num_pad) ch='3';
X else ch=(c==0x33) ? 'n' : '\16';
X break;
X }
X case 0x6a : {/*4*/
X if (flags.num_pad) ch='4';
X else ch=(c==0x34) ? 'h' : '\10';
X break;
X }
X case 0x6b : {/*5*/
X ch='.';
X break;
X }
X case 0x6c : {/*6*/
X if (flags.num_pad) ch='6';
X else ch=(c==0x36) ? 'l' : '\14';
X break;
X }
X case 0x67 : {/*7*/
X if (flags.num_pad) ch='7';
X else ch=(c==0x37) ? 'y' : '\31';
X break;
X }
X case 0x68 : {/*8*/
X if (flags.num_pad) ch='8';
X else ch=(c==0x38) ? 'k' : '\13';
X break;
X }
X case 0x69 : {/*9*/
X if (flags.num_pad) ch='9';
X else ch=(c==0x39) ? 'u' : '\25';
X break;
X }
X default : ch=c;
X }
X return (ch);
X}
X
X/* After changing the value of flags.invlet_constant, make the current
X * inventory letters the fixed ones. -dgk
X */
Xvoid
Xfixinv()
X{
X struct obj *otmp;
X extern int lastinvnr;
X char ilet = 'a';
X
X for(otmp = invent; otmp; otmp = otmp->nobj) {
X otmp->invlet = ilet;
X if (++ilet > 'z') ilet = 'A';
X }
X lastinvnr = 51;
X}
X
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
Xlong
Xfilesize(file)
Xchar *file;
X{
X long old_dta;
X struct {
X char pad1[21];
X char attr;
X unsigned short time;
X unsigned short date;
X long size;
X char name[14];
X } fcb;
X fcb.size = (-1L);
X old_dta=Fgetdta();
X Fsetdta(&fcb);
X Fsfirst(file,0);
X Fsetdta(old_dta);
X return fcb.size;
X}
X
Xlong
Xall_files_size(path)
Xchar *path;
X{
X register int level;
X long size, tmp;
X char buf[PATHLEN];
X
X Strcpy(buf, path);
X for (level = 1, size = 0; level <= MAXLEVEL; level++) {
X name_file(buf, level);
X tmp = filesize(buf);
X if (tmp > 0)
X size += tmp;
X }
X return (size);
X}
X
Xvoid
Xcopybones(mode)
Xint mode;
X{
X register int fd, level;
X char from[PATHLEN], to[PATHLEN];
X long sizes[MAXLEVEL + 1];
X extern boolean level_exists[];
X if (!ramdisk)
X return;
X Strcpy(to, (mode == TOPERM) ? permbones : bones);
X Strcpy(from, (mode == TOPERM) ? bones : permbones);
X
X for (level = 1; level <= MAXLEVEL; level++) {
X name_file(from, level);
X sizes[level] = filesize(from); /* -1 if file doesn't exist */
X name_file(to, level);
X (void) unlink(to); /* remove old bones files in 'to' */
X }
X for (level = 1; level <= MAXLEVEL; level++) {
X if (sizes[level] == -1L)
X continue;
X name_file(from, level);
X name_file(to, level);
X if (sizes[level] > freediskspace(to)) {
X cprintf(
X "Not enough room to copy file '%s' to '%s'.\n",
X from, to);
X goto cleanup;
X }
X /* We use savelev and getlev to move the bones files around,
X * but savelev sets level_exists[] TRUE for this level, so
X * we have to set it back FALSE again.
X */
X#ifdef TOS
X if ((fd = open(from, 0x8000)) < 0) {
X#else TOS
X if ((fd = open(from, 0)) < 0) {
X#endif TOS
X cprintf( "Warning: can't open '%s'.\n", from);
X continue;
X } else {
X sizes[level] = 0; /* 'from' bones exists */
X getlev(fd, 0, level, FALSE);
X (void) close(fd);
X if ((fd = creat(to, FCMASK)) < 0) {
X cprintf(
X "Warning: can't create '%s'.\n", to);
X continue;
X } else {
X savelev(fd, level);
X (void) close(fd);
X level_exists[level] = FALSE; /* see above */
X }
X }
X }
X /* If we are copying bones files back to permanent storage, unlink
X * the bones files in the LEVELS directory.
X */
X if (mode == TOPERM)
X for (level = 1; level <= MAXLEVEL; level++) {
X if (sizes[level] == -1)
X continue;
X name_file(from, level);
X (void) unlink(from);
X }
X return;
X
Xcleanup:
X /* Ran out of disk space! Unlink the "to" files and issue an
X * appropriate message.
X */
X for (level = 1; level <= MAXLEVEL; level++)
X if (sizes[level] == 0) {
X name_file(to, level);
X (void) unlink(to);
X }
X cprintf( "There is not enough room in ");
X if (mode == TOPERM) {
X cprintf( "permanent storage for bones files!\n");
X cprintf("Bones will be left in LEVELS directory '%s'!\n",
X levels[0] ? levels : ".");
X return;
X } else {
X cprintf("LEVELS directory '%s' to copy bones files!\n",
X levels[0] ? levels : ".");
X getreturn("to quit");
X settty("Be seeing you...\n");
X exit(0);
X }
X}
X
XsaveDiskPrompt(start)
Xint start;
X{
X extern saveprompt;
X char buf[BUFSIZ];
X int i;
X
X if (saveprompt) {
X remember_topl();
X home();
X cl_end();
X Printf("If save file is on a SAVE disk, put that disk in now.\n");
X cl_end();
X Printf("Name of save file (default: '%s'%s) ? ", SAVEF,
X start ? "" : ", <Esc> aborts save");
X (void) fflush(stdout);
X getlin(buf);
X if (!start && buf[0] == '\033') {
X home();
X cl_end();
X curs(1, 2);
X cl_end();
X return 0;
X }
X for (i = 0; buf[i]; i++)
X if (!isspace(buf[i])) {
X strncpy(SAVEF, buf, PATHLEN);
X break;
X }
X }
X return 1;
X}
X
X/* Prompt for the game disk, then check if you can access the record file.
X * If not, warn the player.
X */
Xvoid
XgameDiskPrompt()
X{
X FILE *fp;
X extern saveprompt;
X
X if (saveprompt) {
X putch('\n');
X getreturn("when the GAME disk is ready");
X }
X if ((fp = fopen(RECORD, "r"))) /* check for GAME disk */
X (void) fclose(fp);
X else {
X cprintf("\n\nWARNING: I can't find record file '%s'!\n",
X RECORD);
X cprintf("If the GAME disk is not in, put it in now.\n");
X getreturn("to continue");
X }
X}
X
X#define CONFIGFILE "hack103.cnf"
Xvoid
Xread_config_file()
X{
X char config[FILENAME], tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
X char buf[BUFSZ], *bufp;
X FILE *fp;
X extern char plname[];
X extern int saveprompt;
X
X tmp_ramdisk[0] = 0;
X tmp_levels[0] = 0;
X Strcpy(config, hackdir);
X append_slash(config);
X Strcat(config, CONFIGFILE);
X if (!(fp = fopen(config, "r"))) {
X cprintf("Warning: no configuration file '%s'!\n",
X config);
X getreturn("to continue");
X return;
X }
X while (fgets(buf, BUFSZ, fp)) {
X if (*buf == '#') /* comment first character */
X continue;
X
X /* remove any 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 '=' separating option name from option value
X */
X if (!(bufp = strchr(buf, '='))) {
X cprintf("Bad option line: '%s'\n", buf);
X getreturn("to continue");
X continue;
X }
X
X /* move past whitespace between '=' and option value
X */
X while (isspace(*++bufp))
X ;
X
X /* Now go through the possible configurations
X */
X if (!strncmp(buf, "RAMDISK", 3)) {
X strncpy(tmp_ramdisk, bufp, PATHLEN);
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 char *ptr;
X if (ptr = index(bufp, ';')) {
X *ptr = '\0';
X if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
X saveprompt = FALSE;
X }
X (void) strncpy(SAVEF, bufp, PATHLEN);
X append_slash(SAVEF);
X
X } else if (!strncmp(buf, "GRAPHICS", 4)) {
X unsigned int translate[MAXPCHARS];
X int i;
X
X if ((i = 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",
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])) < 0) {
X cprintf("Syntax error in GRAPHICS\n");
X getreturn("to continue");
X }
X#define SETPCHAR(f, n) showsyms.f = (i > n) ? translate[n] : defsyms.f
X SETPCHAR(stone, 0);
X SETPCHAR(vwall, 1);
X SETPCHAR(hwall, 2);
X SETPCHAR(tlcorn, 3);
X SETPCHAR(trcorn, 4);
X SETPCHAR(blcorn, 5);
X SETPCHAR(brcorn, 6);
X SETPCHAR(crwall, 7);
X SETPCHAR(tuwall, 8);
X SETPCHAR(tdwall, 9);
X SETPCHAR(tlwall, 10);
X SETPCHAR(trwall, 11);
X SETPCHAR(vbeam, 12);
X SETPCHAR(hbeam, 13);
X SETPCHAR(lslant, 14);
X SETPCHAR(rslant, 15);
X SETPCHAR(door, 16);
X SETPCHAR(room, 17);
X SETPCHAR(corr, 18);
X SETPCHAR(upstair, 19);
X SETPCHAR(dnstair, 20);
X SETPCHAR(trap, 21);
X SETPCHAR(web, 22);
X SETPCHAR(pool, 23);
X#ifdef FOUNTAINS
X SETPCHAR(fountain, 24);
X#endif
X#ifdef SINKS
X SETPCHAR(sink, 25);
X#endif
X#ifdef THRONES
X SETPCHAR(throne, 26);
X#endif
X#ifdef ALTARS
X SETPCHAR(altar, 27);
X#endif
X#ifdef STRONGHOLD
X SETPCHAR(upladder, 28);
X SETPCHAR(dnladder, 29);
X SETPCHAR(dbvwall, 30);
X SETPCHAR(dbhwall, 31);
X#endif
X#undef SETPCHAR
X } else {
X cprintf("Bad option line: '%s'\n", buf);
X getreturn("to continue");
X }
X }
X (void) fclose(fp);
X
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 Strcpy(levels, tmp_levels);
X Strcpy(bones, levels);
X}
X
Xvoid
Xset_lock_and_bones()
X{
X if (!ramdisk) {
X Strcpy(levels, permbones);
X Strcpy(bones, permbones);
X }
X append_slash(bones);
X Strcat(bones, BONES);
X append_slash(permbones);
X Strcat(permbones, BONES);
X Strcpy(lock, levels);
X append_slash(lock);
X Strcat(lock, LEVELS);
X}
X
Xvoid
Xappend_slash(name)
Xchar *name;
X{
X char *ptr;
X
X if (!name[0])
X return;
X ptr = name + (strlen(name) - 1);
X if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
X *(ptr + 1) = '\\';
X *(ptr + 2) = 0;
X }
X}
X
X
Xcheck_then_creat(file, pmode)
Xchar *file;
Xint pmode;
X{
X long freespace = freediskspace(file);
X extern boolean restoring;
X if (freespace < 0)
X return (-1);
X if (!restoring && freespace < 8000L) {
X pline("\7NetHack is almost out of disk space for making levels!");
X pline("You should save the game now. Save this game?");
X (void) fflush(stdout);
X if (yn() == 'y')
X dosave();
X return(-1); /* In case he decides not to save don't let him
X * change levels
X */
X }
X return( creat(file, pmode));
X}
X
Xvoid
Xgetreturn(str)
Xchar *str;
X{
X int ch;
X
X cprintf("Hit <RETURN> %s.", str);
X while ((ch = Getchar()) != '\n')
X putch(ch);
X}
X
Xvoid
Xchdrive(str)
Xchar *str;
X{
X int drive;
X char *ptr;
X if ((ptr = index(str, ':')) != NULL) {
X drive = toupper(*(ptr - 1))-'A';
X Dsetdrv(drive);
X }
X}
X
X
X/* Do a chdir back to the original directory
X */
Xvoid msexit(code)
Xint code;
X{
X#ifdef CHDIR
X extern char orgdir[];
X#endif CHDIR
X
X#ifdef DGK
X (void) fflush(stdout);
X copybones(TOPERM);
X#endif DGK
X#ifdef CHDIR
X Dsetpath(orgdir); /* do the chdir, but not with chdirx */
X#endif CHDIR
X exit(code);
X}
X
X/*qsort: sort an array. Really a shell sort, but it will do*/
Xvoid qsort(base,nel,size,compar)
Xchar *base;
Xint nel, size;
Xint (*compar) ();
X{
X int gap, i, j;
X register int cnt;
X for (gap=nel>>1; gap>0; gap>>=1)
X for (i=gap; i<nel; i++)
X for (j=i-gap; j>=0; j-=gap) {
X register char *s1, *s2;
X s1=base+(j*size);
X s2=base+((j+gap)*size);
X if ((*compar)(s1,s2)<=0) break;
X for (cnt=size;--cnt>=0;) {
X register char ch;
X ch = *s1;
X *s1++ = *s2;
X *s2++ = ch;
X }
X }
X/*end qsort*/}
X
Xstatic char *msgs[]={" ",
X "not file owner",
X "no such file or directory",
X "no such process",
X "interrupted system call",
X "I/O error",
X "no such device",
X "argument list too long",
X "exec format error",
X "bad file number",
X "no child process",
X "no more processes allowed",
X "not enough memory space",
X "permission denied",
X "bad memory address",
X "bulk device required",
X "resource is busy",
X "file exists",
X "cross device link",
X "no such device",
X "not a directory",
X "is a directory",
X "invalid argument",
X "no more files allowed",
X "too many open files",
X "not a terminal",
X "text file busy",
X "file too large",
X "no space left on device",
X "illegal seek",
X "read only file system",
X "too many links",
X "broken pipe",
X "math argument error",
X "math result too large"};
X
X/*perror: print a string, then the error*/
Xvoid perror(s)
Xchar *s;
X{
X int select;
X if ((errno<0) || (errno>34)) select=0;
X else select=errno;
X cprintf("%s: %s\n",s,msgs[select]);
X/*end perror*/}
X
Xsetrandom()
X{
X Srand(Tgettime());
X/*end setrandom*/}
X
Xgetyear()
X{
X return (1980+((Tgetdate()>>9)&0x7f));
X/*end getyear*/}
X
Xchar *getdate()
X{
X static char datestr[7];
X int day, mo, yr, date;
X date=Tgetdate();
X day=date&0x1f;
X mo=(date>>5)&0xf;
X yr=getyear()-1900;
X Sprintf(datestr,"%2d%2d%2d",yr,mo,day);
X if (datestr[2]==' ') datestr[2]='0';
X if (datestr[4]==' ') datestr[4]='0';
X return (datestr);
X/*getdate*/}
Xstatic int cum[]={0,0,31,59,90,120,151,181,212,243,273,304,334};
X
Xphase_of_the_moon()
X{
X int day,mo,epact,golden,date;
X date=Tgetdate();
X day=date&0x1f;
X mo=(date>>5)&0xf;
X day+=cum[mo];
X if (((getyear() % 4)==0) && (mo>2)) day++;
X golden=(getyear()%19)+1;
X epact=(11*golden+18) % 30;
X if ((epact==25 && golden>11) || (epact==24)) epact++;
X return( (((((day+epact)*6)+11)%177)/22)&7);
X/*end phase_of_the_moon*/}
X
Xnight()
X{
X int hour;
X hour=(Tgettime()>>11)&0x1f;
X return ((hour<6) || (hour>21));
X/*end night*/}
X
Xmidnight()
X{
X int hour;
X hour=(Tgettime()>>11)&0x1f;
X return (hour==0);
X/*end midnight*/}
X
Xgethdate(name) char *name;
X{
X/*end gethdate*/}
X
Xuptodate(fd)
X{
X return(1);
X/*end uptodate*/}
X
Xgetlock()
X{
X/*end getlock*/}
X
Xgetenv(s)
Xchar *s;
X{
X return(0);
X/*end getenv*/}
X
X/*getcwd: return the current directory*/
Xchar *getcwd(path,len)
Xchar *path;
Xint len;
X{
X if (Dgetpath(path,0)<0) return (NULL);
X else return(path);
X/*end getcwd*/}
X
X/*chdir: change directories*/
Xchdir(path)
Xchar *path;
X{
X if (*path) return (Dsetpath(path));
X else return 0;
X/*end chdir*/}
X
X/*Lattice's strncpy always appends a null*/
Xint strncpy(to,from,len)
Xchar *to,*from;
Xint len;
X{ int result;
X result=len;
X while (*from && len) {*to++ = *from++; --len;}
X if (len) {*to='\0'; --len;}
X return result-len;
X/*end strncpy*/}
X
X#ifdef DEBUG
Xprinter(s)
Xchar *s;
X{
X while (*s) Cprnout(*s++);
X/*end printer*/}
X#endif DEBUG
END_OF_FILE
if test 16197 -ne `wc -c <'others/tos.c'`; then
echo shar: \"'others/tos.c'\" unpacked with wrong size!
fi
# end of 'others/tos.c'
fi
echo shar: End of archive 22 \(of 38\).
cp /dev/null ark22isdone
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 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 38 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