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