[comp.sources.games] v02i007: nethack - display oriented dungeons & dragons, Part07/16

games-request@tekred.TEK.COM (07/28/87)

Submitted by: mike@genat.UUCP (Mike Stephenson)
Comp.sources.games: Volume 2, Issue 7
Archive-name: nethack/Part07



#! /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 7 (of 16)."
# Contents:  msdos.c objnam.c potion.c unixunix.c
# Wrapped by billr@tekred on Tue Jul 28 09:49:32 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f msdos.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"msdos.c\"
else
echo shar: Extracting \"msdos.c\" \(13705 characters\)
sed "s/^X//" >msdos.c <<'END_OF_msdos.c'
X/*	SCCS Id: @(#)msdos.c	1.3	87/07/14
X/* An assortment of MSDOS functions.
X */
X
X#include <stdio.h>
X#include "hack.h"
X
X#ifdef MSDOS
X# include <dos.h>
X
Xvoid
Xflushout()
X{
X	(void) fflush(stdout);
X}
X
Xgetuid() {
X	return 1;
X}
X
Xchar *
Xgetlogin() {
X	return ((char *) NULL);
X}
X
Xtgetch() {
X	char ch, popch();
X	static char DOSgetch(), BIOSgetch();
X
X	if (!(ch = popch())) {
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	}
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(&regs, &regs);
X	if (!regs.h.al) {	/* an extended code -- not yet supported */
X		regs.h.ah = DIRECT_INPUT;
X		intdos(&regs, &regs);	/* eat the next character */
X		regs.h.al = 0;		/* and return a 0 */
X	}
X	return (regs.h.al);
X}
X
X
X# ifdef DGK
X#  include <ctype.h>
X#  include <fcntl.h>
X
X#  define Sprintf (void) sprintf
X#  define WARN 1
X#  define NOWARN 0
X
Xstatic char *
Xgetcomspec(warn) {
X	return getenv("COMSPEC");
X}
X
X#  ifdef SHELL
X#   include <process.h>
Xdosh() {
X	extern char orgdir[];
X	char *comspec;
X
X	if (comspec = getcomspec()) {
X		settty("To return to HACK, type \"exit\" at the DOS prompt.\n");
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("No COMSPEC !?  Can't exec COMMAND.COM");
X	return(0);
X}
X#  endif /* SHELL */
X
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 iskeypad(x)	(KEYPADLOW <= (x) && (x) <= KEYPADHI)
Xstatic struct {
X	char normal, shift;
X	} keypad[KEYPADHI - KEYPADLOW + 1] = {
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};
X
X/* BIOSgetch gets keys directly with a BIOS call.
X */
X#  define SHIFT		(0x1 | 0x2)
X#  define KEYBRD_BIOS	0x16
X
Xstatic char
XBIOSgetch() {
X	unsigned char scan, shift, ch;
X	union REGS regs;
X
X	/* Get scan code.
X	 */
X	regs.h.ah = 0;
X	int86(KEYBRD_BIOS, &regs, &regs);
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, &regs, &regs);
X	shift = regs.h.al;
X
X	/* If scan code is for the keypad, translate it.
X	 */
X	if (iskeypad(scan)) {
X		if (shift & SHIFT)
X			ch = keypad[scan - KEYPADLOW].shift;
X		else
X			ch = keypad[scan - KEYPADLOW].normal;
X	}
X	return ch;
X}
X
X/* construct the string  file.level */
Xvoid
Xname_file(file, level)
Xchar *file;
Xint level;
X{
X	char *tf;
X	
X	if (tf = rindex(file, '.'))
X		Sprintf(tf+1, "%d", level);
X}
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
Xstatic char
Xswitchar()
X{
X	union REGS regs;
X
X	regs.x.ax = GETSWITCHAR;
X	intdos(&regs, &regs);
X	return regs.h.dl;
X}
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(&regs, &regs);
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
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(&regs, &regs, &sregs);
X	return !regs.x.cflag;
X}
X
Xstatic
Xfindnext() {
X	union REGS regs;
X
X	regs.x.ax = FINDNEXT;
X	intdos(&regs, &regs);
X	return !regs.x.cflag;
X}
X
X/* Get disk transfer area */
Xstatic char *
Xgetdta() {
X	union REGS regs;
X	struct SREGS sregs;
X	char *ret;
X
X	regs.x.ax = GETDTA;
X	intdosx(&regs, &regs, &sregs);
X	FP_OFF(ret) = regs.x.bx;
X	FP_SEG(ret) = sregs.es;
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 *getdta(), *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}
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		return;
X	} else {
X		/* Remove all bones files on the RAMdisk */
X		eraseall(levels, allbones);
X		playwoRAMdisk();
X	}
X}
X
XplaywoRAMdisk() {
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
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
Xrecord_exists() {
X	int fd;
X
X	if ((fd = open(RECORD, 0)) >= 0) {
X		close(fd);
X		return TRUE;
X	}
X	return FALSE;
X}
X
X/* Return 1 if the comspec was found */
Xstatic
Xcomspec_exists() {
X	int fd;
X	char *comspec;
X
X	if (comspec = getcomspec())
X		if ((fd = open(comspec, 0)) >= 0) {
X			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 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}
X
X/* Read configuration */
Xvoid
Xread_config_file() {
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 = 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		} 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, 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			struct symbols s;
X
X			if (sscanf(bufp, "%u%u%u%u%u%u%u%u%u", &s.vwall,
X				    &s.hwall, &s.tlcorn, &s.trcorn, &s.blcorn,
X				    &s.brcorn, &s.door, &s.room, &s.corr) == 9)
X				symbol = s;
X			else {
X				msmsg("GRAPHICS did not contain 9 values\n");
X				getreturn("to continue");
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	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/* 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}
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	flushout();
X}
X
X/* Chdrive() changes the default drive.
X */
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}
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	old_stdin, old_stdout, ioctl();
X
Xdisable_ctrlP() {
X	if (!flags.rawio)
X		return;
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}
X
Xenable_ctrlP() {
X	if (!flags.rawio)
X		return;
X	if (old_stdin)
X		(void) ioctl(STDIN, SETBITS, old_stdin);
X	if (old_stdout)
X		(void) ioctl(STDOUT, SETBITS, old_stdout);
X}
X
Xstatic unsigned
Xioctl(handle, mode, setvalue)
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(&regs, &regs);
X	return (regs.x.dx);
X}
X
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, *getenv(), 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 NULL;
X}
X# endif /* DGK */
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	flushout();
X	enable_ctrlP();		/* in case this wasn't done */
X	if (ramdisk)
X		copybones(TOPERM);
X# endif
X# ifdef CHDIR
X	chdir(orgdir);		/* chdir, not chdirx */
X#  ifdef DGK
X	chdrive(orgdir);
X#  endif
X# endif
X	exit(code);
X}
X#endif /* MSDOS */
END_OF_msdos.c
if test 13705 -ne `wc -c <msdos.c`; then
    echo shar: \"msdos.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f objnam.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"objnam.c\"
