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