home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part61
< prev
next >
Wrap
Internet Message Format
|
1993-02-04
|
60KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i069: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part61/108
Message-ID: <4372@master.CNA.TEK.COM>
Date: 1 Feb 93 19:49:45 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2382
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1619
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 69
Archive-name: nethack31/Part61
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /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 61 (of 108)."
# Contents: src/files.c src/zap.c2
# Wrapped by billr@saab on Wed Jan 27 16:09:10 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/files.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/files.c'\"
else
echo shar: Extracting \"'src/files.c'\" \(21581 characters\)
sed "s/^X//" >'src/files.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)files.c 3.1 92/12/07 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#include <ctype.h>
X
X#if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)
X#include <fcntl.h>
X#endif
X#if defined(UNIX) || defined(VMS)
X#include <errno.h>
X# ifndef SKIP_ERRNO
Xextern int errno;
X# endif
X#include <signal.h>
X#endif
X
X#if defined(MSDOS) || defined(OS2) || defined(TOS)
X# ifndef GNUDOS
X#include <sys\stat.h>
X# else
X#include <sys/stat.h>
X# endif
X#endif
X#ifndef O_BINARY /* used for micros, no-op for others */
X# define O_BINARY 0
X#endif
X
X#ifdef MFLOPPY
Xchar bones[FILENAME]; /* pathname of bones files */
Xchar lock[FILENAME]; /* pathname of level files */
X#else
Xstatic char bones[] = "bonesnn.xxxx";
X# ifdef VMS
Xchar lock[PL_NSIZ+17] = "1lock"; /* long enough for _uid+name+.99;1 */
X# else
Xchar lock[PL_NSIZ+14] = "1lock"; /* long enough for uid+name+.99 */
X# endif
X#endif
X
X#ifdef MAC
X#include <files.h>
XMacDirs theDirs ;
X#endif
X
X#ifdef UNIX
X#define SAVESIZE (PL_NSIZ + 13) /* save/99999player.e */
X#else
X# ifdef VMS
X#define SAVESIZE (PL_NSIZ + 22) /* [.save]<uid>player.e;1 */
X# else
X#define SAVESIZE FILENAME /* from macconf.h or pcconf.h */
X# endif
X#endif
X
Xchar SAVEF[SAVESIZE]; /* holds relative path of save file from playground */
X#ifdef MICRO
Xchar SAVEP[SAVESIZE]; /* holds path of directory for save file */
X#endif
X#ifdef AMIGA
Xextern char PATH[]; /* see sys/amiga/amidos.c */
X#endif
X
Xstatic char * FDECL(set_bonesfile_name, (char *,d_level*));
X
X/* fopen a file, with OS-dependent bells and whistles */
XFILE *
Xfopen_datafile(filename, mode)
Xconst char *filename, *mode;
X{
X FILE *fp;
X#ifdef AMIGA
X fp = fopenp(filename, mode);
X#else
X# ifdef VMS /* essential to have punctuation, to avoid logical names */
X char tmp[BUFSIZ];
X
X if (!index(filename, '.') && !index(filename, ';'))
X filename = strcat(strcpy(tmp, filename), ";0");
X fp = fopen(filename, mode, "mbc=16");
X# else
X fp = fopen(filename, mode);
X# endif
X#endif
X return fp;
X}
X
X
X/* ---------- BEGIN LEVEL FILE HANDLING ----------- */
X
X#ifdef MFLOPPY
X/* Set names for bones[] and lock[] */
Xvoid
Xset_lock_and_bones()
X{
X if (!ramdisk) {
X Strcpy(levels, permbones);
X Strcpy(bones, permbones);
X }
X append_slash(permbones);
X append_slash(levels);
X append_slash(bones);
X Strcat(bones, "bonesnn.*");
X Strcpy(lock, levels);
X Strcat(lock, alllevels);
X return;
X}
X#endif /* MFLOPPY */
X
X
X/* Construct a file name for a level-type file, which is of the form
X * something.level (with any old level stripped off).
X * This assumes there is space on the end of 'file' to append
X * a two digit number. This is true for 'level'
X * but be careful if you use it for other things -dgk
X */
Xvoid
Xset_levelfile_name(file, lev)
Xchar *file;
Xint lev;
X{
X char *tf;
X
X tf = rindex(file, '.');
X if (!tf) tf = eos(file);
X Sprintf(tf, ".%d", lev);
X#ifdef VMS
X Strcat(tf, ";1");
X#endif
X return;
X}
X
Xint
Xcreate_levelfile(lev)
Xint lev;
X{
X int fd;
X
X set_levelfile_name(lock, lev);
X
X#if defined(MICRO)
X /* Use O_TRUNC to force the file to be shortened if it already
X * exists and is currently longer.
X */
X fd = open(lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
X#else
X#ifdef MAC
X fd = maccreat ( lock , LEVL_TYPE ) ;
X#else /* MAC */
X fd = creat(lock, FCMASK);
X#endif /* MAC */
X#endif /* MICRO */
X
X return fd;
X}
X
X
Xint
Xopen_levelfile(lev)
Xint lev;
X{
X int fd;
X
X set_levelfile_name(lock, lev);
X#ifdef MFLOPPY
X /* If not currently accessible, swap it in. */
X if (fileinfo[lev].where != ACTIVE)
X swapin_file(lev);
X#endif
X# ifdef MAC
X fd = macopen ( lock , O_RDONLY | O_BINARY , LEVL_TYPE ) ;
X# else /* MAC */
X fd = open(lock, O_RDONLY | O_BINARY, 0);
X# endif /* MAC */
X return fd;
X}
X
X
Xvoid
Xdelete_levelfile(lev)
Xint lev;
X{
X set_levelfile_name(lock, lev);
X (void) unlink(lock);
X}
X
X
Xvoid
Xclearlocks()
X{
X#ifdef MFLOPPY
X eraseall(levels, alllevels);
X# ifndef AMIGA
X if (ramdisk)
X eraseall(permbones, alllevels);
X# endif
X#else
X register int x;
X
X# if defined(UNIX) || defined(VMS)
X (void) signal(SIGHUP, SIG_IGN);
X# endif
X for (x = maxledgerno(); x >= 0; x--)
X delete_levelfile(x); /* not all levels need be present */
X#endif
X}
X
X/* ---------- END LEVEL FILE HANDLING ----------- */
X
X
X/* ---------- BEGIN BONES FILE HANDLING ----------- */
X
Xstatic char *
Xset_bonesfile_name(file, lev)
Xchar *file;
Xd_level *lev;
X{
X char *dptr = rindex(file, '.');
X s_level *sptr;
X
X if (!dptr) dptr = eos(file);
X *(dptr-2) = dungeons[lev->dnum].boneid;
X#ifdef MULDGN
X *(dptr-1) = In_quest(lev) ? pl_character[0] : '0';
X#else
X *(dptr-1) = '0';
X#endif
X if ((sptr = Is_special(lev)) != 0)
X Sprintf(dptr, ".%c", sptr->boneid);
X else
X Sprintf(dptr, ".%d", lev->dlevel);
X#ifdef VMS
X Strcat(dptr, ";1");
X#endif
X return(dptr-2);
X}
X
Xint
Xcreate_bonesfile(lev, bonesid)
Xd_level *lev;
Xchar **bonesid;
X{
X int fd;
X
X *bonesid = set_bonesfile_name(bones, lev);
X
X#ifdef MICRO
X /* Use O_TRUNC to force the file to be shortened if it already
X * exists and is currently longer.
X */
X fd = open(bones, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
X#else
X# ifdef MAC
X fd = maccreat ( bones , BONE_TYPE ) ;
X# else /* MAC */
X fd = creat(bones, FCMASK);
X# endif /* MAC */
X# if defined(VMS) && !defined(SECURE)
X /*
X Re-protect bones file with world:read+write+execute+delete access.
X umask() doesn't seem very reliable; also, vaxcrtl won't let us set
X delete access without write access, which is what's really wanted.
X Can't simply create it with the desired protection because creat
X ANDs the mask with the user's default protection, which usually
X denies some or all access to world.
X */
X (void) chmod(bones, FCMASK | 007); /* allow other users full access */
X# endif /* VMS && !SECURE */
X#endif /* MICRO */
X
X return fd;
X}
X
X
Xint
Xopen_bonesfile(lev, bonesid)
Xd_level *lev;
Xchar **bonesid;
X{
X int fd;
X
X *bonesid = set_bonesfile_name(bones, lev);
X uncompress(bones); /* no effect if nonexistent */
X#ifdef MAC
X fd = macopen ( bones , O_RDONLY | O_BINARY , BONE_TYPE ) ;
X#else
X fd = open(bones, O_RDONLY | O_BINARY, 0);
X#endif
X return fd;
X}
X
X
Xint
Xdelete_bonesfile(lev)
Xd_level *lev;
X{
X (void) set_bonesfile_name(bones, lev);
X return !(unlink(bones) < 0);
X}
X
X
X/* assume we're compressing the recently read or created bonesfile, so the
X * file name is already set properly */
Xvoid
Xcompress_bonesfile()
X{
X compress(bones);
X}
X
X/* ---------- END BONES FILE HANDLING ----------- */
X
X
X/* ---------- BEGIN SAVE FILE HANDLING ----------- */
X
X/* set savefile name in OS-dependent manner from pre-existing plname,
X * avoiding troublesome characters */
Xvoid
Xset_savefile_name()
X{
X#ifdef VMS
X Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
X regularize(SAVEF+7);
X Strcat(SAVEF, ";1");
X#else
X# ifdef MICRO
X Strcpy(SAVEF, SAVEP);
X {
X int i = strlen(SAVEP);
X# ifdef AMIGA
X /* plname has to share space with SAVEP and ".sav" */
X (void)strncat(SAVEF, plname, FILENAME - i - 4);
X# else
X (void)strncat(SAVEF, plname, 8);
X# endif
X regularize(SAVEF+i);
X }
X Strcat(SAVEF, ".sav");
X# else
X Sprintf(SAVEF, "save/%d%s", (int)getuid(), plname);
X regularize(SAVEF+5); /* avoid . or / in name */
X# endif
X#endif
X}
X
X#ifdef INSURANCE
Xvoid
Xsave_savefile_name(fd)
Xint fd;
X{
X (void) write(fd, (genericptr_t) SAVEF, sizeof(SAVEF));
X}
X#endif
X
X
X#if defined(WIZARD) && !defined(MICRO)
X/* change pre-existing savefile name to indicate an error savefile */
Xvoid
Xset_error_savefile()
X{
X# ifdef VMS
X {
X char *semi_colon = rindex(SAVEF, ';');
X if (semi_colon) *semi_colon = '\0';
X }
X Strcat(SAVEF, ".e;1");
X# else
X#ifdef MAC
X Strcat(SAVEF, "-e");
X#else
X Strcat(SAVEF, ".e");
X#endif
X# endif
X}
X#endif
X
X
X/* create save file, overwriting one if it already exists */
Xint
Xcreate_savefile()
X{
X int fd;
X# ifdef AMIGA
X fd = ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC);
X# else
X# ifdef MICRO
X fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
X# else
X# ifdef MAC
X fd = creat(SAVEF, SAVE_TYPE);
X# else /* MAC */
X fd = creat(SAVEF, FCMASK);
X# endif /* MAC */
X# if defined(VMS) && !defined(SECURE)
X /*
X Make sure the save file is owned by the current process. That's
X the default for non-privileged users, but for priv'd users the
X file will be owned by the directory's owner instead of the user.
X */
X# ifdef getuid /*(see vmsunix.c)*/
X# undef getuid
X# endif
X (void) chown(SAVEF, getuid(), getgid());
X# endif /* VMS && !SECURE */
X# endif
X# endif
X
X return fd;
X}
X
X
X/* open savefile for reading */
Xint
Xopen_savefile()
X{
X int fd;
X
X#ifdef AMIGA
X fd = ami_wbench_getsave(O_RDONLY);
X#else
X# ifdef MAC
X fd = macopen ( SAVEF , O_RDONLY , SAVE_TYPE ) ;
X# else /* MAC */
X fd = open(SAVEF, O_RDONLY, 0);
X# endif /* MAC */
X#endif /* AMIGA */
X return fd;
X}
X
X
X/* delete savefile */
Xint
Xdelete_savefile()
X{
X#ifdef AMIGA
X ami_wbench_unlink(SAVEF);
X#endif
X (void) unlink(SAVEF);
X return 0; /* for xxxmain.c test */
X}
X
X
X/* ---------- END SAVE FILE HANDLING ----------- */
X
X
X/* ---------- BEGIN FILE COMPRESSION HANDLING ----------- */
X
X/* compress file */
Xvoid
Xcompress(filename)
Xconst char *filename;
X{
X#ifdef COMPRESS
X char cmd[80];
X
X Strcpy(cmd, COMPRESS);
X Strcat(cmd, " ");
X# ifdef COMPRESS_OPTIONS
X Strcat(cmd, COMPRESS_OPTIONS);
X Strcat(cmd, " ");
X# endif
X Strcat(cmd,filename);
X (void) system(cmd);
X#endif
X}
X
X
X/* uncompress file if it exists */
Xvoid
Xuncompress(filename)
Xconst char *filename;
X{
X#ifdef COMPRESS
X char cmd[80], cfn[80];
X int fd;
X
X Strcpy(cfn,filename);
X Strcat(cfn,".Z");
X if((fd = open(cfn,O_RDONLY)) >= 0) {
X (void) close(fd);
X Strcpy(cmd, COMPRESS);
X Strcat(cmd, " -d "); /* uncompress */
X# ifdef COMPRESS_OPTIONS
X Strcat(cmd, COMPRESS_OPTIONS);
X Strcat(cmd, " ");
X# endif
X Strcat(cmd,cfn);
X (void) system(cmd);
X }
X#endif
X}
X
X/* ---------- END FILE COMPRESSION HANDLING ----------- */
X
X
X/* ---------- BEGIN FILE LOCKING HANDLING ----------- */
X
X#ifdef NO_FILE_LINKS /* implies UNIX */
Xstatic int lockfd; /* for lock_file() to pass to unlock_file() */
X#endif
X
X#if defined(UNIX) || defined(VMS)
X#define HUP if(!done_hup)
X
Xstatic char *
Xmake_lockname(filename)
Xconst char *filename;
X{
X static char lockname[BUFSZ];
X
X# ifdef NO_FILE_LINKS
X Strcpy(lockname, LOCKDIR);
X Strcat(lockname, "/");
X Strcat(lockname, filename);
X# else
X Strcpy(lockname, filename);
X# endif
X# ifdef VMS
X {
X char *semi_colon = rindex(lockname, ';');
X if (semi_colon) *semi_colon = '\0';
X }
X Strcat(lockname, ".lock;1");
X# else
X Strcat(lockname, "_lock");
X# endif
X return lockname;
X}
X#endif /* UNIX || VMS */
X
X
X/* lock a file */
Xboolean
Xlock_file(filename, retryct)
Xconst char *filename;
Xint retryct;
X{
X#if defined(UNIX) || defined(VMS)
X char *lockname;
X
X lockname = make_lockname(filename);
X
X# ifdef NO_FILE_LINKS
X while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) {
X# else
X while (link(filename, lockname) == -1) {
X# endif
X register int errnosv = errno;
X
X switch (errnosv) { /* George Barbanis */
X case ENOENT:
X HUP raw_printf("Can't find file %s to lock!", filename);
X return FALSE;
X case EACCES:
X HUP raw_printf("No write permission to lock %s!",
X filename);
X return FALSE;
X case EEXIST:
X break; /* retry checks below */
X default:
X HUP perror(lockname);
X HUP raw_printf(
X "Cannot lock %s for unknown reason (%d).",
X filename, errnosv);
X return FALSE;
X }
X
X if (!retryct--) {
X HUP (void) raw_print("I give up. Sorry.");
X HUP raw_printf("Perhaps there is an old %s around?",
X lockname);
X return FALSE;
X }
X
X HUP raw_printf("Waiting for access to %s. (%d retries left).",
X filename, retryct);
X# if defined(SYSV) || defined(ULTRIX) || defined(VMS)
X (void)
X# endif
X sleep(1);
X }
X#endif /* UNIX || VMS */
X return TRUE;
X}
X
X
X#ifdef VMS /* for unlock_file, use the unlink() routine in vmsunix.c */
X# ifdef unlink
X# undef unlink
X# endif
X# define unlink(foo) vms_unlink(foo)
X#endif
X
X/* unlock file, which must be currently locked by lock_file */
Xvoid
Xunlock_file(filename)
Xconst char *filename;
X{
X#if defined(UNIX) || defined(VMS)
X char *lockname;
X
X lockname = make_lockname(filename);
X
X if (unlink(lockname) < 0)
X HUP raw_printf("Can't unlink %s.", lockname);
X# ifdef NO_FILE_LINKS
X (void) close(lockfd);
X# endif
X
X#endif /* UNIX || VMS */
X}
X
X/* ---------- END FILE LOCKING HANDLING ----------- */
X
X
X/* ---------- BEGIN CONFIG FILE HANDLING ----------- */
X
Xconst char *configfile =
X#ifdef UNIX
X ".nethackrc";
X#else
X#ifdef MAC
X "NetHack defaults";
X#else
X "NetHack.cnf";
X#endif
X#endif
X
Xstatic FILE *FDECL(fopen_config_file, (const char *));
Xstatic int FDECL(get_uchars, (FILE *, char *, char *, uchar *, int, const char *));
Xint FDECL(parse_config_line, (FILE *, char *, char *, char *));
X
X#ifndef MFLOPPY
X#define fopenp fopen
X#endif
X
Xstatic FILE *
Xfopen_config_file(filename)
Xconst char *filename;
X{
X FILE *fp;
X#if defined(UNIX) || defined(VMS)
X char tmp_config[BUFSZ];
X#endif
X
X /* "filename" is an environment variable, so it should hang around */
X if (filename && ((fp = fopenp(filename, "r")) != (FILE *)0)) {
X configfile = filename;
X return(fp);
X }
X
X#if defined(MICRO) || defined(MAC)
X if ((fp = fopenp(configfile, "r")) != (FILE *)0)
X return(fp);
X#else
X# ifdef VMS
X if ((fp = fopenp("nethackini", "r")) != (FILE *)0) {
X configfile = "nethackini";
X return(fp);
X }
X if ((fp = fopenp("sys$login:nethack.ini", "r")) != (FILE *)0) {
X configfile = "nethack.ini";
X return(fp);
X }
X Sprintf(tmp_config, "%s%s", getenv("HOME"), "NetHack.cnf");
X if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
X return(fp);
X# else /* should be only UNIX left */
X Sprintf(tmp_config, "%s/%s", getenv("HOME"), ".nethackrc");
X if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
X return(fp);
X# endif
X#endif
X return (FILE *)0;
X
X}
X
X
X/*
X * Retrieve a list of integers from a file into a uchar array.
X *
X * NOTE: This routine is unable to read a value of 0.
X */
Xstatic int
Xget_uchars(fp, buf, bufp, list, size, name)
X FILE *fp; /* input file pointer */
X char *buf; /* read buffer, must be of size BUFSZ */
X char *bufp; /* current pointer */
X uchar *list; /* return list */
X int size; /* return list size */
X const char *name; /* name of option for error message */
X{
X unsigned int num = 0;
X int count = 0;
X
X while (1) {
X switch(*bufp) {
X case ' ': case '\0':
X case '\t': case '\n':
X if (num) {
X list[count++] = num;
X num = 0;
X }
X if (count == size || !*bufp) return count;
X bufp++;
X break;
X
X case '0': case '1': case '2': case '3':
X case '4': case '5': case '6': case '7':
X case '8': case '9':
X num = num*10 + (*bufp-'0');
X bufp++;
X break;
X
X case '\\':
X if (fp == (FILE *)0)
X goto gi_error;
X do {
X if (!fgets(buf, BUFSZ, fp)) goto gi_error;
X } while (buf[0] == '#');
X bufp = buf;
X break;
X
X default:
Xgi_error:
X raw_printf("Syntax error in %s", name);
X wait_synch();
X return count;
X }
X }
X /*NOTREACHED*/
X}
X
X/*ARGSUSED*/
Xint
Xparse_config_line(fp, buf, tmp_ramdisk, tmp_levels)
XFILE *fp;
Xchar *buf;
Xchar *tmp_ramdisk;
Xchar *tmp_levels;
X{
X char *bufp, *altp;
X
X if (*buf == '#')
X return 1;
X
X /* remove trailing whitespace */
X bufp = eos(buf);
X while (--bufp > buf && isspace(*bufp))
X continue;
X
X if (bufp <= buf)
X return 1; /* skip all-blank lines */
X else
X *(bufp + 1) = '\0'; /* terminate line */
X
X /* find the '=' or ':' */
X bufp = index(buf, '=');
X altp = index(buf, ':');
X if (!bufp || (altp && altp < bufp)) bufp = altp;
X if (!bufp) return 0;
X
X /* skip whitespace between '=' and value */
X do { ++bufp; } while (isspace(*bufp));
X
X /* Go through possible variables */
X if (!strncmpi(buf, "OPTIONS", 4)) {
X parseoptions(bufp, TRUE, TRUE);
X if (plname[0]) /* If a name was given */
X plnamesuffix(); /* set the character class */
X#ifdef MICRO
X } else if (!strncmpi(buf, "HACKDIR", 4)) {
X (void) strncpy(hackdir, bufp, PATHLEN);
X# ifdef MFLOPPY
X } else if (!strncmpi(buf, "RAMDISK", 3)) {
X /* The following ifdef is NOT in the wrong
X * place. For now, we accept and silently
X * ignore RAMDISK */
X# ifndef AMIGA
X (void) strncpy(tmp_ramdisk, bufp, PATHLEN);
X# endif
X# endif
X } else if (!strncmpi(buf, "LEVELS", 4)) {
X (void) strncpy(tmp_levels, bufp, PATHLEN);
X
X } else if (!strncmpi(buf, "SAVE", 4)) {
X char *ptr;
X if (ptr = index(bufp, ';')) {
X *ptr = '\0';
X# ifdef MFLOPPY
X if (*(ptr+1) == 'n' || *(ptr+1) == 'N') {
X extern int saveprompt;
X saveprompt = FALSE;
X }
X# endif
X }
X (void) strncpy(SAVEP, bufp, PATHLEN);
X append_slash(SAVEP);
X#endif /* MICRO */
X } else if(!strncmpi(buf, "CHARACTER", 4)) {
X (void) strncpy(pl_character, bufp, PL_CSIZ);
X } else if(!strncmpi(buf, "DOGNAME", 3)) {
X (void) strncpy(dogname, bufp, 62);
X } else if(!strncmpi(buf, "CATNAME", 3)) {
X (void) strncpy(catname, bufp, 62);
X } else if(!strncmpi(buf, "NAME", 4)) {
X (void) strncpy(plname, bufp, PL_NSIZ);
X plnamesuffix();
X } else if (!strncmpi(buf, "GRAPHICS", 4)) {
X uchar translate[MAXPCHARS];
X int len;
X
X len = get_uchars(fp, buf, bufp, translate,
X MAXPCHARS, "GRAPHICS");
X assign_graphics(translate, len);
X } else if (!strncmpi(buf, "OBJECTS", 3)) {
X /* oc_syms[0] is the RANDOM object, unused */
X (void) get_uchars(fp, buf, bufp, &(oc_syms[1]),
X MAXOCLASSES-1, "OBJECTS");
X } else if (!strncmpi(buf, "MONSTERS", 3)) {
X /* monsyms[0] is unused */
X (void) get_uchars(fp, buf, bufp, &(monsyms[1]),
X MAXMCLASSES-1, "MONSTERS");
X#ifdef AMIGA
X } else if (!strncmpi(buf, "PATH", 4)) {
X (void) strncpy(PATH, bufp, PATHLEN);
X } else if (!strncmpi(buf, "PENS", 3)) {
X int i;
X char *t;
X extern unsigned short amii_curmap[];
X for (i = 0, t = strtok(bufp, ",");
X t && i < 8;
X t = strtok(NULL, ","), ++i) {
X sscanf(t, "%hx", &amii_curmap[i]);
X }
X amii_setpens();
X#endif
X } else
X return 0;
X return 1;
X}
X
Xvoid
Xread_config_file(filename)
Xconst char *filename;
X{
X#define tmp_levels (char *)0
X#define tmp_ramdisk (char *)0
X
X#ifdef MICRO
X#undef tmp_levels
X char tmp_levels[PATHLEN];
X# ifdef MFLOPPY
X# ifndef AMIGA
X#undef tmp_ramdisk
X char tmp_ramdisk[PATHLEN];
X# endif
X# endif
X#endif
X char buf[BUFSZ];
X FILE *fp;
X
X#if defined(MAC)
X {
X long nul = 0L ;
X Str255 volName ;
X /*
X * We should try and get this data from a rsrc, in the profile file
X * the user double-clicked... This data should be saved with the
X * save file in the resource fork, AND be saveable in "stationery"
X */
X GetVol ( volName , & theDirs . dataRefNum ) ;
X GetWDInfo ( theDirs . dataRefNum , & theDirs . dataRefNum , & theDirs .
X dataDirID , & nul ) ;
X if ( volName [ 0 ] > 31 ) volName [ 0 ] = 31 ;
X for ( nul = 1 ; nul <= volName [ 0 ] ; nul ++ ) {
X if ( volName [ nul ] == ':' ) {
X volName [ nul ] = 0 ;
X volName [ 0 ] = nul - 1 ;
X break ;
X }
X }
X BlockMove ( volName , theDirs . dataName , 32L ) ;
X }
X#endif /* MAC */
X
X if (!(fp = fopen_config_file(filename))) return;
X
X#ifdef MICRO
X# ifdef MFLOPPY
X# ifndef AMIGA
X tmp_ramdisk[0] = 0;
X# endif
X# endif
X tmp_levels[0] = 0;
X#endif
X
X while (fgets(buf, BUFSZ, fp)) {
X if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) {
X raw_printf("Bad option line: \"%s\"", buf);
X wait_synch();
X }
X }
X (void) fclose(fp);
X
X#ifdef MICRO
X# ifdef MFLOPPY
X Strcpy(permbones, tmp_levels);
X# ifndef AMIGA
X if (tmp_ramdisk[0]) {
X Strcpy(levels, tmp_ramdisk);
X if (strcmp(permbones, levels)) /* if not identical */
X ramdisk = TRUE;
X } else
X# endif /* AMIGA */
X Strcpy(levels, tmp_levels);
X
X Strcpy(bones, levels);
X# endif /* MFLOPPY */
X#endif /* MICRO */
X return;
X}
X
X/* ---------- END CONFIG FILE HANDLING ----------- */
X
X/* ---------- BEGIN SCOREBOARD CREATION ----------- */
X
X/* verify that we can write to the scoreboard file; if not, try to create one */
Xvoid
Xcheck_recordfile(dir)
Xconst char *dir;
X{
X#if defined(UNIX) || defined(VMS)
X int fd = open(RECORD, O_RDWR, 0);
X
X if (fd >= 0) {
X# ifdef VMS /* must be stream-lf to use UPDATE_RECORD_IN_PLACE */
X if (!file_is_stmlf(fd)) {
X raw_printf( /* note: assume VMS dir has trailing punct */
X "Warning: scoreboard file %s%s is not in stream_lf format",
X (dir ? dir : "[]"), RECORD);
X wait_synch();
X }
X# endif
X (void) close(fd); /* RECORD is accessible */
X } else if ((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) >= 0) {
X (void) close(fd); /* RECORD newly created */
X# if defined(VMS) && !defined(SECURE)
X /* Re-protect RECORD with world:read+write+execute+delete access. */
X (void) chmod(RECORD, FCMASK | 007); /* allow everyone full access */
X# endif /* VMS && !SECURE */
X } else {
X raw_printf("Warning: cannot write scoreboard file %s/%s",
X (dir ? dir : "."), RECORD);
X wait_synch();
X }
X#endif /* !UNIX && !VMS */
X
X#ifdef MICRO
X int fd;
X char tmp[PATHLEN];
X
X# ifdef OS2_CODEVIEW /* explicit path on opening for OS/2 */
X Strcpy(tmp, dir);
X append_slash(tmp);
X Strcat(tmp, RECORD);
X# else
X Strcpy(tmp, RECORD);
X# endif
X
X if ((fd = open(tmp, O_RDWR)) < 0) {
X /* try to create empty record */
X# ifdef AZTEC_C
X /* Aztec doesn't use the third argument */
X if ((fd = open(tmp, O_CREAT|O_RDWR)) < 0) {
X# else
X if ((fd = open(tmp, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) < 0) {
X# endif
X raw_printf("Warning: cannot write record %s", tmp);
X wait_synch();
X } else
X (void) close(fd);
X } else /* open succeeded */
X (void) close(fd);
X#else /* MICRO */
X
X# ifdef MAC
X int fd = macopen ( RECORD , O_RDWR | O_CREAT , TEXT_TYPE ) ;
X
X if ( fd < 0 ) {
X raw_printf ( "Warning: cannot write %s" , RECORD ) ;
X } else {
X close ( fd ) ;
X }
X# endif /* MAC */
X
X#endif /* MICRO */
X}
X
X/* ---------- END SCOREBOARD CREATION ----------- */
X
X
X/*files.c*/
END_OF_FILE
if test 21581 -ne `wc -c <'src/files.c'`; then
echo shar: \"'src/files.c'\" unpacked with wrong size!
fi
# end of 'src/files.c'
fi
if test -f 'src/zap.c2' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/zap.c2'\"
else
echo shar: Extracting \"'src/zap.c2'\" \(32988 characters\)
sed "s/^X//" >'src/zap.c2' <<'END_OF_FILE'
Xconst char *
Xexclam(force)
Xregister int force;
X{
X /* force == 0 occurs e.g. with sleep ray */
X /* note that large force is usual with wands so that !! would
X require information about hand/weapon/wand */
X return (const char *)((force < 0) ? "?" : (force <= 4) ? "." : "!");
X}
X
Xvoid
Xhit(str,mtmp,force)
Xregister const char *str;
Xregister struct monst *mtmp;
Xregister const char *force; /* usually either "." or "!" */
X{
X if(!cansee(bhitpos.x,bhitpos.y) || !flags.verbose)
X pline("%s hits it.", The(str));
X else pline("%s hits %s%s", The(str), mon_nam(mtmp), force);
X}
X
Xvoid
Xmiss(str,mtmp)
Xregister const char *str;
Xregister struct monst *mtmp;
X{
X pline("%s misses %s.", The(str),
X (cansee(bhitpos.x,bhitpos.y) && flags.verbose) ?
X mon_nam(mtmp) : "it");
X}
X
X/*
X * Called for the following distance effects:
X * when a weapon is thrown (weapon == THROWN_WEAPON)
X * when an object is kicked (KICKED_WEAPON)
X * when an IMMEDIATE wand is zapped (ZAPPED_WAND)
X * when a light beam is flashed (FLASHED_LIGHT)
X * for some invisible effect on a monster (INVIS_BEAM)
X * A thrown/kicked object falls down at the end of its range or when a monster
X * is hit. The variable 'bhitpos' is set to the final position of the weapon
X * thrown/zapped. The ray of a wand may affect (by calling a provided
X * function) several objects and monsters on its path. The return value
X * is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
X *
X * Check !u.uswallow before calling bhit().
X */
Xstruct monst *
Xbhit(ddx,ddy,range,weapon,fhitm,fhito,obj)
Xregister int ddx,ddy,range; /* direction and range */
Xint weapon; /* see values in hack.h */
X /* fns called when mon/obj hit */
Xint FDECL((*fhitm), (MONST_P, OBJ_P)),
X FDECL((*fhito), (OBJ_P, OBJ_P));
Xstruct obj *obj; /* object tossed/used */
X{
X register struct monst *mtmp;
X register uchar typ;
X register boolean shopdoor = FALSE;
X
X if (weapon == KICKED_WEAPON) {
X /* object starts one square in front of player */
X bhitpos.x = u.ux + ddx;
X bhitpos.y = u.uy + ddy;
X range--;
X } else {
X bhitpos.x = u.ux;
X bhitpos.y = u.uy;
X }
X
X if (weapon == FLASHED_LIGHT) {
X tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
X } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
X tmp_at(DISP_FLASH, obj_to_glyph(obj));
X while(range-- > 0) {
X int x,y;
X
X bhitpos.x += ddx;
X bhitpos.y += ddy;
X x = bhitpos.x; y = bhitpos.y;
X
X if(!isok(x, y)) {
X bhitpos.x -= ddx;
X bhitpos.y -= ddy;
X break;
X }
X if(obj->otyp == PICK_AXE && inside_shop(x, y) &&
X shkcatch(obj, x, y)) {
X tmp_at(DISP_END, 0);
X return(m_at(x, y));
X }
X
X typ = levl[bhitpos.x][bhitpos.y].typ;
X
X if (weapon == ZAPPED_WAND && find_drawbridge(&x,&y))
X switch (obj->otyp) {
X case WAN_OPENING:
X case SPE_KNOCK:
X if (is_db_wall(bhitpos.x, bhitpos.y)) {
X if (cansee(x,y) || cansee(bhitpos.x,bhitpos.y))
X makeknown(obj->otyp);
X open_drawbridge(x,y);
X }
X break;
X case WAN_LOCKING:
X case SPE_WIZARD_LOCK:
X if ((cansee(x,y) || cansee(bhitpos.x, bhitpos.y))
X && levl[x][y].typ == DRAWBRIDGE_DOWN)
X makeknown(obj->otyp);
X close_drawbridge(x,y);
X break;
X case WAN_STRIKING:
X case SPE_FORCE_BOLT:
X if (typ != DRAWBRIDGE_UP)
X destroy_drawbridge(x,y);
X makeknown(obj->otyp);
X break;
X }
X
X if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
X if(weapon != ZAPPED_WAND) {
X if(weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
X return(mtmp);
X }
X (*fhitm)(mtmp, obj);
X range -= 3;
X }
X if(fhito) {
X if(bhitpile(obj,fhito,bhitpos.x,bhitpos.y))
X range--;
X } else if(weapon == KICKED_WEAPON &&
X ((obj->otyp == GOLD_PIECE &&
X OBJ_AT(bhitpos.x, bhitpos.y)) ||
X down_gate(bhitpos.x, bhitpos.y) != -1)) {
X tmp_at(DISP_END, 0);
X return (struct monst *)0;
X }
X if(weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
X switch (obj->otyp) {
X case WAN_OPENING:
X case WAN_LOCKING:
X case WAN_STRIKING:
X case SPE_KNOCK:
X case SPE_WIZARD_LOCK:
X case SPE_FORCE_BOLT:
X if (doorlock(obj, bhitpos.x, bhitpos.y)) {
X if (cansee(bhitpos.x, bhitpos.y) ||
X (obj->otyp == WAN_STRIKING))
X makeknown(obj->otyp);
X if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
X && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
X shopdoor = TRUE;
X }
X }
X break;
X }
X }
X if(!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
X bhitpos.x -= ddx;
X bhitpos.y -= ddy;
X break;
X }
X if(weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
X tmp_at(bhitpos.x, bhitpos.y);
X delay_output();
X /* kicked objects fall in pools */
X if((weapon == KICKED_WEAPON) &&
X is_pool(bhitpos.x, bhitpos.y))
X break;
X#ifdef SINKS
X if(IS_SINK(typ) && weapon != FLASHED_LIGHT)
X break; /* physical objects fall onto sink */
X#endif
X }
X }
X
X if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
X
X if(shopdoor)
X pay_for_damage("destroy");
X
X return (struct monst *)0;
X}
X
Xstruct monst *
Xboomhit(dx, dy)
Xint dx, dy;
X{
X register int i, ct;
X int boom = S_boomleft; /* showsym[] index */
X struct monst *mtmp;
X
X bhitpos.x = u.ux;
X bhitpos.y = u.uy;
X
X for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break;
X tmp_at(DISP_FLASH, cmap_to_glyph(boom));
X for(ct=0; ct<10; ct++) {
X if(i == 8) i = 0;
X boom = (boom == S_boomleft) ? S_boomright : S_boomleft;
X tmp_at(DISP_CHANGE, cmap_to_glyph(boom));/* change glyph */
X dx = xdir[i];
X dy = ydir[i];
X bhitpos.x += dx;
X bhitpos.y += dy;
X if(MON_AT(bhitpos.x, bhitpos.y)) {
X mtmp = m_at(bhitpos.x,bhitpos.y);
X m_respond(mtmp);
X tmp_at(DISP_END, 0);
X return(mtmp);
X }
X if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ) ||
X closed_door(bhitpos.x, bhitpos.y)) {
X bhitpos.x -= dx;
X bhitpos.y -= dy;
X break;
X }
X if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
X if(Fumbling || rn2(20) >= ACURR(A_DEX)) {
X /* we hit ourselves */
X (void) thitu(10, rnd(10), (struct obj *)0,
X "boomerang");
X break;
X } else { /* we catch it */
X tmp_at(DISP_END, 0);
X pline("Skillfully, you catch the boomerang.");
X return(&youmonst);
X }
X }
X tmp_at(bhitpos.x, bhitpos.y);
X delay_output();
X if(ct % 5 != 0) i++;
X#ifdef SINKS
X if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ))
X break; /* boomerang falls on sink */
X#endif
X }
X tmp_at(DISP_END, 0); /* do not leave last symbol */
X return (struct monst *)0;
X}
X
Xstatic int
Xzhit(mon, type, nd) /* returns damage to mon */
Xregister struct monst *mon;
Xregister int type, nd;
X{
X register int tmp = 0;
X register int abstype = abs(type) % 10;
X
X switch(abstype) {
X case ZT_MAGIC_MISSILE:
X tmp = d(nd,6);
X break;
X case ZT_FIRE:
X if(resists_fire(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X if(resists_cold(mon->data)) tmp += 7;
X break;
X case ZT_COLD:
X if(resists_cold(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X if(resists_fire(mon->data)) tmp += d(nd, 3);
X break;
X case ZT_SLEEP:
X tmp = 0;
X if(resists_sleep(mon->data) ||
X resist(mon, (type == ZT_WAND(ZT_SLEEP)) ?
X WAND_CLASS : '\0', 0, NOTELL))
X shieldeff(mon->mx, mon->my);
X else if (mon->mcanmove) {
X int tmp2 = d(nd,25);
X mon->mcanmove = 0;
X if ((unsigned)mon->mfrozen + tmp2 > 127)
X mon->mfrozen = 127;
X else mon->mfrozen += tmp2;
X }
X break;
X case ZT_DEATH: /* death/disintegration */
X if(abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
X if(mon->data == &mons[PM_DEATH]) {
X mon->mhpmax += mon->mhpmax/2;
X mon->mhp = mon->mhpmax;
X tmp = 0;
X break;
X }
X if(is_undead(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X type = -1; /* so they don't get saving throws */
X } else {
X if (resists_disint(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X } else {
X tmp = MAGIC_COOKIE;
X break;
X }
X }
X tmp = mon->mhp+1;
X break;
X case ZT_LIGHTNING:
X if(resists_elec(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X if (haseyes(mon->data)) {
X register unsigned rnd_tmp = rnd(50);
X mon->mcansee = 0;
X if((mon->mblinded + rnd_tmp) > 127)
X mon->mblinded = 127;
X else mon->mblinded += rnd_tmp;
X }
X break;
X case ZT_POISON_GAS:
X if(resists_poison(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X break;
X case ZT_ACID:
X if(resists_acid(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X break;
X }
X#ifdef MULDGN
X if(pl_character[0] == 'K' && type >= 10 && type <= 19 &&
X u.uhave.questart) tmp *= 2;
X#endif
X if (type >= 0)
X if (resist(mon, (type < ZT_SPELL(0)) ? WAND_CLASS : '\0',
X 0, NOTELL)) tmp /= 2;
X mon->mhp -= tmp;
X return(tmp);
X}
X
X/*
X * burn scrolls and spell books on floor at position x,y
X * return the number of scrolls and spell books burned
X */
Xstatic int
Xburn_floor_paper(x, y)
Xint x, y;
X{
X register struct obj *obj, *obj2;
X register int cnt = 0;
X register long i, scrquan;
X
X for(obj = level.objects[x][y]; obj; obj = obj2) {
X obj2 = obj->nexthere;
X /* Bug fix - KAA */
X if(obj->oclass == SCROLL_CLASS
X || obj->oclass == SPBOOK_CLASS) {
X if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
X continue;
X scrquan = obj->quan;
X for(i = 1; i <= scrquan ; i++)
X if(!rn2(3)) {
X cnt++;
X /* not useupf(), which charges */
X if (obj->quan > 1L) obj->quan--;
X else delobj(obj);
X }
X }
X }
X return(cnt);
X}
X
X/* type == 0 to 9 : you shooting a wand */
X/* type == 10 to 19 : you casting a spell */
X/* type == 20 to 29 : you breathing as a monster */
X/* type == -10 to -19 : monster casting spell */
X/* type == -20 to -29 : monster breathing at you */
X/* type == -30 to -39 : monster shooting a wand (MUSE only) */
X/* called with dx = dy = 0 with vertical bolts */
Xvoid
Xbuzz(type,nd,sx,sy,dx,dy)
Xregister int type, nd;
Xregister xchar sx,sy;
Xregister int dx,dy;
X{
X int range, abstype = abs(type) % 10;
X struct rm *lev;
X register xchar lsx, lsy;
X struct monst *mon;
X boolean bodyhit = FALSE, shopdamage = FALSE;
X#ifdef MUSE
X register const char *fltxt = fl[(type <= -30) ? abstype : abs(type)];
X#else
X register const char *fltxt = fl[abs(type)];
X#endif
X if(u.uswallow) {
X register int tmp;
X
X if(type < 0) return;
X tmp = zhit(u.ustuck, type, nd);
X if(!u.ustuck) u.uswallow = 0;
X else pline("%s rips into %s%s",
X The(fltxt), mon_nam(u.ustuck), exclam(tmp));
X /* Using disintegration from the inside only makes a hole... */
X if (tmp == MAGIC_COOKIE)
X u.ustuck->mhp = 0;
X if (u.ustuck->mhp < 1)
X killed(u.ustuck);
X return;
X }
X if(type < 0) newsym(u.ux,u.uy);
X range = rn1(7,7);
X if(dx == 0 && dy == 0) range = 1;
X tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
X while(range-- > 0) {
X lsx = sx; sx += dx;
X lsy = sy; sy += dy;
X if(isok(sx,sy) && (lev = &levl[sx][sy])->typ) {
X if(cansee(sx,sy)) {
X if(ZAP_POS(lev->typ) || cansee(lsx,lsy))
X tmp_at(sx,sy);
X delay_output(); /* wait a little */
X }
X } else
X goto make_bounce;
X
X if (type != ZT_SPELL(ZT_FIRE))
X /* Fireballs only damage when they explode */
X range += zap_over_floor(sx, sy, type, &shopdamage);
X if ((mon = m_at(sx, sy)) != 0) {
X if (type == ZT_SPELL(ZT_FIRE)) break;
X if (type >= 0) mon->data->mflags3 &= ~M3_WAITMASK;
X if (rnd(20) < 18 + find_mac(mon)) {
X#ifdef MUSE
X struct obj *oshld = which_armor(mon, W_ARMS);
X
X if (oshld && oshld->otyp == SHIELD_OF_REFLECTION) {
X if(cansee(mon->mx,mon->my)) {
X hit(fltxt, mon, exclam(0));
X pline("But it reflects from %s shield!",
X s_suffix(mon_nam(mon)));
X makeknown(SHIELD_OF_REFLECTION);
X shieldeff(sx, sy);
X }
X
X dx = -dx;
X dy = -dy;
X } else
X#endif
X {
X register int tmp = zhit(mon, type, nd);
X
X if (is_rider(mon->data) && type == ZT_BREATH(ZT_DEATH)) {
X if(cansee(mon->mx, mon->my)) {
X hit(fltxt, mon, exclam(tmp));
X pline("%s disintegrates.", Monnam(mon));
X if(Blind)
X You("sense the fragments of %s body reassembling!",
X s_suffix(mon_nam(mon)));
X else
X pline("%s body fragments reassemble before your %s!",
X s_suffix(Monnam(mon)),
X makeplural(body_part(EYE)));
X pline("%s resurrects!", Monnam(mon));
X }
X mon->mhp = mon->mhpmax;
X break; /* Out of while loop */
X }
X if(mon->data == &mons[PM_DEATH] &&
X abs(type)%10 == ZT_DEATH) {
X if(cansee(mon->mx,mon->my)) {
X hit(fltxt, mon, exclam(tmp));
X pline("Death absorbs the deadly %s!",
X type == ZT_BREATH(ZT_DEATH) ?
X "blast" : "ray");
X pline("It seems even stronger than before.");
X }
X break; /* Out of while loop */
X }
X if (tmp == MAGIC_COOKIE) { /* disintegration */
X struct obj *otmp, *otmp2;
X pline("%s is disintegrated!", Monnam(mon));
X mon->mgold = 0;
X otmp = mon->minvent;
X while(otmp) {
X#ifdef MULDGN
X if (is_quest_artifact(otmp))
X otmp = otmp->nobj;
X else {
X#endif
X otmp2 = otmp;
X if (otmp == mon->minvent)
X mon->minvent = otmp->nobj;
X otmp = otmp->nobj;
X obfree(otmp2, (struct obj *)0);
X#ifdef MULDGN
X }
X#endif
X }
X if (type < 0)
X monkilled(mon, (char *)0, AD_RBRE);
X else
X xkilled(mon, 2);
X } else if(mon->mhp < 1) {
X if(type < 0)
X monkilled(mon, fltxt, AD_RBRE);
X else
X killed(mon);
X } else
X hit(fltxt, mon, exclam(tmp));
X }
X range -= 2;
X } else
X miss(fltxt,mon);
X } else if(sx == u.ux && sy == u.uy) {
X nomul(0);
X if(rnd(20) < 18+u.uac) {
X register int dam = 0;
X range -= 2;
X pline("%s hits you!", The(fltxt));
X if (Reflecting) {
X if (!Blind) {
X if(Reflecting & WORN_AMUL)
X makeknown(AMULET_OF_REFLECTION);
X else
X makeknown(SHIELD_OF_REFLECTION);
X pline("But it reflects from your %s!",
X (Reflecting & W_AMUL) ? "amulet" : "shield");
X } else
X pline("For some reason you are not affected.");
X dx = -dx;
X dy = -dy;
X shieldeff(sx, sy);
X }
X else switch(abstype) {
X case ZT_MAGIC_MISSILE:
X if(Antimagic) {
X shieldeff(sx, sy);
X pline("The missiles bounce off!");
X } else {
X dam = d(nd,6);
X exercise(A_STR, FALSE);
X }
X break;
X case ZT_FIRE:
X if(Fire_resistance) {
X shieldeff(sx, sy);
X You("don't feel hot!");
X#ifdef POLYSELF
X ugolemeffects(AD_FIRE, d(nd, 6));
X#endif
X } else dam = d(nd, 6);
X while (1) {
X switch(rn2(5)) {
X case 0:
X if (!rust_dmg(uarmh, "leather helmet", 0, FALSE))
X continue;
X break;
X case 1:
X bodyhit = TRUE;
X if (uarmc) break;
X if (uarm)
X (void)(rust_dmg(uarm, xname(uarm), 0, FALSE));
X break;
X case 2:
X if (!rust_dmg(uarms, "wooden shield", 0, FALSE))
X continue;
X break;
X case 3:
X if (!rust_dmg(uarmg, "gloves", 0, FALSE)) continue;
X break;
X case 4:
X if (!rust_dmg(uarmf, "boots", 0, FALSE)) continue;
X break;
X }
X break; /* Out of while loop */
X }
X if(!rn2(3) && bodyhit)
X destroy_item(POTION_CLASS, AD_FIRE);
X if(!rn2(3) && bodyhit)
X destroy_item(SCROLL_CLASS, AD_FIRE);
X if(!rn2(5) && bodyhit)
X destroy_item(SPBOOK_CLASS, AD_FIRE);
X break;
X case ZT_COLD:
X if(Cold_resistance) {
X shieldeff(sx, sy);
X You("don't feel cold.");
X#ifdef POLYSELF
X ugolemeffects(AD_COLD, d(nd, 6));
X#endif
X } else
X dam = d(nd, 6);
X if(!rn2(3))
X destroy_item(POTION_CLASS, AD_COLD);
X break;
X case ZT_SLEEP:
X if(Sleep_resistance) {
X shieldeff(u.ux, u.uy);
X You("don't feel sleepy.");
X } else {
X /* have to do this _before_ we reset multi */
X stop_occupation();
X nomul(-d(nd,25)); /* sleep ray */
X u.usleep = 1;
X nomovemsg = "You wake up.";
X }
X break;
X case ZT_DEATH:
X if(abs(type) == ZT_BREATH(ZT_DEATH)) {
X if (Disint_resistance) {
X You("are not disintegrated.");
X break;
X } else if(uarms) {
X (void) destroy_arm(uarms);
X break;
X } else if (uarm) {
X (void) destroy_arm(uarm);
X break;
X }
X }
X#ifdef POLYSELF
X else if(is_undead(uasmon)) {
X shieldeff(sx, sy);
X You("seem unaffected.");
X break;
X }
X#endif
X else if(Antimagic) {
X shieldeff(sx, sy);
X You("aren't affected.");
X } else
X u.uhp = -1;
X break;
X case ZT_LIGHTNING:
X if (Shock_resistance) {
X shieldeff(sx, sy);
X You("aren't affected.");
X#ifdef POLYSELF
X ugolemeffects(AD_ELEC, d(nd, 6));
X#endif
X } else {
X dam = d(nd, 6);
X exercise(A_CON, FALSE);
X }
X if(!rn2(3))
X destroy_item(WAND_CLASS, AD_ELEC);
X if(!rn2(3))
X destroy_item(RING_CLASS, AD_ELEC);
X break;
X case ZT_POISON_GAS:
X poisoned("blast", A_DEX, "poisoned blast", 15);
X break;
X case ZT_ACID:
X#ifdef POLYSELF
X if (resists_acid(uasmon))
X dam = 0;
X else
X#endif
X {
X pline("The acid burns!");
X dam = d(nd,6);
X exercise(A_STR, FALSE);
X }
X if(!rn2(6)) erode_weapon(TRUE);
X if(!rn2(6)) erode_armor(TRUE);
X break;
X }
X if(Half_spell_damage && dam &&
X type < 0 && (type > -20 || type < -29)) /* !Breath */
X dam = (dam+1) / 2;
X losehp(dam, fltxt, KILLED_BY_AN);
X } else pline("%s whizzes by you!", The(fltxt));
X if (abstype == ZT_LIGHTNING && !Blind) {
X You("are blinded by the flash!");
X make_blinded((long)d(nd,50),FALSE);
X }
X stop_occupation();
X nomul(0);
X }
X if(!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
X int bounce;
X uchar rmn;
X
X make_bounce:
X if (type == ZT_SPELL(ZT_FIRE)) {
X sx = lsx;
X sy = lsy;
X break; /* fireballs explode before the wall */
X }
X bounce = 0;
X range--;
X if(range && cansee(lsx,lsy))
X pline("%s bounces!", The(fltxt));
X if(!dx || !dy || !rn2(20)) {
X dx = -dx;
X dy = -dy;
X } else {
X if(isok(sx,lsy) && ZAP_POS(rmn = levl[sx][lsy].typ) &&
X (IS_ROOM(rmn) || (isok(sx+dx,lsy) &&
X ZAP_POS(levl[sx+dx][lsy].typ))))
X bounce = 1;
X if(isok(lsx,sy) && ZAP_POS(rmn = levl[lsx][sy].typ) &&
X (IS_ROOM(rmn) || (isok(lsx,sy+dy) &&
X ZAP_POS(levl[lsx][sy+dy].typ))))
X if(!bounce || rn2(2))
X bounce = 2;
X
X switch(bounce) {
X case 0: dx = -dx; /* fall into... */
X case 1: dy = -dy; break;
X case 2: dx = -dx; break;
X }
X tmp_at(DISP_CHANGE, zapdir_to_glyph(dx,dy,abstype));
X }
X }
X }
X tmp_at(DISP_END,0);
X if (type == ZT_SPELL(ZT_FIRE))
X explode(sx, sy, type, d(12,6), 0);
X if (shopdamage)
X pay_for_damage(abstype == ZT_FIRE ? "burn away" :
X abstype == ZT_COLD ? "shatter" :
X abstype == ZT_DEATH ? "disintegrate" : "destroy");
X}
X
X/* Burn floor scrolls, evaporate pools, etc... in a single square. Used
X * both for normal bolts of fire, cold, etc... and for fireballs.
X * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
X * amount by which range is reduced (the latter is just ignored by fireballs)
X */
Xint
Xzap_over_floor(x, y, type, shopdamage)
Xxchar x, y;
Xint type;
Xboolean *shopdamage;
X{
X struct monst *mon;
X int abstype = abs(type) % 10;
X struct rm *lev = &levl[x][y];
X int rangemod = 0;
X
X if(abstype == ZT_FIRE) {
X if(is_ice(x, y)) {
X if (lev->typ == DRAWBRIDGE_UP)
X lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
X else { /* lev->typ == ICE */
X#ifdef STUPID
X if (lev->icedpool == ICED_POOL) lev->typ = POOL;
X else lev->typ = MOAT;
X#else
X lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
X#endif
X lev->icedpool = 0;
X }
X newsym(x,y);
X Norep("The ice crackles and melts.");
X if (x == u.ux && y == u.uy)
X spoteffects(); /* possibly drown */
X } else if(is_pool(x,y)) {
X const char *msgtxt = "You hear a hissing sound.";
X if(lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
X if (cansee(x,y)) msgtxt = "Some water evaporates.";
X } else {
X register struct trap *ttmp;
X
X rangemod -= 3;
X lev->typ = ROOM;
X ttmp = maketrap(x, y, PIT);
X ttmp->tseen = 1;
X if (cansee(x,y)) msgtxt = "The water evaporates.";
X }
X Norep(msgtxt);
X if (lev->typ == ROOM) newsym(x,y);
X }
X }
X else if(abstype == ZT_COLD && (is_pool(x,y) || is_lava(x,y))) {
X boolean lava = is_lava(x,y);
X boolean moat = (!lava && (lev->typ != POOL) &&
X (lev->typ != WATER) &&
X !Is_medusa_level(&u.uz) &&
X !Is_waterlevel(&u.uz));
X
X if (lev->typ == WATER) {
X /* For now, don't let WATER freeze. */
X if (cansee(x,y))
X pline("The water freezes for a moment.");
X else
X You("hear a soft crackling sound");
X rangemod -= 1000; /* stop */
X } else {
X rangemod -= 3;
X if (lev->typ == DRAWBRIDGE_UP) {
X lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
X } else {
X if (!lava)
X lev->icedpool =
X (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
X lev->typ = (lava ? ROOM : ICE);
X }
X /*
X * Not perfect: There could be stuff on the bottom. If
X * we leave it here, it'll pop to the surface which is
X * strange, so just destroy all the objects at this location.
X * A better solution requires major changes (as usual).
X */
X if(OBJ_AT(x,y))
X delallobj(x,y);
X if(cansee(x,y)) {
X if(moat)
X Norep("The moat is bridged with ice!");
X else if(lava)
X Norep("The lava cools and solidifies.");
X else
X Norep("The water freezes.");
X newsym(x,y);
X } else if(flags.soundok && !lava)
X You("hear a crackling sound.");
X if(x == u.ux && y == u.uy &&
X u.utrap && u.utraptype == TT_LAVA) {
X#ifdef POLYSELF
X if (passes_walls(uasmon))
X You("pass through the now-solid rock.");
X else {
X#endif
X u.utrap = rn1(50,20);
X u.utraptype = TT_INFLOOR;
X You("are firmly stuck in the cooling rock.");
X#ifdef POLYSELF
X }
X#endif
X }
X }
X }
X if(closed_door(x, y)) {
X rangemod = -1000;
X switch(abstype) {
X case ZT_FIRE:
X if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
X add_damage(x, y, 400L);
X *shopdamage = TRUE;
X }
X lev->doormask = D_NODOOR;
X unblock_point(x,y); /* vision */
X if(cansee(x,y)) {
X pline("The door is consumed in flames!");
X newsym(x,y);
X }
X else You("smell smoke.");
X break;
X case ZT_COLD:
X if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
X add_damage(x, y, 400L);
X *shopdamage = TRUE;
X }
X lev->doormask = D_NODOOR;
X unblock_point(x,y); /* vision */
X if(cansee(x,y)) {
X pline("The door freezes and shatters!");
X newsym(x,y);
X }
X else You("feel cold.");
X break;
X case ZT_DEATH:
X /* death spells/wands don't disintegrate */
X if(abs(type) != ZT_BREATH(ZT_DEATH))
X goto def_case;
X if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
X add_damage(x, y, 400L);
X *shopdamage = TRUE;
X }
X lev->doormask = D_NODOOR;
X unblock_point(x,y); /* vision */
X if(cansee(x,y)) {
X pline("The door disintegrates!");
X newsym(x,y);
X }
X else if(flags.soundok)
X You("hear a crashing sound.");
X break;
X case ZT_LIGHTNING:
X if(type >= 0 && *in_rooms(x, y, SHOPBASE)) {
X add_damage(x, y, 400L);
X *shopdamage = TRUE;
X }
X lev->doormask = D_BROKEN;
X unblock_point(x,y); /* vision */
X if(cansee(x,y)) {
X pline("The door splinters!");
X newsym(x,y);
X }
X else if(flags.soundok)
X You("hear a crackling sound.");
X break;
X default:
X def_case:
X if(cansee(x,y)) {
X pline("The door absorbs %s %s!",
X (type < 0) ? "the" : "your",
X abs(type) < ZT_SPELL(0) ? "bolt" :
X abs(type) < ZT_BREATH(0) ? "spell" :
X "blast");
X } else You("feel vibrations.");
X break;
X }
X }
X if(OBJ_AT(x, y) && abstype == ZT_FIRE)
X if(burn_floor_paper(x,y) && cansee(x,y)) {
X newsym(x,y);
X if(!Blind)
X You("see a puff of smoke.");
X }
X if ((mon = m_at(x,y)) != 0) {
X /* Cannot use wakeup() which also angers the monster */
X mon->msleep = 0;
X if(mon->m_ap_type) seemimic(mon);
X if(type >= 0) {
X setmangry(mon);
X if(mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
X ghod_hitsu(mon);
X if(mon->isshk && !*u.ushops)
X hot_pursuit(mon);
X }
X }
X return rangemod;
X}
X
Xvoid
Xrloco(obj)
Xregister struct obj *obj;
X{
X register xchar tx, ty, otx, oty;
X
X otx = obj->ox;
X oty = obj->oy;
X do {
X tx = rn1(COLNO-3,2);
X ty = rn2(ROWNO);
X } while(!goodpos(tx,ty,(struct monst *)0, (struct permonst *)0));
X freeobj(obj);
X if (flooreffects(obj, tx, ty, "fall"))
X return;
X if(costly_spot(otx, oty) && (!costly_spot(tx, ty) ||
X !index(in_rooms(tx, ty, 0),
X *in_rooms(otx, oty, 0)))) {
X if(costly_spot(u.ux, u.uy) &&
X index(u.urooms, *in_rooms(otx, oty, 0)))
X addtobill(obj, FALSE, FALSE, FALSE);
X else (void)stolen_value(obj, otx, oty, FALSE, FALSE);
X }
X obj->nobj = fobj;
X fobj = obj;
X place_object(obj, tx, ty);
X newsym(otx, oty);
X newsym(tx,ty);
X}
X
Xvoid
Xfracture_rock(obj) /* fractured by pick-axe or wand of striking */
Xregister struct obj *obj; /* no texts here! */
X{
X obj->otyp = ROCK;
X obj->quan = (long) rn1(60, 7);
X obj->owt = weight(obj);
X obj->oclass = GEM_CLASS;
X obj->known = FALSE;
X obj->onamelth = 0; /* no names */
X if(!does_block(obj->ox,obj->oy,&levl[obj->ox][obj->oy]))
X unblock_point(obj->ox,obj->oy);
X if(cansee(obj->ox,obj->oy))
X newsym(obj->ox,obj->oy);
X}
X
Xboolean
Xbreak_statue(obj)
Xregister struct obj *obj;
X{
X struct trap *trap;
X struct obj *item, *nitem;
X
X if((trap = t_at(obj->ox,obj->oy)) && trap->ttyp == STATUE_TRAP)
X if(makemon(&mons[obj->corpsenm], obj->ox, obj->oy)) {
X pline("Instead of shattering, the statue suddenly comes alive!");
X delobj(obj);
X deltrap(trap);
X return FALSE;
X }
X for(item = obj->cobj; item; item = nitem) {
X nitem = item->nobj;
X item->nobj = fobj;
X fobj = item;
X place_object(item, obj->ox, obj->oy);
X }
X obj->cobj = (struct obj *)0;
X fracture_rock(obj);
X return TRUE;
X}
X
Xconst char *destroy_strings[] = {
X "freezes and shatters", "freeze and shatter", "shattered potion",
X "boils and explodes", "boil and explode", "boiling potion",
X "catches fire and burns", "catch fire and burn", "burning scroll",
X "catches fire and burns", "catch fire and burn", "burning book",
X "turns to dust and vanishes", "turn to dust and vanish", "",
X "breaks apart and explodes", "break apart and explode", "exploding wand"
X};
X
Xvoid
Xdestroy_item(osym, dmgtyp)
Xregister int osym, dmgtyp;
X{
X register struct obj *obj, *obj2;
X register int dmg, xresist, skip;
X register long i, cnt, quan;
X register int dindx;
X const char *mult;
X
X for(obj = invent; obj; obj = obj2) {
X
X obj2 = obj->nobj;
X if(obj->oclass != osym) continue; /* test only objs of type osym */
X if(obj->oartifact) continue; /* don't destroy artifacts */
X xresist = skip = 0;
X#ifdef GCC_WARN
X dmg = dindx = 0;
X quan = 0L;
X#endif
X switch(dmgtyp) {
X case AD_COLD:
X if(osym == POTION_CLASS) {
X quan = obj->quan;
X dindx = 0;
X dmg = rnd(4);
X } else skip++;
X break;
X case AD_FIRE:
X xresist = (Fire_resistance && obj->oclass != POTION_CLASS);
X
X if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
X skip++;
X if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
X skip++;
X if (!Blind)
X pline("%s glows a strange %s, but remains intact.",
X The(xname(obj)),
X Hallucination ? hcolor() : "dark red");
X }
X quan = obj->quan;
X switch(osym) {
X case POTION_CLASS:
X dindx = 1;
X dmg = rnd(6);
X break;
X case SCROLL_CLASS:
X dindx = 2;
X dmg = 1;
X break;
X case SPBOOK_CLASS:
X dindx = 3;
X dmg = 1;
X break;
X default:
X skip++;
X break;
X }
X break;
X case AD_ELEC:
X xresist = (Shock_resistance && obj->oclass != RING_CLASS);
X quan = obj->quan;
X switch(osym) {
X case RING_CLASS:
X if(obj->otyp == RIN_SHOCK_RESISTANCE)
X { skip++; break; }
X dindx = 4;
X dmg = 0;
X break;
X case WAND_CLASS:
X if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
X dindx = 5;
X dmg = rnd(10);
X break;
X default:
X skip++;
X break;
X }
X break;
X default:
X skip++;
X break;
X }
X if(!skip) {
X for(i = cnt = 0L; i < quan; i++)
X if(!rn2(3)) cnt++;
X
X if(!cnt) continue;
X if(cnt == quan) mult = "Your";
X else mult = (cnt == 1L) ? "One of your" : "Some of your";
X pline("%s %s %s!", mult, xname(obj),
X (cnt > 1L) ? destroy_strings[dindx*3 + 1]
X : destroy_strings[dindx*3]);
X if(osym == POTION_CLASS && dmgtyp != AD_COLD)
X potionbreathe(obj);
X for(i = 0; i < cnt; i++) {
X if (obj->owornmask) {
X if (obj->owornmask & W_RING) /* ring being worn */
X Ring_gone(obj);
X else
X setnotworn(obj);
X }
X useup(obj);
X }
X if(dmg) {
X if(xresist) You("aren't hurt!");
X else {
X losehp(dmg, (cnt==1L) ? destroy_strings[dindx*3 + 2] :
X (const char *)makeplural(destroy_strings[dindx*3 + 2]),
X (cnt==1L) ? KILLED_BY_AN : KILLED_BY);
X exercise(A_STR, FALSE);
X }
X }
X }
X }
X return;
X}
X
Xint
Xdestroy_mitem(mtmp, osym, dmgtyp)
Xregister struct monst *mtmp;
Xregister int osym, dmgtyp;
X{
X register struct obj *obj, *obj2;
X register int skip, tmp = 0;
X register long i, cnt, quan;
X register int dindx;
X boolean vis=canseemon(mtmp);
X
X for(obj = mtmp->minvent; obj; obj = obj2) {
X
X obj2 = obj->nobj;
X if(obj->oclass != osym) continue; /* test only objs of type osym */
X skip = 0;
X#ifdef GCC_WARN
X quan = 0L;
X dindx = 0;
X#endif
X switch(dmgtyp) {
X case AD_COLD:
X if(osym == POTION_CLASS) {
X quan = obj->quan;
X dindx = 0;
X tmp++;
X } else skip++;
X break;
X case AD_FIRE:
X if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
X skip++;
X if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
X skip++;
X if (vis)
X pline("%s glows a strange %s, but remains intact.",
X The(distant_name(obj, xname)),
X Hallucination ? hcolor() : "dark red");
X }
X quan = obj->quan;
X switch(osym) {
X case POTION_CLASS:
X dindx = 1;
X tmp++;
X break;
X case SCROLL_CLASS:
X dindx = 2;
X tmp++;
X break;
X case SPBOOK_CLASS:
X dindx = 3;
X tmp++;
X break;
X default:
X skip++;
X break;
X }
X break;
X case AD_ELEC:
X quan = obj->quan;
X switch(osym) {
X case RING_CLASS:
X if(obj->otyp == RIN_SHOCK_RESISTANCE)
X { skip++; break; }
X dindx = 4;
X break;
X case WAND_CLASS:
X if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
X dindx = 5;
X tmp++;
X break;
X default:
X skip++;
X break;
X }
X break;
X default:
X skip++;
X break;
X }
X if(!skip) {
X for(i = cnt = 0L; i < quan; i++)
X if(!rn2(3)) cnt++;
X
X if(!cnt) continue;
X if (vis) pline("%s %s %s!",
X s_suffix(Monnam(mtmp)), xname(obj),
X (cnt > 1L) ? destroy_strings[dindx*3 + 1]
X : destroy_strings[dindx*3]);
X for(i = 0; i < cnt; i++) m_useup(mtmp, obj);
X }
X }
X return(tmp);
X}
X
X/*ARGSUSED*/
Xint
Xresist(mtmp, class, damage, tell)
Xregister struct monst *mtmp;
Xregister char class;
Xregister int damage, tell;
X{
X register int resisted;
X register int lev;
X
X switch(class) {
X
X case WAND_CLASS:
X lev = 8;
X break;
X
X case SCROLL_CLASS:
X lev = 6;
X break;
X
X case POTION_CLASS:
X lev = 5;
X break;
X
X default: lev = u.ulevel;
X break;
X }
X
X resisted = (rn2(100) - (unsigned)mtmp->m_lev + lev) < mtmp->data->mr;
X if(resisted) {
X
X if(tell) {
X shieldeff(mtmp->mx, mtmp->my);
X pline("%s resists!", Monnam(mtmp));
X }
X mtmp->mhp -= damage/2;
X } else mtmp->mhp -= damage;
X
X#ifdef MUSE
X if(mtmp->mhp < 1) {
X if(m_using) monkilled(mtmp, "", AD_RBRE);
X else killed(mtmp);
X }
X#else
X if(mtmp->mhp < 1) killed(mtmp);
X#endif
X return(resisted);
X}
X
Xvoid
Xmakewish()
X{
X char buf[BUFSZ];
X register struct obj *otmp;
X int tries = 0;
X
X if (flags.verbose) You("may wish for an object.");
Xretry:
X getlin("For what do you wish?", buf);
X if(buf[0] == '\033') buf[0] = 0;
X /*
X * Note: if they wished for and got a non-object successfully,
X * otmp == &zeroobj
X */
X otmp = readobjnam(buf);
X if (!otmp) {
X pline("Nothing fitting that description exists in the game.");
X if (++tries < 5) goto retry;
X pline(thats_enough_tries);
X if (!(otmp = readobjnam((char *)0)))
X return; /* for safety; should never happen */
X }
X if (otmp != &zeroobj) {
X if(otmp->oartifact && !touch_artifact(otmp,&youmonst))
X dropy(otmp);
X else
X /* The(aobjnam()) is safe since otmp is unidentified -dlc */
X (void) hold_another_object(otmp, u.uswallow ?
X "Oops! %s out of your reach!" :
X Is_airlevel(&u.uz) ?
X "Oops! %s out of your grasp!" :
X "Oops! %s to the floor!",
X The(aobjnam(otmp, Is_airlevel(&u.uz) ?
X "slip" : "drop")),
X (const char *)0);
X u.ublesscnt += rn1(100,50); /* the gods take notice */
X }
X}
X
X/*zap.c*/
END_OF_FILE
if test 32988 -ne `wc -c <'src/zap.c2'`; then
echo shar: \"'src/zap.c2'\" unpacked with wrong size!
fi
# end of 'src/zap.c2'
fi
echo shar: End of archive 61 \(of 108\).
cp /dev/null ark61isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone 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