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(®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
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, ®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 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(®s, ®s);
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(®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
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
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 */
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 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(®s, ®s);
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