else
echo shar: Extracting \"objnam.c\" \(13414 characters\)
sed "s/^X//" >objnam.c <<'END_OF_objnam.c'
X/*	SCCS Id: @(#)objnam.c	1.3	87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* objnam.c - version 1.0.2 */
X
X#include	"hack.h"
X#define Sprintf (void) sprintf
X#define Strcat  (void) strcat
X#define	Strcpy	(void) strcpy
X#define	PREFIX	15
Xextern char *eos();
Xextern int bases[];
X
Xchar *
Xstrprepend(s,pref) register char *s, *pref; {
Xregister int i = strlen(pref);
X	if(i > PREFIX) {
X		pline("WARNING: prefix too short.");
X		return(s);
X	}
X	s -= i;
X	(void) strncpy(s, pref, i);	/* do not copy trailing 0 */
X	return(s);
X}
X
Xchar *
Xsitoa(a) int a; {
Xstatic char buf[13];
X	Sprintf(buf, (a < 0) ? "%d" : "+%d", a);
X	return(buf);
X}
X
Xchar *
Xtypename(otyp)
Xregister int otyp;
X{
Xstatic char buf[BUFSZ];
Xregister struct objclass *ocl = &objects[otyp];
Xregister char *an = ocl->oc_name;
Xregister char *dn = ocl->oc_descr;
Xregister char *un = ocl->oc_uname;
Xregister int nn = ocl->oc_name_known;
X	switch(ocl->oc_olet) {
X	case POTION_SYM:
X		Strcpy(buf, "potion");
X		break;
X	case SCROLL_SYM:
X		Strcpy(buf, "scroll");
X		break;
X	case WAND_SYM:
X		Strcpy(buf, "wand");
X		break;
X#ifdef SPELLS
X	case SPBOOK_SYM:
X		Strcpy(buf, "spellbook");
X		break;
X#endif
X	case RING_SYM:
X		Strcpy(buf, "ring");
X		break;
X	default:
X		if(nn) {
X			Strcpy(buf, an);
X			if(otyp >= TURQUOISE && otyp <= JADE)
X				Strcat(buf, " stone");
X			if(un)
X				Sprintf(eos(buf), " called %s", un);
X			if(dn)
X				Sprintf(eos(buf), " (%s)", dn);
X		} else {
X			Strcpy(buf, dn ? dn : an);
X			if(ocl->oc_olet == GEM_SYM)
X				Strcat(buf, " gem");
X			if(un)
X				Sprintf(eos(buf), " called %s", un);
X		}
X		return(buf);
X	}
X	/* here for ring/scroll/potion/wand */
X	if(nn)
X		Sprintf(eos(buf), " of %s", an);
X	if(un)
X		Sprintf(eos(buf), " called %s", un);
X	if(dn)
X		Sprintf(eos(buf), " (%s)", dn);
X	return(buf);
X}
X
Xchar *
Xxname(obj)
Xregister struct obj *obj;
X{
Xstatic char bufr[BUFSZ];
Xregister char *buf = &(bufr[PREFIX]);	/* leave room for "17 -3 " */
Xregister int nn = objects[obj->otyp].oc_name_known;
Xregister char *an = objects[obj->otyp].oc_name;
Xregister char *dn = objects[obj->otyp].oc_descr;
Xregister char *un = objects[obj->otyp].oc_uname;
Xregister int pl = (obj->quan != 1);
X#ifdef KAA
X	if(!obj->dknown && !Blind && obj->olet != WEAPON_SYM) obj->dknown=1;
X#else
X	if(!obj->dknown && !Blind) obj->dknown = 1; /* %% doesnt belong here */
X#endif
X	switch(obj->olet) {
X	case AMULET_SYM:
X		Strcpy(buf, (obj->spe < 0 && obj->known)
X			? "cheap plastic imitation of the " : "");
X		Strcat(buf,"Amulet of Yendor");
X		break;
X	case TOOL_SYM:
X		if(!nn) {
X			Strcpy(buf, dn);
X			break;
X		}
X		Strcpy(buf,an);
X		break;
X	case FOOD_SYM:
X		if(obj->otyp == DEAD_HOMUNCULUS && pl) {
X			pl = 0;
X			Strcpy(buf, "dead homunculi");
X			break;
X		}
X		/* fungis ? */
X#ifdef KAA /* The fungus mistake was a D&D holdover. */
X		if(obj->otyp == DEAD_VIOLET_FUNGUS && pl) {
X			pl = 0;
X			Strcpy(buf, "dead violet fungi");
X			break;
X		}
X#endif
X		/* fall into next case */
X	case WEAPON_SYM:
X		if(obj->otyp == WORM_TOOTH && pl) {
X			pl = 0;
X			Strcpy(buf, "worm teeth");
X			break;
X		}
X		if(obj->otyp == CRYSKNIFE && pl) {
X			pl = 0;
X			Strcpy(buf, "crysknives");
X			break;
X		}
X		/* fall into next case */
X	case ARMOR_SYM:
X	case CHAIN_SYM:
X	case ROCK_SYM:
X		Strcpy(buf,an);
X		break;
X	case BALL_SYM:
X		Sprintf(buf, "%sheavy iron ball",
X		  (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
X		break;
X	case POTION_SYM:
X		if(nn || un || !obj->dknown) {
X			Strcpy(buf, "potion");
X			if(pl) {
X				pl = 0;
X				Strcat(buf, "s");
X			}
X			if(!obj->dknown) break;
X			if(un) {
X				Strcat(buf, " called ");
X				Strcat(buf, un);
X			} else {
X				Strcat(buf, " of ");
X				Strcat(buf, an);
X			}
X		} else {
X			Strcpy(buf, dn);
X			Strcat(buf, " potion");
X		}
X		break;
X	case SCROLL_SYM:
X		Strcpy(buf, "scroll");
X		if(pl) {
X			pl = 0;
X			Strcat(buf, "s");
X		}
X		if(!obj->dknown) break;
X		if(nn) {
X			Strcat(buf, " of ");
X			Strcat(buf, an);
X		} else if(un) {
X			Strcat(buf, " called ");
X			Strcat(buf, un);
X		} else {
X			Strcat(buf, " labeled ");
X			Strcat(buf, dn);
X		}
X		break;
X	case WAND_SYM:
X		if(!obj->dknown)
X			Sprintf(buf, "wand");
X		else if(nn)
X			Sprintf(buf, "wand of %s", an);
X		else if(un)
X			Sprintf(buf, "wand called %s", un);
X		else
X			Sprintf(buf, "%s wand", dn);
X		break;
X#ifdef SPELLS
X	case SPBOOK_SYM:
X		if(!obj->dknown)
X			Sprintf(buf, "spellbook");
X		else if(nn)
X			Sprintf(buf, "spellbook of %s", an);
X		else if(un)
X			Sprintf(buf, "spellbook called %s", un);
X		else
X			Sprintf(buf, "%s spellbook", dn);
X		break;
X#endif
X	case RING_SYM:
X		if(!obj->dknown)
X			Sprintf(buf, "ring");
X		else if(nn)
X			Sprintf(buf, "ring of %s", an);
X		else if(un)
X			Sprintf(buf, "ring called %s", un);
X		else
X			Sprintf(buf, "%s ring", dn);
X		break;
X	case GEM_SYM:
X		if(!obj->dknown) {
X			Strcpy(buf, "gem");
X			break;
X		}
X		if(!nn) {
X#ifdef KAA
X			if(un) {
X				if (!pl)  Sprintf(buf,"gem called %s",un);
X				else	  Sprintf(buf,"gems called %s",un);
X				pl=0;
X			} else
X#endif
X				Sprintf(buf, "%s gem", dn);
X			break;
X		}
X		Strcpy(buf, an);
X		if(obj->otyp >= TURQUOISE && obj->otyp <= JADE)
X			Strcat(buf, " stone");
X		break;
X	default:
X		Sprintf(buf,"glorkum %c (0%o) %u %d",
X			obj->olet,obj->olet,obj->otyp,obj->spe);
X	}
X	if(pl) {
X		register char *p;
X
X		for(p = buf; *p; p++) {
X			if(!strncmp(" of ", p, 4)) {
X				/* pieces of, cloves of, lumps of */
X				register int c1, c2 = 's';
X
X				do {
X					c1 = c2; c2 = *p; *p++ = c1;
X				} while(c1);
X				goto nopl;
X			}
X		}
X		p = eos(buf)-1;
X		if(*p == 's' || *p == 'z' || *p == 'x' ||
X		    (*p == 'h' && p[-1] == 's'))
X			Strcat(buf, "es");	/* boxes */
X		else if(*p == 'y' && !index(vowels, p[-1]))
X			Strcpy(p, "ies");	/* rubies, zruties */
X		else
X			Strcat(buf, "s");
X	}
Xnopl:
X	if(obj->onamelth) {
X		Strcat(buf, " named ");
X		Strcat(buf, ONAME(obj));
X	}
X	return(buf);
X}
X
Xchar *
Xdoname(obj)
Xregister struct obj *obj;
X{
Xchar prefix[PREFIX];
Xregister char *bp = xname(obj);
X	if(obj->quan != 1)
X		Sprintf(prefix, "%u ", obj->quan);
X	else
X		Strcpy(prefix, "a ");
X	switch(obj->olet) {
X	case AMULET_SYM:
X		if(strncmp(bp, "cheap ", 6))
X			Strcpy(prefix, "the ");
X		break;
X	case ARMOR_SYM:
X		if(obj->owornmask & W_ARMOR)
X			Strcat(bp, " (being worn)");
X		/* fall into next case */
X	case WEAPON_SYM:
X		if(obj->known) {
X#ifdef KAA
X			/* dknown is special for weapons */
X			if(obj->dknown && obj->olet == WEAPON_SYM)
X				Strcat(prefix,"blessed ");
X#endif
X			Strcat(prefix, sitoa(obj->spe));
X			Strcat(prefix, " ");
X		}
X		break;
X#ifdef MARKER
X	case TOOL_SYM:			/* temp. hack by GAN 11/18/86 */
X		if(obj->otyp != MAGIC_MARKER) break;
X#endif
X	case WAND_SYM:
X		if(obj->known)
X			Sprintf(eos(bp), " (%d)", obj->spe);
X		break;
X	case RING_SYM:
X		if(obj->owornmask & W_RINGR) Strcat(bp, " (on right hand)");
X		if(obj->owornmask & W_RINGL) Strcat(bp, " (on left hand)");
X		if(obj->known && (objects[obj->otyp].bits & SPEC)) {
X			Strcat(prefix, sitoa(obj->spe));
X			Strcat(prefix, " ");
X		}
X		break;
X	}
X	if(obj->owornmask & W_WEP)
X		Strcat(bp, " (weapon in hand)");
X	if(obj->unpaid)
X		Strcat(bp, " (unpaid)");
X	if(!strcmp(prefix, "a ") && index(vowels, *bp))
X		Strcpy(prefix, "an ");
X	bp = strprepend(bp, prefix);
X	return(bp);
X}
X
X/* used only in fight.c (thitu) */
Xsetan(str,buf)
Xregister char *str,*buf;
X{
X	if(index(vowels,*str))
X		Sprintf(buf, "an %s", str);
X	else
X		Sprintf(buf, "a %s", str);
X}
X
Xchar *
Xaobjnam(otmp,verb) register struct obj *otmp; register char *verb; {
Xregister char *bp = xname(otmp);
Xchar prefix[PREFIX];
X	if(otmp->quan != 1) {
X		Sprintf(prefix, "%u ", otmp->quan);
X		bp = strprepend(bp, prefix);
X	}
X
X	if(verb) {
X		/* verb is given in plural (i.e., without trailing s) */
X		Strcat(bp, " ");
X		if(otmp->quan != 1)
X			Strcat(bp, verb);
X		else if(!strcmp(verb, "are"))
X			Strcat(bp, "is");
X		else {
X			Strcat(bp, verb);
X			Strcat(bp, "s");
X		}
X	}
X	return(bp);
X}
X
Xchar *
XDoname(obj)
Xregister struct obj *obj;
X{
X	register char *s = doname(obj);
X
X	if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
X	return(s);
X}
X
Xchar *wrp[] = {	"wand", "ring", "potion", "scroll", "gem"
X#ifdef SPELLS
X		, "spellbook"
X#endif
X	      };
Xchar wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM
X#ifdef SPELLS
X		  , SPBOOK_SYM
X#endif
X		};
X
Xstruct obj *
Xreadobjnam(bp) register char *bp; {
Xregister char *p;
Xregister int i;
Xint cnt, spe, spesgn, typ, heavy;
Xchar let;
Xchar *un, *dn, *an;
X#ifdef KAA
Xint blessed=0;
X#endif
X/* int the = 0; char *oname = 0; */
X	cnt = spe = spesgn = typ = heavy = 0;
X	let = 0;
X	an = dn = un = 0;
X	for(p = bp; *p; p++)	/* set the string to lower case */
X		if('A' <= *p && *p <= 'Z') *p += 'a'-'A';
X	if(!strncmp(bp, "the ", 4)){
X/*		the = 1; */
X		bp += 4;
X	} else if(!strncmp(bp, "an ", 3)){
X		cnt = 1;
X		bp += 3;
X	} else if(!strncmp(bp, "a ", 2)){
X		cnt = 1;
X		bp += 2;
X	}
X#ifdef KAA
X	if(!strncmp(bp,"blessed ",8)) {
X		blessed=1;
X		bp += 8;
X	}
X#endif
X	if(!cnt && digit(*bp)){
X		cnt = atoi(bp);
X		while(digit(*bp)) bp++;
X		while(*bp == ' ') bp++;
X	}
X	if(!cnt) cnt = 1;		/* %% what with "gems" etc. ? */
X
X	if(*bp == '+' || *bp == '-'){
X		spesgn = (*bp++ == '+') ? 1 : -1;
X		spe = atoi(bp);
X		while(digit(*bp)) bp++;
X		while(*bp == ' ') bp++;
X	} else {
X		p = rindex(bp, '(');
X		if(p) {
X			if(p > bp && p[-1] == ' ') p[-1] = 0;
X			else *p = 0;
X			p++;
X			spe = atoi(p);
X			while(digit(*p)) p++;
X			if(strcmp(p, ")")) spe = 0;
X			else spesgn = 1;
X		}
X	}
X	/* now we have the actual name, as delivered by xname, say
X		green potions called whisky
X		scrolls labeled "QWERTY"
X		egg
X		dead zruties
X		fortune cookies
X		very heavy iron ball named hoei
X		wand of wishing
X		elven cloak
X	*/
X	for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) {
X		*p = 0;
X/*		oname = p+7; */
X	}
X	for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) {
X		*p = 0;
X		un = p+8;
X	}
X	for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) {
X		*p = 0;
X		dn = p+9;
X	}
X
X	/* first change to singular if necessary */
X	if(cnt != 1) {
X		/* find "cloves of garlic", "worthless pieces of blue glass" */
X		for(p = bp; *p; p++) if(!strncmp(p, "s of ", 5)){
X			while(*p = p[1]) p++;
X			goto sing;
X		}
X		/* remove -s or -es (boxes) or -ies (rubies, zruties) */
X		p = eos(bp);
X		if(p[-1] == 's') {
X			if(p[-2] == 'e') {
X				if(p[-3] == 'i') {
X#ifdef KAA
X					if(!strcmp(p-7, "cookies") || !strcmp(p-4, "pies"))
X#else
X					if(!strcmp(p-7, "cookies"))
X#endif
X						goto mins;
X					Strcpy(p-3, "y");
X					goto sing;
X				}
X
X				/* note: cloves / knives from clove / knife */
X				if(!strcmp(p-6, "knives")) {
X					Strcpy(p-3, "fe");
X					goto sing;
X				}
X
X				/* note: nurses, axes but boxes */
X				if(!strcmp(p-5, "boxes")) {
X					p[-2] = 0;
X					goto sing;
X				}
X			}
X		mins:
X			p[-1] = 0;
X		} else {
X			if(!strcmp(p-9, "homunculi")
X#ifdef KAA
X				|| !strcmp(p-5, "fungi")
X#endif
X							) {
X				Strcpy(p-1, "us"); /* !! makes string longer */
X				goto sing;
X			}
X			if(!strcmp(p-5, "teeth")) {
X				Strcpy(p-5, "tooth");
X				goto sing;
X			}
X			/* here we cannot find the plural suffix */
X		}
X	}
Xsing:
X	if(!strcmp(bp, "amulet of yendor")) {
X		typ = AMULET_OF_YENDOR;
X		goto typfnd;
X	}
X	if(!strcmp(bp, "ring mail")){	/* Note: ring mail is not a ring ! */
X		let = ARMOR_SYM;
X		an = bp;
X		goto srch;
X	}
X
X	p = eos(bp);
X#ifdef KOPS	/* kluge to re-capitalize "dead Kop" */
X	if (!strcmp(p-3, "kop")) {
X		*(p-3) = 'K';
X		an = bp;
X		goto srch;
X	}
X#endif
X
X	for(i = 0; i < sizeof(wrpsym); i++) {
X		register int j = strlen(wrp[i]);
X		if(!strncmp(bp, wrp[i], j)){
X			let = wrpsym[i];
X			bp += j;
X			if(!strncmp(bp, " of ", 4)) an = bp+4;
X			/* else if(*bp) ?? */
X			goto srch;
X		}
X		if(!strcmp(p-j, wrp[i])){
X			let = wrpsym[i];
X			p -= j;
X			*p = 0;
X			if(p[-1] == ' ') p[-1] = 0;
X			dn = bp;
X			goto srch;
X		}
X	}
X	if(!strcmp(p-6, " stone")){
X		p[-6] = 0;
X		let = GEM_SYM;
X		an = bp;
X		goto srch;
X	}
X#ifdef KAA
X	if(!strcmp(p-10, "gold piece") || !strcmp(p-7, "zorkmid")) {
X		if (cnt > 5000) cnt=5000;
X		if (cnt < 1) cnt=1;
X		pline("%d gold piece%s.", cnt, cnt==1 ? "" : "s");
X		u.ugold += cnt;
X		flags.botl=1;
X		return(0);
X	}
X#endif
X	if(!strcmp(bp, "very heavy iron ball")){
X		heavy = 1;
X		typ = HEAVY_IRON_BALL;
X		goto typfnd;
X	}
X	an = bp;
Xsrch:
X	if(!an && !dn && !un)
X		goto any;
X	i = 1;
X	if(let) i = bases[letindex(let)];
X	while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){
X		register char *zn = objects[i].oc_name;
X
X		if(!zn) goto nxti;
X		if(an && strcmp(an, zn))
X			goto nxti;
X		if(dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn)))
X			goto nxti;
X		if(un && (!(zn = objects[i].oc_uname) || strcmp(un, zn)))
X			goto nxti;
X		typ = i;
X		goto typfnd;
X	nxti:
X		i++;
X	}
Xany:
X	if(!let) let = wrpsym[rn2(sizeof(wrpsym))];
X	typ = probtype(let);
Xtypfnd:
X	{ register struct obj *otmp;
X	  extern struct obj *mksobj();
X	let = objects[typ].oc_olet;
X	otmp = mksobj(typ);
X	if(heavy)
X		otmp->owt += 15;
X	if(cnt > 0 && index("%?!*)", let) &&
X#ifdef KAA
X		(cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt <= 20)))
X#else
X		(cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20)))
X#endif
X		otmp->quan = cnt;
X
X	if(spe > 3 && spe > otmp->spe)
X		spe = 0;
X	else if(let == WAND_SYM)
X		spe = otmp->spe;
X#ifdef KAA
X	if(let==WEAPON_SYM && blessed) {
X		if(u.uluck < 0) otmp->cursed=1;
X		else otmp->dknown=1;
X	}
X#endif
X	if(spe == 3 && u.uluck < 0)
X		spesgn = -1;
X	if(let != WAND_SYM && spesgn == -1)
X		spe = -spe;
X	if(let == BALL_SYM)
X		spe = 0;
X	else if(let == AMULET_SYM)
X		spe = -1;
X	else if(typ == WAN_WISHING && rn2(10))
X		spe = (rn2(10) ? -1 : 0);
X#ifdef MARKER
X	else if(typ == MAGIC_MARKER)
X		spe = rn1(50,50);
X#endif
X	otmp->spe = spe;
X
X	if(spesgn == -1)
X		otmp->cursed = 1;
X
X	return(otmp);
X    }
X}
END_OF_objnam.c
if test 13414 -ne `wc -c <objnam.c`; then
    echo shar: \"objnam.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f potion.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"potion.c\"
else
echo shar: Extracting \"potion.c\" \(13424 characters\)
sed "s/^X//" >potion.c <<'END_OF_potion.c'
X/*	SCCS Id: @(#)potion.c	1.3	87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* potion.c - version 1.0.3 */
X
X#include "hack.h"
Xextern int float_down();
Xextern char *nomovemsg;
Xextern struct monst youmonst;
Xextern struct monst *makemon();
Xchar *hcolor();
X#ifdef KAA
Xchar *xname();
Xextern char pl_character[];
X#endif
X#ifdef FOUNTAINS
Xextern int drinkfountain();
Xextern int dipfountain();
X#endif
X
Xint	nothing, unkn;
X
Xdodrink() {
X	register struct obj *otmp;
X	register int	retval;
X
X#ifdef FOUNTAINS
X
X      /* Is there something to drink here, i.e., a fountain? */
X       if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
X	  pline("Drink from the fountain? [ny] ");
X	  if(readchar() == 'y') {
X	    (void) drinkfountain();
X	    return(0);
X	  }
X       }   
X
X#endif /* FOUNTAINS /**/
X
X	nothing = unkn = 0;
X	otmp = getobj("!", "drink");
X	if(!otmp) return(0);
X	if(!strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) {
X		ghost_from_bottle();
X		goto use_it;
X	}
X	if((retval = peffects(otmp)) >= 0) return(retval);
X
X	if(nothing) {
X	    unkn++;
X	    pline("You have a %s feeling for a moment, then it passes.",
X		  Hallucination ? "normal" : "peculiar");
X	}
X	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
X		if(!unkn) {
X			objects[otmp->otyp].oc_name_known = 1;
X			more_experienced(0,10);
X		} else if(!objects[otmp->otyp].oc_uname)
X			docall(otmp);
X	}
Xuse_it:
X	useup(otmp);
X	return(1);
X}
X
Xpeffects(otmp)
X	register struct obj	*otmp;
X{
X	register struct obj	*objs;
X	register struct monst	*mtmp;
X
X	switch(otmp->otyp){
X	case POT_RESTORE_STRENGTH:
X#ifdef SPELLS
X	case SPE_RESTORE_STRENGTH:
X#endif
X		unkn++;
X		pline("Wow!  This makes you feel great!");
X		if(u.ustr < u.ustrmax) {
X			u.ustr = u.ustrmax;
X			flags.botl = 1;
X		}
X		break;
X#ifdef KAA
X	case POT_HALLUCINATION:
X		if (Hallucination) nothing++;
X		else pline("Oh wow!  Everything looks so cosmic!");
X		Hallucination += rn1(100,750);
X		setsee();
X		break;
X	case POT_HOLY_WATER:
X		unkn++;
X		if(index("VWZ&",u.usym)) {
X			pline("This burns like acid!");
X			losehp(d(2,6)); /* will never kill you */
X		} else {
X			pline("You feel full of awe.");
X			if (Sick) Sick=0;
X			if (HConfusion) HConfusion=0;
X		}
X#else
X	case POT_HOLY_WATER:
X	case POT_HALLUCINATION:
X#endif
X		break;
X	case POT_BOOZE:
X		unkn++;
X		pline("Ooph!  This tastes like liquid fire!");
X		HConfusion += d(3,8);
X		/* the whiskey makes us feel better */
X		if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey");
X		if(!rn2(4)) {
X			pline("You pass out.");
X			multi = -rnd(15);
X			nomovemsg = "You awake with a headache.";
X		}
X		break;
X	case POT_INVISIBILITY:
X#ifdef SPELLS
X	case SPE_INVISIBILITY:
X#endif
X		if(Invis || See_invisible)
X		  nothing++;
X		else {
X		  if(!Blind)
X		    pline("Gee!  All of a sudden, you can't see yourself.");
X		  else
X		    pline("You feel rather airy."), unkn++;
X		  newsym(u.ux,u.uy);
X		}
X		HInvis += rn1(15,31);
X		break;
X	case POT_FRUIT_JUICE:
X		pline("This tastes like fruit juice.");
X		lesshungry(20);
X		break;
X	case POT_HEALING:
X		pline("You begin to feel better.");
X		healup(rnd(10), 1, 1, 1);
X		break;
X	case POT_PARALYSIS:
X		if(Levitation)
X			pline("You are motionlessly suspended.");
X		else
X			pline("Your feet are frozen to the floor!");
X		nomul(-(rn1(10,25)));
X		break;
X	case POT_MONSTER_DETECTION:
X#ifdef SPELLS
X	case SPE_DETECT_MONSTERS:
X#endif
X		if(!fmon) {
X			strange_feeling(otmp, "You feel threatened.");
X			return(1);
X		} else {
X			cls();
X			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X				if(mtmp->mx > 0)
X				at(mtmp->mx,mtmp->my,Hallucination ? rndmonsym() :
X				mtmp->data->mlet);
X			prme();
X			pline("You sense the presence of monsters.");
X			more();
X			docrt();
X		}
X		break;
X	case POT_OBJECT_DETECTION:
X#ifdef SPELLS
X	case SPE_DETECT_TREASURE:
X#endif
X		if(!fobj) {
X			strange_feeling(otmp, "You feel a pull downward.");
X			return(1);
X		} else {
X		    for(objs = fobj; objs; objs = objs->nobj)
X			if(objs->ox != u.ux || objs->oy != u.uy)
X				goto outobjmap;
X		    pline("You sense the presence of objects close nearby.");
X		    break;
X		outobjmap:
X			cls();
X			for(objs = fobj; objs; objs = objs->nobj)
X				at(objs->ox,objs->oy,Hallucination ? rndobjsym()
X				 : objs->olet);
X
X			/* monster possessions added by GAN 12/16/86 */
X			for(mtmp = fmon ; mtmp ; mtmp = mtmp->nmon)
X				if(mtmp->minvent)
X					for(objs = mtmp->minvent; objs ;
X					    objs = objs->nobj)
X						at(mtmp->mx,mtmp->my,objs->olet);
X			prme();
X			pline("You sense the presence of objects.");
X			more();
X			docrt();
X		}
X		break;
X	case POT_SICKNESS:
X		pline("Yech! This stuff tastes like poison.");
X		if(Poison_resistance)
X    pline("(But in fact it was biologically contaminated orange juice.)");
X#ifdef KAA
X		if (pl_character[0] == 'H')
X			pline("Fortunately you have been immunized!");
X		else {
X#endif
X			losestr(rn1(4,3));
X			losehp(rnd(10), "contaminated potion");
X#ifdef KAA
X		}
X#endif
X		if(Hallucination) {
X			pline("You are shocked back to your senses!");
X			Hallucination=1;
X		}
X		break;
X	case POT_CONFUSION:
X		if(!Confusion)
X		    if (Hallucination) {
X			pline("What a trippy feeling!");
X			unkn++;
X		    } else
X			pline("Huh, What?  Where am I?");
X		else	nothing++;
X		HConfusion += rn1(7,16);
X		break;
X	case POT_GAIN_STRENGTH:
X		pline("Wow do you feel strong!");
X		gainstr(0);
X		break;
X	case POT_SPEED:
X		if(Wounded_legs) {
X			heal_legs();
X			unkn++;
X			break;
X		}		/* and fall through */
X#ifdef SPELLS
X	case SPE_HASTE_SELF:
X#endif
X		if(!(Fast & ~INTRINSIC))
X			pline("You are suddenly moving much faster.");
X		else
X			pline("Your legs get new energy."), unkn++;
X		Fast += rn1(10,100);
X		break;
X	case POT_BLINDNESS:
X		if(!Blind)
X			if (Hallucination)
X				pline("Bummer!  Everything is dark!  Help!");
X			else 
X				pline("A cloud of darkness falls upon you.");
X		else	nothing++;
X		Blind += rn1(100,250);
X		seeoff(0);
X		break;
X	case POT_GAIN_LEVEL: 
X		pluslvl();
X		break;
X	case POT_EXTRA_HEALING:
X		pline("You feel much better.");
X		healup(d(2,20)+1, 2, 1, 1);
X		if(Hallucination) Hallucination = 1;
X		break;
X	case POT_LEVITATION:
X#ifdef SPELLS
X	case SPE_LEVITATION:
X#endif
X		if(!Levitation)
X			float_up();
X		else
X			nothing++;
X		Levitation += rnd(100);
X		u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down;
X		break;
X	case POT_GAIN_ENERGY:			/* M. Stephenson */
X#ifdef SPELLS
X		{	register int	 num;
X			if(Confusion) {
X			    pline("You feel feverish.");
X			    unkn++;
X			} else
X			    pline("Magical energies course through your body.");
X			num = rnd(5) + 1;
X			u.uenmax += num;
X			u.uen += num;
X			flags.botl = 1;
X			break;
X		}
X#else
X		pline("This potion tastes wierd!");
X		break;
X#endif
X	default:
X		impossible("What a funny potion! (%u)", otmp->otyp);
X		return(0);
X	}
X	return(-1);
X}
X
Xhealup(nhp, nxtra, curesick, cureblind)
X	int	nhp, nxtra;
X	register boolean curesick, cureblind;
X{
X#ifdef KAA
X	if (u.mtimedone & nhp) {
X		u.mh += rnd(nhp);
X		if (u.mh > u.mhmax) u.mh = ++u.mhmax;
X	}
X#endif
X	if(nhp)	{
X		u.uhp += nhp;
X		if(u.uhp > u.uhpmax)	u.uhp = (u.uhpmax += nxtra);
X	}
X	if(Blind && cureblind)	Blind = 1;	/* see on next move */
X	if(Sick && curesick)	Sick = 0;
X	flags.botl = 1;
X	return;
X}
X
Xpluslvl()
X{
X	register num;
X
X	pline("You feel more experienced.");
X	num = rnd(10);
X	u.uhpmax += num;
X	u.uhp += num;
X#ifdef SPELLS
X	num = rnd(u.ulevel/2+1) + 1;		/* M. Stephenson */
X	u.uenmax += num;
X	u.uen += num;
X#endif
X	if(u.ulevel < 14) {
X		extern long newuexp();
X
X		u.uexp = newuexp()+1;
X		pline("Welcome to experience level %u.", ++u.ulevel);
X	}
X	flags.botl = 1;
X}
X
Xstrange_feeling(obj,txt)
Xregister struct obj *obj;
Xregister char *txt;
X{
X	if(flags.beginner)
X		pline("You have a %s feeling for a moment, then it passes.",
X		Hallucination ? "normal" : "strange");
X	else
X		pline(txt);
X	if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
X		docall(obj);
X	useup(obj);
X}
X
Xchar *bottlenames[] = {
X	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
X};
X
Xpotionhit(mon, obj)
Xregister struct monst *mon;
Xregister struct obj *obj;
X{
X	extern char *xname();
X	register char *botlnam = bottlenames[rn2(SIZE(bottlenames))];
X	boolean uclose, isyou = (mon == &youmonst);
X
X	if(isyou) {
X		uclose = TRUE;
X		pline("The %s crashes on your head and breaks into shivers.",
X			botlnam);
X		losehp(rnd(2), "thrown potion");
X	} else {
X		uclose = (dist(mon->mx,mon->my) < 3);
X		/* perhaps 'E' and 'a' have no head? */
X		pline("The %s crashes on %s's head and breaks into shivers.",
X			botlnam, monnam(mon));
X		if(rn2(5) && mon->mhp > 1)
X			mon->mhp--;
X	}
X	pline("The %s evaporates.", xname(obj));
X
X#ifdef KAA
X	if(!isyou) switch (obj->otyp) {
X#else
X	if(!isyou && !rn2(3)) switch(obj->otyp) {
X#endif
X
X	case POT_RESTORE_STRENGTH:
X	case POT_GAIN_STRENGTH:
X	case POT_HEALING:
X	case POT_EXTRA_HEALING:
X		if(mon->mhp < mon->mhpmax) {
X			mon->mhp = mon->mhpmax;
X			pline("%s looks sound and hale again!", Monnam(mon));
X		}
X		break;
X	case POT_SICKNESS:
X		if((mon->mhpmax > 3) && !resist(mon, '!', 0, NOTELL))
X			mon->mhpmax /= 2;
X		if((mon->mhp > 2) && !resist(mon, '!', 0, NOTELL))
X			mon->mhp /= 2;
X#ifdef KAA
X		pline("%s looks rather ill.", Monnam(mon));
X#endif
X		break;
X	case POT_CONFUSION:
X	case POT_BOOZE:
X		if(!resist(mon, '!', 0, NOTELL))  mon->mconf = 1;
X		break;
X	case POT_INVISIBILITY:
X		unpmon(mon);
X		mon->minvis = 1;
X		pmon(mon);
X		break;
X	case POT_PARALYSIS:
X		mon->mfroz = 1;
X		break;
X	case POT_SPEED:
X		mon->mspeed = MFAST;
X		break;
X	case POT_BLINDNESS:
X		mon->mblinded |= 64 + rn2(32) +
X				      rn2(32) * !resist(mon, '!', 0, NOTELL);
X		break;
X#ifdef KAA
X	case POT_HOLY_WATER:
X		if (index("ZVW &", mon->data->mlet)) {
X			pline("%s shrieks in pain!", Monnam(mon));
X			mon->mhp -= d(2,6);
X			if (mon->mhp <1) killed(mon);
X		}
X		break;
X#endif
X/*	
X	case POT_GAIN_LEVEL:
X	case POT_LEVITATION:
X	case POT_FRUIT_JUICE:
X	case POT_MONSTER_DETECTION:
X	case POT_OBJECT_DETECTION:
X		break;
X*/
X	}
X	if(uclose && rn2(5))
X		potionbreathe(obj);
X	obfree(obj, Null(obj));
X}
X
Xpotionbreathe(obj)
Xregister struct obj *obj;
X{
X	switch(obj->otyp) {
X	case POT_RESTORE_STRENGTH:
X	case POT_GAIN_STRENGTH:
X		if(u.ustr < u.ustrmax) u.ustr++, flags.botl = 1;
X		break;
X	case POT_HEALING:
X	case POT_EXTRA_HEALING:
X		if(u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
X		break;
X	case POT_SICKNESS:
X		if(u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
X		flags.botl = 1;
X		break;
X	case POT_HALLUCINATION:
X#ifdef KAA
X		pline("You have a vision for a moment.");
X		break;
X#endif
X	case POT_CONFUSION:
X	case POT_BOOZE:
X		if(!Confusion)
X			pline("You feel somewhat dizzy.");
X		HConfusion += rnd(5);
X		break;
X	case POT_INVISIBILITY:
X		pline("For an instant you couldn't see your right hand.");
X		break;
X	case POT_PARALYSIS:
X		pline("Something seems to be holding you.");
X		nomul(-rnd(5));
X		break;
X	case POT_SPEED:
X		Fast += rnd(5);
X		pline("Your knees seem more flexible now.");
X		break;
X	case POT_BLINDNESS:
X		if(!Blind) pline("It suddenly gets dark.");
X		Blind += rnd(5);
X		seeoff(0);
X		break;
X/*	
X	case POT_GAIN_LEVEL:
X	case POT_LEVITATION:
X	case POT_FRUIT_JUICE:
X	case POT_MONSTER_DETECTION:
X	case POT_OBJECT_DETECTION:
X		break;
X*/
X	}
X	/* note: no obfree() */
X}
X
X/*
X * -- rudimentary -- to do this correctly requires much more work
X * -- all sharp weapons get one or more qualities derived from the potions
X * -- texts on scrolls may be (partially) wiped out; do they become blank?
X * --   or does their effect change, like under Confusion?
X * -- all objects may be made invisible by POT_INVISIBILITY
X * -- If the flask is small, can one dip a large object? Does it magically
X * --   become a jug? Etc.
X */
Xdodip(){
X	register struct obj *potion, *obj;
X#ifdef KAA
X	char *tmp;
X#endif
X
X	if(!(obj = getobj("#", "dip")))
X		return(0);
X#ifdef FOUNTAINS
X	/* Is there something to dip into here, i.e., a fountain? */
X	if (levl[u.ux][u.uy].typ == FOUNTAIN) {
X		pline("Dip it in the fountain? [ny] ");
X		if(readchar() == 'y') {
X			dipfountain(obj);
X			return(1);
X		}
X	}
X#endif
X	if(!(potion = getobj("!", "dip into")))
X		return(0);
X#ifndef KAA
X	pline("Interesting...");
X#else
X	if(potion->otyp == POT_HOLY_WATER) {
X		if (obj->cursed) {
X			obj->cursed=0;
X			pline("Your %s %s.", aobjnam(obj,"softly glow"), 
X			Hallucination ? hcolor() : "amber");
X	poof:	useup(potion);
X			return(1);
X		} else if(obj->otyp >= ARROW && obj->otyp <= SPEAR) {
X			obj->dknown=1;
X			tmp = Hallucination ? hcolor() : "light blue";
X	/* dknown for weapons is meaningless, so it's free to be reused. */
X			pline("Your %s with a%s %s aura.", aobjnam(obj,"softly glow"),
X			index("aeiou",*tmp) ? "n" : "", tmp);
X			goto poof;
X		}
X	}
X#endif
X	if(obj->otyp == ARROW || obj->otyp == DART ||
X	   obj->otyp == CROSSBOW_BOLT || obj->otyp == SHURIKEN) {
X		if(potion->otyp == POT_SICKNESS) {
X			char buf[BUFSZ];
X			useup(potion);
X			if(obj->spe < 7) obj->spe++;	/* %% */
X			sprintf(buf, xname(potion));
X			pline("The %s forms a coating on the %s.",
X				buf, xname(obj));
X		}
X	}
X#ifdef KAA
X	pline("Interesting...");
X#endif
X	return(1);
X}
X
Xghost_from_bottle(){
X	extern struct permonst pm_ghost;
X	register struct monst *mtmp;
X
X	if(!(mtmp = makemon(PM_GHOST,u.ux,u.uy))){
X		pline("This bottle turns out to be empty.");
X		return;
X	}
X	mnexto(mtmp);
X	pline("As you open the bottle, an enormous ghost emerges!");
X	pline("You are frightened to death, and unable to move.");
X	nomul(-3);
X}
X
Xgainstr(inc)
Xregister int	inc;
X{
X	if(u.ustr >= 118) return;	/* > 118 is impossible */
X
X	if((u.ustr > 17) && !inc)	u.ustr += rnd(118 - u.ustr);
X#ifdef HARD
X	else				u.ustr++;
X#else 
X	else				u.ustr += (inc) ? 1 : rnd(3);
X#endif
X
X	if(u.ustr > u.ustrmax)		u.ustrmax = u.ustr;
X	flags.botl = 1;
X}
END_OF_potion.c
if test 13424 -ne `wc -c <potion.c`; then
    echo shar: \"potion.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f unixunix.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"unixunix.c\"
else
echo shar: Extracting \"unixunix.c\" \(10405 characters\)
sed "s/^X//" >unixunix.c <<'END_OF_unixunix.c'
X/*	SCCS Id: @(#)unixunix.c	1.3	87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* hack.unix.c - version 1.0.3 */
X
X/* This file collects some Unix dependencies; pager.c contains some more */
X
X/*
X * The time is used for:
X *	- seed for rand()
X *	- year on tombstone and yymmdd in record file
X *	- phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
X *	- night and midnight (the undead are dangerous at midnight)
X *	- determination of what files are "very old"
X */
X
X#include <stdio.h>
X#include <errno.h>
X#include "hack.h"	/* mainly for index() which depends on BSD */
X
X#include	<sys/types.h>		/* for time_t and stat */
X#include	<sys/stat.h>
X#ifdef BSD
X#include	<sys/time.h>
X#else
X#include	<time.h>
X#endif
X
Xextern char *getenv();
Xextern time_t time();
X
Xsetrandom()
X{
X	(void) srand((int) time ((time_t *) 0));
X}
X
Xstruct tm *
Xgetlt()
X{
X	time_t date;
X	struct tm *localtime();
X
X	(void) time(&date);
X	return(localtime(&date));
X}
X
Xgetyear()
X{
X	return(1900 + getlt()->tm_year);
X}
X
Xchar *
Xgetdate()
X{
X	static char datestr[7];
X	register struct tm *lt = getlt();
X
X	(void) sprintf(datestr, "%2d%2d%2d",
X		lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
X	if(datestr[2] == ' ') datestr[2] = '0';
X	if(datestr[4] == ' ') datestr[4] = '0';
X	return(datestr);
X}
X
Xphase_of_the_moon()			/* 0-7, with 0: new, 4: full */
X{					/* moon period: 29.5306 days */
X					/* year: 365.2422 days */
X	register struct tm *lt = getlt();
X	register int epact, diy, golden;
X
X	diy = lt->tm_yday;
X	golden = (lt->tm_year % 19) + 1;
X	epact = (11 * golden + 18) % 30;
X	if ((epact == 25 && golden > 11) || epact == 24)
X		epact++;
X
X	return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 );
X}
X
Xnight()
X{
X	register int hour = getlt()->tm_hour;
X
X	return(hour < 6 || hour > 21);
X}
X
Xmidnight()
X{
X	return(getlt()->tm_hour == 0);
X}
X
Xstruct stat buf, hbuf;
X
Xgethdate(name) char *name; {
X/* old version - for people short of space */
X/*
X/* register char *np;
X/*	if(stat(name, &hbuf))
X/*		error("Cannot get status of %s.",
X/*			(np = rindex(name, '/')) ? np+1 : name);
X/*
X/* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */
X
X
X/*
X * The problem with   #include	<sys/param.h>   is that this include file
X * does not exist on all systems, and moreover, that it sometimes includes
X * <sys/types.h> again, so that the compiler sees these typedefs twice.
X */
X#define		MAXPATHLEN	1024
X
Xregister char *np, *path;
Xchar filename[MAXPATHLEN+1];
X	if (index(name, '/') != NULL || (path = getenv("PATH")) == NULL)
X		path = "";
X
X	for (;;) {
X		if ((np = index(path, ':')) == NULL)
X			np = path + strlen(path);	/* point to end str */
X		if (np - path <= 1)			/* %% */
X			(void) strcpy(filename, name);
X		else {
X			(void) strncpy(filename, path, np - path);
X			filename[np - path] = '/';
X			(void) strcpy(filename + (np - path) + 1, name);
X		}
X		if (stat(filename, &hbuf) == 0)
X			return;
X		if (*np == '\0')
X			break;
X		path = np + 1;
X	}
X	error("Cannot get status of %s.",
X		(np = rindex(name, '/')) ? np+1 : name);
X}
X
Xuptodate(fd) {
X	if(fstat(fd, &buf)) {
X		pline("Cannot get status of saved level? ");
X		return(0);
X	}
X	if(buf.st_mtime < hbuf.st_mtime) {
X		pline("Saved level is out of date. ");
X		return(0);
X	}
X	return(1);
X}
X
X/* see whether we should throw away this xlock file */
Xveryold(fd) {
X	register int i;
X	time_t date;
X
X	if(fstat(fd, &buf)) return(0);			/* cannot get status */
X	if(buf.st_size != sizeof(int)) return(0);	/* not an xlock file */
X	(void) time(&date);
X	if(date - buf.st_mtime < 3L*24L*60L*60L) {	/* recent */
X		extern int errno;
X		int lockedpid;	/* should be the same size as hackpid */
X
X		if(read(fd, (char *)&lockedpid, sizeof(lockedpid)) !=
X			sizeof(lockedpid))
X			/* strange ... */
X			return(0);
X
X		/* From: Rick Adams <seismo!rick>
X		/* This will work on 4.1cbsd, 4.2bsd and system 3? & 5.
X		/* It will do nothing on V7 or 4.1bsd. */
X		if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
X			return(0);
X	}
X	(void) close(fd);
X	for(i = 1; i <= MAXLEVEL; i++) {		/* try to remove all */
X		glo(i);
X		(void) unlink(lock);
X	}
X	glo(0);
X	if(unlink(lock)) return(0);			/* cannot remove it */
X	return(1);					/* success! */
X}
X
Xgetlock()
X{
X	extern int errno, hackpid, locknum;
X	register int i = 0, fd;
X
X	(void) fflush(stdout);
X
X	/* we ignore QUIT and INT at this point */
X	if (link(HLOCK, LLOCK) == -1) {
X		register int errnosv = errno;
X
X		perror(HLOCK);
X		printf("Cannot link %s to %s\n", LLOCK, HLOCK);
X		switch(errnosv) {
X		case ENOENT:
X		    printf("Perhaps there is no (empty) file %s ?\n", HLOCK);
X		    break;
X		case EACCES:
X		    printf("It seems you don't have write permission here.\n");
X		    break;
X		case EEXIST:
X		    printf("(Try again or rm %s.)\n", LLOCK);
X		    break;
X		default:
X		    printf("I don't know what is wrong.");
X		}
X		getret();
X		error("");
X		/*NOTREACHED*/
X	}
X
X	regularize(lock);
X	glo(0);
X	if(locknum > 25) locknum = 25;
X
X	do {
X		if(locknum) lock[0] = 'a' + i++;
X
X		if((fd = open(lock, 0)) == -1) {
X			if(errno == ENOENT) goto gotlock;    /* no such file */
X			perror(lock);
X			(void) unlink(LLOCK);
X			error("Cannot open %s", lock);
X		}
X
X		if(veryold(fd))	/* if true, this closes fd and unlinks lock */
X			goto gotlock;
X		(void) close(fd);
X	} while(i < locknum);
X
X	(void) unlink(LLOCK);
X	error(locknum ? "Too many hacks running now."
X		      : "There is a game in progress under your name.");
Xgotlock:
X	fd = creat(lock, FMASK);
X	if(unlink(LLOCK) == -1)
X		error("Cannot unlink %s.", LLOCK);
X	if(fd == -1) {
X		error("cannot creat lock file.");
X	} else {
X		if(write(fd, (char *) &hackpid, sizeof(hackpid))
X		    != sizeof(hackpid)){
X			error("cannot write lock");
X		}
X		if(close(fd) == -1) {
X			error("cannot close lock");
X		}
X	}
X}	
X
X#ifdef MAIL
X
X/*
X * Notify user when new mail has arrived. [Idea from Merlyn Leroy, but
X * I don't know the details of his implementation.]
X * { Later note: he disliked my calling a general mailreader and felt that
X *   hack should do the paging itself. But when I get mail, I want to put it
X *   in some folder, reply, etc. - it would be unreasonable to put all these
X *   functions in hack. }
X * The mail daemon '2' is at present not a real monster, but only a visual
X * effect. Thus, makemon() is superfluous. This might become otherwise,
X * however. The motion of '2' is less restrained than usual: diagonal moves
X * from a DOOR are possible. He might also use SDOOR's. Also, '2' is visible
X * in a ROOM, even when you are Blind.
X * Its path should be longer when you are Telepat-hic and Blind.
X *
X * Interesting side effects:
X *	- You can get rich by sending yourself a lot of mail and selling
X *	  it to the shopkeeper. Unfortunately mail isn't very valuable.
X *	- You might die in case '2' comes along at a critical moment during
X *	  a fight and delivers a scroll the weight of which causes you to
X *	  collapse.
X *
X * Possible extensions:
X *	- Open the file MAIL and do fstat instead of stat for efficiency.
X *	  (But sh uses stat, so this cannot be too bad.)
X *	- Examine the mail and produce a scroll of mail called "From somebody".
X *	- Invoke MAILREADER in such a way that only this single letter is read.
X *
X *	- Make him lose his mail when a Nymph steals the letter.
X *	- Do something to the text when the scroll is enchanted or cancelled.
X */
X#include	"mkroom.h"
Xstatic struct stat omstat,nmstat;
Xstatic char *mailbox;
Xstatic long laststattime;
X
Xgetmailstatus() {
X	if(!(mailbox = getenv("MAIL")))
X		return;
X	if(stat(mailbox, &omstat)){
X#ifdef PERMANENT_MAILBOX
X		pline("Cannot get status of MAIL=%s .", mailbox);
X		mailbox = 0;
X#else
X		omstat.st_mtime = 0;
X#endif
X	}
X}
X
Xckmailstatus() {
X	if(!mailbox
X#ifdef MAILCKFREQ
X		    || moves < laststattime + MAILCKFREQ
X#endif
X							)
X		return;
X	laststattime = moves;
X	if(stat(mailbox, &nmstat)){
X#ifdef PERMANENT_MAILBOX
X		pline("Cannot get status of MAIL=%s anymore.", mailbox);
X		mailbox = 0;
X#else
X		nmstat.st_mtime = 0;
X#endif
X	} else if(nmstat.st_mtime > omstat.st_mtime) {
X		if(nmstat.st_size)
X			newmail();
X		getmailstatus();	/* might be too late ... */
X	}
X}
X
Xnewmail() {
X	/* produce a scroll of mail */
X	register struct obj *obj;
X	register struct monst *md;
X	extern char plname[];
X	extern struct obj *mksobj(), *addinv();
X	extern struct monst *makemon();
X	extern struct permonst pm_mail_daemon;
X
X	obj = mksobj(SCR_MAIL);
X	if(md = makemon(&pm_mail_daemon, u.ux, u.uy)) /* always succeeds */
X		mdrush(md,0);
X
X	pline("\"Hello, %s! I have some mail for you.\"", plname);
X	if(md) {
X		if(dist(md->mx,md->my) > 2)
X			pline("\"Catch!\"");
X		more();
X
X		/* let him disappear again */
X		mdrush(md,1);
X		mondead(md);
X	}
X
X	obj = addinv(obj);
X	(void) identify(obj);		/* set known and do prinv() */
X}
X
X/* make md run through the cave */
Xmdrush(md,away)
Xregister struct monst *md;
Xboolean away;
X{
X	register int uroom = inroom(u.ux, u.uy);
X	if(uroom >= 0) {
X		register int tmp = rooms[uroom].fdoor;
X		register int cnt = rooms[uroom].doorct;
X		register int fx = u.ux, fy = u.uy;
X		while(cnt--) {
X			if(dist(fx,fy) < dist(doors[tmp].x, doors[tmp].y)){
X				fx = doors[tmp].x;
X				fy = doors[tmp].y;
X			}
X			tmp++;
X		}
X		tmp_at(-1, md->data->mlet);	/* open call */
X		if(away) {	/* interchange origin and destination */
X			unpmon(md);
X			tmp = fx; fx = md->mx; md->mx = tmp;
X			tmp = fy; fy = md->my; md->my = tmp;
X		}
X		while(fx != md->mx || fy != md->my) {
X			register int dx,dy,nfx = fx,nfy = fy,d1,d2;
X
X			tmp_at(fx,fy);
X			d1 = DIST(fx,fy,md->mx,md->my);
X			for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
X			    if(dx || dy) {
X				d2 = DIST(fx+dx,fy+dy,md->mx,md->my);
X				if(d2 < d1) {
X				    d1 = d2;
X				    nfx = fx+dx;
X				    nfy = fy+dy;
X				}
X			    }
X			if(nfx != fx || nfy != fy) {
X			    fx = nfx;
X			    fy = nfy;
X			} else {
X			    if(!away) {
X				md->mx = fx;
X				md->my = fy;
X			    }
X			    break;
X			} 
X		}
X		tmp_at(-1,-1);			/* close call */
X	}
X	if(!away)
X		pmon(md);
X}
X
Xreadmail() {
X#ifdef DEF_MAILREADER			/* This implies that UNIX is defined */
X	register char *mr = 0;
X	more();
X	if(!(mr = getenv("MAILREADER")))
X		mr = DEF_MAILREADER;
X	if(child(1)){
X		execl(mr, mr, (char *) 0);
X		exit(1);
X	}
X#else
X	(void) page_file(mailbox, FALSE);
X#endif
X	/* get new stat; not entirely correct: there is a small time
X	   window where we do not see new mail */
X	getmailstatus();
X}
X#endif /* MAIL /**/
X
Xregularize(s)	/* normalize file name - we don't like ..'s or /'s */
Xregister char *s;
X{
X	register char *lp;
X
X	while((lp = index(s, '.')) || (lp = index(s, '/')))
X		*lp = '_';
X}
END_OF_unixunix.c
if test 10405 -ne `wc -c <unixunix.c`; then
    echo shar: \"unixunix.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 7 \(of 16\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 16 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