[comp.sources.games] v10i048: nethack3p9 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 48
Archive-name: nethack3p9/Part03
Supersedes: NetHack3: Volume 7, Issue 56-93



#! /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 3 (of 56)."
# Contents:  others/pcunix.c src/zap.c
# Wrapped by billr@saab on Wed Jul 11 17:10:52 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'others/pcunix.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'others/pcunix.c'\"
else
echo shar: Extracting \"'others/pcunix.c'\" \(4479 characters\)
sed "s/^X//" >'others/pcunix.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)pcunix.c	3.0	89/12/29
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
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 "hack.h"	/* mainly for index() which depends on BSD */
X
X#ifndef MACOS
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#endif
X
Xstatic struct tm * NDECL(getlt);
X
X#ifdef OVLB
X
X#ifndef MACOS
Xstatic struct stat buf;
X# ifdef WANT_GETHDATE
Xstatic struct stat hbuf;
X# endif
X#endif
X
Xvoid
Xsetrandom()
X{
X	(void) Srand((int) time ((time_t *) 0));
X}
X
Xstatic struct tm *
Xgetlt()
X{
X	time_t date;
X
X	(void) time(&date);
X	return(localtime(&date));
X}
X
Xint
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	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
Xint
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
Xint
Xnight()
X{
X	register int hour = getlt()->tm_hour;
X
X	return(hour < 6 || hour > 21);
X}
X
Xint
Xmidnight()
X{
X	return(getlt()->tm_hour == 0);
X}
X
X#ifndef MACOS
Xvoid
Xgethdate(name)
Xchar *name;
X{
X# ifdef WANT_GETHDATE
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 * 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
X    register char *np, *path;
X    char filename[MAXPATHLEN+1], *getenv();
X
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	    Strcpy(filename, name);
X	else {
X	    (void) strncpy(filename, path, np - path);
X	    filename[np - path] = '/';
X	    Strcpy(filename + (np - path) + 1, name);
X	}
X	if (stat(filename, &hbuf) == 0)
X	    return;
X	if (*np == '\0')
X	path = "";
X	path = np + 1;
X    }
X    error("Cannot get status of %s.", (np = rindex(name, '/')) ? np+1 : name);
X# endif /* WANT_GETHDATE */
X}
X
Xint
Xuptodate(fd)
Xint fd;
X{
X# ifdef WANT_GETHDATE
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# else
X#  if defined(MSDOS) && !defined(NO_FSTAT)
X    if(fstat(fd, &buf)) {
X	if(moves > 1) pline("Cannot get status of saved level? ");
X	else pline("Cannot get status of saved game");
X	return(0);
X    } 
X    if(comp_times(buf.st_mtime)) { 
X	if(moves > 1) pline("Saved level is out of date");
X	else pline("Saved game is out of date. ");
X	return(0);
X    }
X#  endif  /* MSDOS /* */
X# endif /* WANT_GETHDATE */
X    return(1);
X}
X#endif	/* MACOS /* */
X
Xvoid
Xregularize(s)
X/*
X * normalize file name - we don't like .'s, /'s, :'s [Mac], or spaces,
X * and in msdos / OS/2 we really get picky
X */
Xregister char *s;
X{
X	register char *lp;
X
X#ifdef MSDOS
X	for (lp = s; *lp; lp++)
X		if (*lp <= ' ' || *lp == '"' || (*lp >= '*' && *lp <= ',') ||
X		    *lp == '.' || *lp == '/' || (*lp >= ':' && *lp <= '?') ||
X# ifdef OS2
X		    *lp == '&' || *lp == '(' || *lp == ')' ||
X# endif
X		    *lp == '|' || *lp >= 127 || (*lp >= '[' && *lp <= ']'))
X                        *lp = '_';
X#else
X	while((lp=index(s, '.')) || (lp=index(s, '/')) || (lp=index(s,' '))
X# ifdef MACOS
X	   || (lp=index(s, ':'))
X# endif
X		) *lp = '_';
X#endif
X}
X
X#endif /* OVLB */
END_OF_FILE
if test 4479 -ne `wc -c <'others/pcunix.c'`; then
    echo shar: \"'others/pcunix.c'\" unpacked with wrong size!
fi
# end of 'others/pcunix.c'
fi
if test -f 'src/zap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/zap.c'\"
else
echo shar: Extracting \"'src/zap.c'\" \(50988 characters\)
sed "s/^X//" >'src/zap.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)zap.c	3.0	89/11/08
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#if defined(ALTARS) && defined(THEOLOGY)
Xstatic boolean NEARDATA priesthit = FALSE;
X#endif
X
Xstatic int FDECL(burn_floor_paper,(int,int));
XSTATIC_PTR int FDECL(bhitm,(struct monst *,struct obj *));
Xstatic void FDECL(cancel_item,(struct obj *));
Xstatic int FDECL(bhitgold,(struct gold *,struct obj *));
XSTATIC_PTR int FDECL(bhito,(struct obj *,struct obj *));
Xstatic void FDECL(backfire,(struct obj *));
Xstatic uchar FDECL(dirlet,(int,int));
Xstatic int FDECL(zhit,(struct monst *,int,int));
X
Xconst char *fl[]= {
X	"magic missile",	/* Wands must be 0-9 */
X	"bolt of fire",
X	"sleep ray",
X	"bolt of cold",
X	"death ray",
X	"bolt of lightning",
X	"",
X	"",
X	"",
X	"",
X
X	"magic missile",	/* Spell equivalents must be 10-19 */
X	"fireball",
X	"sleep ray",
X	"cone of cold",
X	"finger of death",
X	"bolt of lightning",
X	"",
X	"",
X	"",
X	"",
X
X	"blast of missiles",	/* Dragon breath equivalents 20-29*/
X	"blast of fire",
X	"blast of sleep gas",
X	"blast of frost",
X	"blast of disintegration",
X	"blast of lightning",
X	"blast of poison gas",
X	"blast of acid",
X	"",
X	""
X};
X
X#ifdef TEXTCOLOR
Xstatic const int zapcolor[10] = {
X	AT_ZAP, RED|BRIGHT, AT_ZAP, WHITE|BRIGHT, AT_ZAP, WHITE|BRIGHT,
X	AT_ZAP, AT_ZAP, AT_ZAP, AT_ZAP
X};
X#endif
X
X/* Routines for IMMEDIATE wands and spells. */
X/* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
XSTATIC_PTR
Xint
Xbhitm(mtmp, otmp)
Xregister struct monst *mtmp;
Xregister struct obj *otmp;
X{
X	wakeup(mtmp);
X	switch(otmp->otyp) {
X	case WAN_STRIKING:
X#ifdef SPELLS
X	case SPE_FORCE_BOLT:
X#endif
X		if(u.uswallow || rnd(20) < 10+mtmp->data->ac) {
X			register int tmp = d(2,12);
X			hit((otmp->otyp == WAN_STRIKING) ? "wand" : "spell", mtmp, exclam(tmp));
X			(void) resist(mtmp, otmp->olet, tmp, TELL);
X		} else miss((otmp->otyp == WAN_STRIKING) ? "wand" : "spell", mtmp);
X		break;
X	case WAN_SLOW_MONSTER:
X#ifdef SPELLS
X	case SPE_SLOW_MONSTER:
X#endif
X		if(! resist(mtmp, otmp->olet, 0, NOTELL)) {
X			if (mtmp->mspeed == MFAST) mtmp->mspeed = 0;
X			else mtmp->mspeed = MSLOW;
X			if (u.uswallow && (mtmp == u.ustuck) && 
X			    is_whirly(mtmp->data)) {
X				You("disrupt %s!", mon_nam(mtmp));
X				pline("A huge hole opens up...");
X				expels(mtmp, mtmp->data, TRUE);
X			}
X		}
X		break;
X	case WAN_SPEED_MONSTER:
X		if (!resist(mtmp, otmp->olet, 0, NOTELL))
X			if (mtmp->mspeed == MSLOW) mtmp->mspeed = 0;
X			else mtmp->mspeed = MFAST;
X		break;
X	case WAN_UNDEAD_TURNING:
X#ifdef SPELLS
X	case SPE_TURN_UNDEAD:
X#endif
X		if(is_undead(mtmp->data)) {
X
X			if(!resist(mtmp, otmp->olet, rnd(8), NOTELL))
X				mtmp->mflee = 1;
X		}
X		break;
X	case WAN_POLYMORPH:
X#ifdef SPELLS
X	case SPE_POLYMORPH:
X#endif
X		if(!resist(mtmp, otmp->olet, 0, NOTELL))
X		    if( newcham(mtmp, (struct permonst *)0) )
X			if (!Hallucination)
X			    makeknown(otmp->otyp);
X		break;
X	case WAN_CANCELLATION:
X#ifdef SPELLS
X	case SPE_CANCELLATION:
X#endif
X		if(!resist(mtmp, otmp->olet, 0, NOTELL)) {
X		  if (is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
X		    were_change(mtmp);
X#ifdef GOLEMS
X		  if (mtmp->data == &mons[PM_CLAY_GOLEM]) {
X		    if (!Blind)
X		      pline("Some writing vanishes from %s's head!",
X			mon_nam(mtmp));
X		    killed(mtmp);
X		  }
X		  else
X#endif /* GOLEMS */
X		    mtmp->mcan = 1;
X		}
X		break;
X	case WAN_TELEPORTATION:
X#ifdef SPELLS
X	case SPE_TELEPORT_AWAY:
X#endif
X#if defined(ALTARS) && defined(THEOLOGY)
X		if(mtmp->ispriest && in_temple(mtmp->mx, mtmp->my)) {
X		    kludge("%s resists your magic!", Monnam(mtmp));
X		    wakeup(mtmp);
X		    break;
X		}
X#endif
X		rloc(mtmp);
X		break;
X	case WAN_MAKE_INVISIBLE:
X		mtmp->minvis = 1;
X		break;
X	case WAN_NOTHING:
X		break;
X#ifdef PROBING
X	case WAN_PROBING:
X		makeknown(otmp->otyp);
X		mstatusline(mtmp);
X		break;
X#endif
X	case WAN_OPENING:
X		if(u.uswallow && mtmp == u.ustuck) {
X			if (is_animal(mtmp->data)) {
X				if (Blind) pline("Its mouth opens!");
X				else pline("%s opens its mouth!", Monnam(mtmp));
X			}
X			expels(mtmp, mtmp->data, TRUE);
X			break;
X		}
X	case WAN_LOCKING:
X#ifdef SPELLS
X	case SPE_KNOCK:
X	case SPE_WIZARD_LOCK:
X#endif
X		break;
X	default:
X		impossible("What an interesting effect (%u)", otmp->otyp);
X	}
X	return 0;
X}
X
Xstruct monst *
Xrevive(obj,ininv)
Xregister struct obj *obj;
Xboolean ininv;
X{
X	register struct monst *mtmp = (struct monst *)0;
X
X	if(obj->otyp == CORPSE) {
X		int montype = obj->corpsenm;
X		int x = ininv ? u.ux : obj->ox;
X		int y = ininv ? u.uy : obj->oy;
X
X		if (cant_create(&montype)) { /* will make zombie instead */
X			mtmp = makemon(&mons[PM_HUMAN_ZOMBIE], x, y);
X			if (mtmp) {
X				mtmp->mhp = mtmp->mhpmax = 100;
X				mtmp->mspeed = MFAST;
X			}
X		} else {
X			struct obj *otmp;
X#ifdef ARMY
X			if (is_mercenary(&mons[montype]))
X				montype = PM_UNARMORED_SOLDIER;
X#endif
X			mtmp = makemon(&mons[montype], x, y);
X			if (mtmp) {
X				/* Monster retains its name */
X				if (obj->onamelth)
X					mtmp = christen_monst(mtmp, ONAME(obj));
X				/* No inventory for newly revived monsters */
X				while(otmp = (mtmp->minvent)) {
X					mtmp->minvent = otmp->nobj;
X					free((genericptr_t)otmp);
X				}
X			}
X		}
X		if (mtmp && obj->oeaten)
X			mtmp->mhp = eaten_stat(mtmp->mhp, obj);
X		if (ininv) useup(obj);
X		else {
X			/* not useupf(), which charges */
X			if (obj->quan > 1) obj->quan--;
X			else delobj(obj);
X		}
X		if (x != u.ux || y != u.uy || Invisible)
X			newsym(x, y);
X	}
X	return mtmp;
X}
X
Xstatic const char NEARDATA charged_objs[] = { WAND_SYM, WEAPON_SYM, ARMOR_SYM, 0 };
X
Xstatic void
Xcancel_item(obj)
Xregister struct obj *obj;
X{
X	switch(obj->otyp) {
X		case RIN_GAIN_STRENGTH:
X			if(obj->owornmask & W_RING) {
X				ABON(A_STR) -= obj->spe;
X				flags.botl = 1;
X			}
X			break;
X		case RIN_ADORNMENT:
X			if(obj->owornmask & W_RING) {
X				ABON(A_CHA) -= obj->spe;
X				flags.botl = 1;
X			}
X			break;
X		case RIN_INCREASE_DAMAGE:
X			if(obj->owornmask & W_RING)
X				u.udaminc -= obj->spe;
X			break;
X		case GAUNTLETS_OF_DEXTERITY:
X			if(obj->owornmask & W_ARMG) {
X				ABON(A_DEX) -= obj->spe;
X				flags.botl = 1;
X			}
X			break;
X		case HELM_OF_BRILLIANCE:
X			if(obj->owornmask & W_ARMH) {
X				ABON(A_INT) -= obj->spe;
X				ABON(A_WIS) -= obj->spe;
X				flags.botl = 1;
X			}
X			break;
X		/* case RIN_PROTECTION: /* not needed */
X	}
X	if(obj->spe &&
X	  !(obj->otyp == AMULET_OF_YENDOR ||
X	    obj->otyp == WAN_CANCELLATION || /* can't cancel cancellation */
X	    obj->otyp == TIN || obj->otyp == EGG ||
X	    obj->otyp == STATUE ||
X#ifdef MAIL
X	    obj->otyp == SCR_MAIL ||
X#endif
X#ifdef TUTTI_FRUTTI
X	    obj->otyp == SLIME_MOLD ||
X#endif
X	    obj->otyp == KEY || obj->otyp == SKELETON_KEY ||
X	    obj->otyp == LARGE_BOX || obj->otyp == CHEST))
X		obj->spe = (obj->olet == WAND_SYM) ? -1 : 0;
X
X	if (obj->olet == SCROLL_SYM
X#ifdef MAIL
X	    && obj->otyp != SCR_MAIL
X#endif
X	   )
X	    obj->otyp = SCR_BLANK_PAPER;
X
X	if (obj->olet == POTION_SYM && obj->otyp > POT_BOOZE)
X	    obj->otyp = (obj->otyp==POT_SICKNESS || obj->otyp==POT_SEE_INVISIBLE) ? POT_FRUIT_JUICE : POT_WATER;
X	    /* sickness is "biologically contaminated" fruit juice; cancel it
X	     * and it just becomes fruit juice... whereas see invisible
X	     * tastes like "enchanted" fruit juice, it similarly cancels.
X	     */
X	obj->blessed = obj->cursed = FALSE;
X}
X
Xstatic int
Xbhitgold(gold, otmp)
Xregister struct gold *gold;
Xregister struct obj *otmp;
X{
X	switch(otmp->otyp) {
X	case WAN_TELEPORTATION:
X#ifdef SPELLS
X	case SPE_TELEPORT_AWAY:
X#endif
X		rlocgold(gold);
X		break;
X	}
X	return 1;
X}
X
XSTATIC_PTR
Xint
Xbhito(obj, otmp)	/* object obj was hit by the effect of wand otmp */
Xregister struct obj *obj, *otmp;	/* returns TRUE if sth was done */
X{
X	register int res = 1;
X	struct obj *otmp2;
X
X	if(obj == uball || obj == uchain)
X		res = 0;
X	else
X	switch(otmp->otyp) {
X	case WAN_POLYMORPH:
X#ifdef SPELLS
X	case SPE_POLYMORPH:
X#endif
X		/* avoid unicorn/tool abuse */
X		if (obj->otyp == UNICORN_HORN) obj->olet = WEAPON_SYM;
X
X		/* preserve symbol and quantity */
X		otmp2 = mkobj_at(obj->olet, obj->ox, obj->oy, FALSE);
X		otmp2->quan = obj->quan;
X#ifdef MAIL
X		/* You can't send yourself 100 mail messages and then
X		 * polymorph them into useful scrolls
X		 */
X		if (obj->otyp == SCR_MAIL) {
X			otmp2->otyp = SCR_MAIL;
X			otmp2->spe = 1;
X		}
X#endif
X		/* keep special fields (including charges on wands) */
X		if (index(charged_objs, otmp2->olet)) otmp2->spe = obj->spe;
X
X		/* Amulet gets cheap   stewr 870807 */
X		if (obj->otyp == AMULET_OF_YENDOR) otmp2->spe = -1;
X
X		otmp2->cursed = obj->cursed;
X		otmp2->blessed = obj->blessed;
X		otmp2->rustfree = obj->rustfree;
X
X		/* Keep chest/box traps and poisoned ammo if we may */
X		if (obj->otrapped && Is_box(otmp2))
X			otmp2->otrapped = 1;
X		if (obj->opoisoned && 
X		    (otmp2->olet == WEAPON_SYM && otmp2->otyp <= SHURIKEN))
X			otmp2->opoisoned = 1;
X
X		if (obj->otyp == CORPSE){
X		    /* Turn dragon corpses into dragon armors */
X		    if (obj->corpsenm >= PM_GRAY_DRAGON
X				&& obj->corpsenm <= PM_YELLOW_DRAGON) {
X			if (!rn2(10)) { /* Random failure */
X				otmp2->otyp = TIN;
X				otmp2->known = otmp2->dknown = 1;
X			} else {
X				otmp2->otyp = DRAGON_SCALE_MAIL;
X				otmp2->olet = ARMOR_SYM;
X				otmp2->spe = 0;
X				otmp2->rustfree = 1;
X				otmp2->quan = 1;
X				otmp2->cursed = 0;
X			}
X			otmp2->corpsenm = obj->corpsenm;
X		    /* and croc corpses into shoes */
X		    } else if (obj->corpsenm == PM_CROCODILE) {
X			otmp2->otyp = LOW_BOOTS;
X			otmp2->olet = ARMOR_SYM;
X			otmp2->spe = 0;
X			otmp2->rustfree = 1;
X			otmp2->quan = 1;
X			otmp2->cursed = 0;
X		    }
X		}
X
X		/* no box contents --KAA */
X		if (Is_container(otmp2)) delete_contents(otmp2);
X
X		if(otmp2->otyp == MAGIC_LAMP) otmp2->otyp = LAMP;
X
X		if(otmp2->otyp == WAN_WISHING)
X			while(otmp2->otyp == WAN_WISHING ||
X			      otmp2->otyp == WAN_POLYMORPH)
X			    otmp2->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
X
X		/* update the weight */
X		otmp2->owt = weight(otmp2);
X		delobj(obj);
X		break;
X	case WAN_STRIKING:
X#ifdef SPELLS
X	case SPE_FORCE_BOLT:
X#endif
X		if(obj->otyp == BOULDER)
X			fracture_rock(obj);
X		else if(obj->otyp == STATUE)
X			(void) break_statue(obj);
X		else
X			res = 0;
X		break;
X	case WAN_CANCELLATION:
X#ifdef SPELLS
X	case SPE_CANCELLATION:
X#endif
X		cancel_item(obj);
X		break;
X	case WAN_TELEPORTATION:
X#ifdef SPELLS
X	case SPE_TELEPORT_AWAY:
X#endif
X		rloco(obj);
X		break;
X	case WAN_MAKE_INVISIBLE:
X		obj->oinvis = 1;
X		break;
X	case WAN_UNDEAD_TURNING:
X#ifdef SPELLS
X	case SPE_TURN_UNDEAD:
X#endif
X		res = !!revive(obj,FALSE);
X		break;
X	case WAN_OPENING:
X	case WAN_LOCKING:
X#ifdef SPELLS
X	case SPE_KNOCK:
X	case SPE_WIZARD_LOCK:
X#endif
X		if(Is_box(obj))
X			res = boxlock(obj, otmp);
X		else
X			res = 0;
X		if (res /* && obj->olet == WAND_SYM */)
X			makeknown(obj->otyp);
X		break;
X	case WAN_SLOW_MONSTER:		/* no effect on objects */
X#ifdef SPELLS
X	case SPE_SLOW_MONSTER:
X#endif
X	case WAN_SPEED_MONSTER:
X	case WAN_NOTHING:
X#ifdef PROBING
X	case WAN_PROBING:
X#endif
X		res = 0;
X		break;
X	default:
X		impossible("What an interesting effect (%u)", otmp->otyp);
X	}
X	return(res);
X}
X
X/*
X * zappable - returns 1 if zap is available, 0 otherwise.
X *	      it removes a charge from the wand if zappable.
X * added by GAN 11/03/86
X */
Xint
Xzappable(wand)
Xregister struct obj *wand;
X{
X	if(wand->spe < 0 || (wand->spe == 0 && rn2(121)))
X		return 0;
X	if(wand->spe == 0)
X		You("wrest one more spell from the worn-out wand.");
X	wand->spe--;
X	return 1;
X}
X
X/*
X * zapnodir - zaps an NODIR wand.
X * added by GAN 11/03/86
X */
Xvoid
Xzapnodir(wand)
Xregister struct obj *wand;
X{
X	switch(wand->otyp){
X		case WAN_LIGHT:
X			litroom(TRUE);
X			break;
X		case WAN_SECRET_DOOR_DETECTION:
X			if(!findit()) return;
X			break;
X		case WAN_CREATE_MONSTER:
X			{ register int cnt = 1;
X			if(!rn2(23)) cnt += rn2(7) + 1;
X			while(cnt--)
X			    (void) makemon((struct permonst *) 0, u.ux, u.uy);
X			}
X			break;
X		case WAN_WISHING:
X			if(Luck + rn2(5) < 0) {
X				pline("Unfortunately, nothing happens.");
X				break;
X			}
X			makewish();
X			break;
X	}
X	if(!objects[wand->otyp].oc_name_known) {
X			makeknown(wand->otyp);
X			more_experienced(0,10);
X	}
X}
X
Xstatic void
Xbackfire(otmp)
X
X	register struct obj * otmp;
X{
X	pline("The %s suddenly explodes!", xname(otmp));
X	losehp(d(otmp->spe+2,6), "exploding wand", KILLED_BY_AN);
X	useup(otmp);
X}
X
Xstatic const char NEARDATA zap_syms[] = { WAND_SYM, 0 };
X
Xint
Xdozap()
X{
X	register struct obj *obj;
X	int	damage;
X
X	obj = getobj(zap_syms, "zap");
X	if(!obj) return(0);
X
X	check_unpaid(obj);
X
X	/* zappable addition done by GAN 11/03/86 */
X	if(!zappable(obj)) pline(nothing_happens);
X	else if(obj->cursed && !rn2(100)) {
X		backfire(obj);	/* the wand blows up in your face! */
X		return(1);
X	} else if(!(objects[obj->otyp].bits & NODIR) && !getdir(1)) {
X		if (!Blind)
X		    pline("The %s glows and fades.", xname(obj));
X		/* make him pay for knowing !NODIR */
X	} else if(!u.dx && !u.dy && !u.dz && !(objects[obj->otyp].bits & NODIR)) {
X	    if((damage = zapyourself(obj)))
X		losehp(damage, self_pronoun("zapped %sself with a wand", "him"),
X			NO_KILLER_PREFIX);
X	}
X	else {
X		weffects(obj);
X#if defined(ALTARS) && defined(THEOLOGY)
X		if(priesthit) ghod_hitsu();
X		priesthit = FALSE;
X#endif
X	}
X	if (obj->spe < 0) {
X	    pline ("The %s %sturns to dust.",
X		   xname(obj), Blind ? "" : "glows violently, then ");
X	    useup(obj);
X	}
X	return(1);
X}
X
Xint
Xzapyourself(obj)
X	register struct obj	*obj;
X{
X	struct obj	*otmp;
X	int	damage = 0;
X
X	switch(obj->otyp) {
X		case WAN_STRIKING:
X#ifdef SPELLS
X		case SPE_FORCE_BOLT:
X#endif
X		    if(Antimagic) {
X			shieldeff(u.ux, u.uy);
X			pline("Boing!");
X		    } else {
X			You("magically bash yourself!");
X			damage=d(8,6);
X		    }
X		    break;
X		case WAN_LIGHTNING:
X		    makeknown(WAN_LIGHTNING);
X		    if (!Shock_resistance) {
X			pline("Idiot!  You've shocked yourself!");
X			damage = d(12,6);
X		    } else {
X			shieldeff(u.ux, u.uy);
X			You("zap yourself, but seem unharmed.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X			ugolemeffects(AD_ELEC, d(12,6));
X#endif /* GOLEMS */
X#endif
X		    }
X		    destroy_item(WAND_SYM, AD_ELEC);
X		    destroy_item(RING_SYM, AD_ELEC);
X		    if(!Blind) {
X			    You("are blinded by the flash!");
X			    make_blinded((long)rnd(100),FALSE);
X		    }
X		    break;
X		case WAN_FIRE:
X		    makeknown(WAN_FIRE);
X#ifdef SPELLS
X		case SPE_FIREBALL:
X#endif
X#ifdef MUSIC
X		case FIRE_HORN:
X#endif
X		    pline("You've set light to yourself!");
X		    if (Fire_resistance) {
X			shieldeff(u.ux, u.uy);
X			You("feel mildly hot.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X			ugolemeffects(AD_FIRE, d(12,6));
X#endif /* GOLEMS */
X#endif
X		    } else
X			damage = d(12,6);
X		    destroy_item(SCROLL_SYM, AD_FIRE);
X		    destroy_item(POTION_SYM, AD_FIRE);
X#ifdef SPELLS
X		    destroy_item(SPBOOK_SYM, AD_FIRE);
X#endif
X		    break;
X		case WAN_COLD:
X		    makeknown(WAN_COLD);
X#ifdef SPELLS
X		case SPE_CONE_OF_COLD:
X#endif
X#ifdef MUSIC
X		case FROST_HORN:
X#endif
X		    if (Cold_resistance) {
X			shieldeff(u.ux, u.uy);
X			You("feel mildly chilly.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X			ugolemeffects(AD_COLD, d(12,6));
X#endif /* GOLEMS */
X#endif
X		    } else {
X			You("imitate a popsicle!");
X			damage = d(12,6);
X		    }
X		    destroy_item(POTION_SYM, AD_COLD);
X		    break;
X		case WAN_MAGIC_MISSILE:
X		    makeknown(WAN_MAGIC_MISSILE);
X#ifdef SPELLS
X		case SPE_MAGIC_MISSILE:
X#endif
X		    if(Antimagic) {
X			shieldeff(u.ux, u.uy);
X			pline("The missiles bounce!");
X		    } else {
X			damage = d(4,6);
X			pline("Idiot!  You've shot yourself!");
X		    }
X		    break;
X		case WAN_POLYMORPH:
X#ifdef POLYSELF
X		    makeknown(WAN_POLYMORPH);
X#endif
X#ifdef SPELLS
X		case SPE_POLYMORPH:
X#endif
X#ifdef POLYSELF
X		    polyself();
X#else
X		    newman();
X#endif
X		    break;
X		case WAN_CANCELLATION:
X#ifdef SPELLS
X		case SPE_CANCELLATION:
X#endif
X#ifdef POLYSELF
X#ifdef GOLEMS
X		    if (u.umonnum == PM_CLAY_GOLEM) {
X			if (!Blind)
X			    pline("Some writing vanishes from your head!");
X			rehumanize();
X			break;
X		    }
X#endif /* GOLEMS */
X#endif
X		    for(otmp = invent; otmp; otmp = otmp->nobj)
X			cancel_item(otmp);
X#ifdef POLYSELF
X		    if(u.mtimedone) rehumanize();
X#endif
X		    flags.botl = 1;  /* because of potential AC change */
X		    find_ac();
X		    break;
X	       case WAN_MAKE_INVISIBLE:
X		    if (!Invis && !See_invisible)
X			makeknown(WAN_MAKE_INVISIBLE);
X		    HInvis |= INTRINSIC;
X		    if (!See_invisible) newsym(u.ux, u.uy);
X		    break;
X	       case WAN_SPEED_MONSTER:
X		    if (!(Fast & INTRINSIC)) {
X			Fast |= INTRINSIC;
X			You("seem to be moving faster.");
X			makeknown(WAN_SPEED_MONSTER);
X		    }
X		    break;
X	       case WAN_SLEEP:
X		    makeknown(WAN_SLEEP);
X#ifdef SPELLS
X		case SPE_SLEEP:
X#endif
X		    if(Sleep_resistance) {
X			shieldeff(u.ux, u.uy);
X			You("don't feel sleepy!");
X		    } else {
X			pline("The sleep ray hits you!");
X			nomul(-rn2(50));
X		    }
X		    break;
X		case WAN_SLOW_MONSTER:
X#ifdef SPELLS
X		case SPE_SLOW_MONSTER:
X#endif
X		    if(Fast & (TIMEOUT | INTRINSIC)) {
X			Fast &= ~(TIMEOUT | INTRINSIC);
X			You("seem to be moving slower.");
X		    }
X		    break;
X		case WAN_TELEPORTATION:
X#ifdef SPELLS
X		case SPE_TELEPORT_AWAY:
X#endif
X		    tele();
X		    break;
X		case WAN_DEATH:
X#ifdef SPELLS
X		case SPE_FINGER_OF_DEATH:
X#endif
X#ifdef POLYSELF
X		    if (is_undead(uasmon)) {
X			pline((obj->otyp == WAN_DEATH) ?
X			  "The wand shoots an apparently harmless beam at you."
X			  : "You seem no deader than before.");
X			break;
X		    }
X#endif
X		    killer_format = NO_KILLER_PREFIX;
X		    killer = self_pronoun("shot %sself with a death ray","him");
X		    You("irradiate yourself with pure energy!");
X		    You("die.");
X		    makeknown(WAN_DEATH);
X			/* They might survive with an amulet of life saving */
X		    done(DIED);
X		    break;
X#ifdef SPELLS
X		case SPE_TURN_UNDEAD:
X#endif
X		case WAN_UNDEAD_TURNING:
X#ifdef POLYSELF
X		    if (is_undead(uasmon)) {
X			You("feel frightened and %sstunned.",
X			     Stunned ? "even more " : "");
X			make_stunned(HStun + rnd(30), FALSE);
X		    }
X#endif
X		    break;
X#ifdef SPELLS
X		case SPE_DIG:
X		case SPE_DETECT_UNSEEN:
X#endif
X		case WAN_DIGGING:
X		case WAN_NOTHING:
X		case WAN_OPENING:
X		case WAN_LOCKING:
X#ifdef SPELLS
X		case SPE_KNOCK:
X		case SPE_WIZARD_LOCK:
X#endif
X		    break;
X#ifdef PROBING
X		case WAN_PROBING:
X		    makeknown(WAN_PROBING);
X		    ustatusline();
X		    break;
X#endif
X		default: impossible("object %d used?",obj->otyp);
X	}
X	return(damage);
X}
X
X/* called for various wand and spell effects - M. Stephenson */
Xvoid
Xweffects(obj)
Xregister struct	obj	*obj;
X{
X	xchar zx,zy;
X
X	if(objects[obj->otyp].bits & IMMEDIATE) {
X	    if(u.uswallow)	(void)bhitm(u.ustuck, obj);
X	    else if(u.dz) {
X		if(u.dz > 0) {
X#ifdef STRONGHOLD
X		    if(levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN &&
X		       (obj->otyp == WAN_LOCKING
X# ifdef SPELLS
X			|| obj->otyp == SPE_WIZARD_LOCK
X# endif
X			))
X				(void)close_drawbridge(u.ux, u.uy);
X		    else
X#endif
X		    {
X			register struct obj *otmp, *otmp2 = (struct obj *)0;
X
X			if(levl[u.ux][u.uy].gmask)
X				(void) bhitgold(g_at(u.ux, u.uy), obj);
X			/* pre-reverse the polymorph pile,  -dave- 3/90 */
X			if (obj->otyp == WAN_POLYMORPH
X#ifdef SPELLS
X				|| obj->otyp == SPE_POLYMORPH
X#endif
X								) {
X				otmp = level.objects[u.ux][u.uy];
X				level.objects[u.ux][u.uy] = otmp2;
X				while(otmp) {
X					otmp2 = otmp->nexthere;
X					otmp->nexthere = level.objects[u.ux][u.uy];
X					level.objects[u.ux][u.uy] = otmp;
X					otmp = otmp2;
X				}
X			}
X			for(otmp = level.objects[u.ux][u.uy];
X							otmp; otmp = otmp2) {
X				/* changed by GAN to hit all objects there */
X				otmp2 = otmp->nexthere;
X				/* save pointer as bhito may destroy otmp */
X				(void) bhito(otmp, obj);
X			}
X		    }
X		}
X	    } else (void) bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj);
X	} else {
X	    switch(obj->otyp){
X		case WAN_LIGHT:
X#ifdef SPELLS
X		case SPE_LIGHT:
X#endif
X			litroom(TRUE);
X			break;
X		case WAN_SECRET_DOOR_DETECTION:
X#ifdef SPELLS
X		case SPE_DETECT_UNSEEN:
X#endif
X			if(!findit()) return;
X			break;
X		case WAN_CREATE_MONSTER:
X			{ register int cnt = 1;
X			if(!rn2(23)) cnt += rn2(7) + 1;
X			while(cnt--)
X			    (void) makemon((struct permonst *) 0, u.ux, u.uy);
X			}
X			break;
X		case WAN_WISHING:
X			if(Luck + rn2(5) < 0) {
X			    pline("Unfortunately, nothing happens.");
X			    break;
X			}
X			makewish();
X			break;
X		case WAN_DIGGING:
X#ifdef SPELLS
X		case SPE_DIG:
X#endif
X			/* Original effect (approximately):
X			 * from CORR: dig until we pierce a wall
X			 * from ROOM: piece wall and dig until we reach
X			 * an ACCESSIBLE place.
X			 * Currently: dig for digdepth positions;
X			 * also down on request of Lennart Augustsson.
X			 */
X			{ register struct rm *room;
X			  register int digdepth,dlx,dly;
X			  register boolean shopdoor = FALSE;
X#ifdef __GNULINT__
X			dlx = dly = 0;
X#endif
X			if(u.uswallow) {
X				register struct monst *mtmp = u.ustuck;
X
X				if (!is_whirly(mtmp->data)) {
X					if (is_animal(mtmp->data)) 
X						if (Blind) 
X						You("pierce its stomach wall!");
X						else 
X						You("pierce %s's stomach wall!",
X				  	 	    mon_nam(mtmp));
X					mtmp->mhp = 1;	/* almost dead */
X					expels(mtmp, mtmp->data,
X					       !is_animal(mtmp->data));
X				}
X				break;
X			}
X			if(u.dz) {
X			    if(u.dz < 0) {
X				You("loosen a rock from the ceiling.");
X				pline("It falls on your %s!",
X					body_part(HEAD));
X				losehp(1, "falling rock", KILLED_BY_AN);
X				(void) mksobj_at((int)ROCK, u.ux, u.uy);
X				fobj->quan = 1;
X				stackobj(fobj);
X				if(Invisible) newsym(u.ux, u.uy);
X			    } else {
X#ifdef MACOS
X				segments |= SEG_ZAP;
X#endif
X				dighole();
X			    }
X			    break;
X			}
X			zx = u.ux+u.dx;
X			zy = u.uy+u.dy;
X			digdepth = 8 + rn2(18);
X			Tmp_at2(-1, '*');	/* open call */
X			while(--digdepth >= 0) {
X			    if(!isok(zx,zy)) break;
X			    room = &levl[zx][zy];
X			    Tmp_at2(zx,zy);
X			    if(is_maze_lev) {
X				if(IS_WALL(room->typ)) {
X				    if(room->diggable == W_DIGGABLE)
X					room->typ = ROOM;
X				    else if(!Blind)
X					pline("The wall glows then fades.");
X				    break;
X				}
X				if(room->typ == STONE) {
X				    if(room->diggable == W_DIGGABLE)
X					room->typ = CORR;
X				    else if (!Blind)
X					pline("The rock glows then fades.");
X				    break;
X				}
X			    } else
X				if(IS_ROCK(room->typ))
X				    if(may_dig(zx,zy))
X					if(IS_WALL(room->typ) ||
X						room->typ == SDOOR) {
X					    room->typ = DOOR;
X					    room->doormask = D_NODOOR;
X					    mnewsym(zx, zy);
X					    if (cansee(zx,zy)) prl(zx, zy);
X					    digdepth -= 2;
X					} else {
X					    room->typ = CORR;
X					    digdepth--;
X					}
X				    else
X					break;
X				else if(closed_door(zx, zy)) {
X				    room->doormask = D_NODOOR;
X				    mnewsym(zx, zy);
X				    if (cansee(zx,zy)) prl(zx, zy);
X				    if(in_shop(zx,zy)) {
X					shopdoor = TRUE;
X					dlx = zx;
X					dly = zy;
X				    }
X				    digdepth -= 2;
X				}
X			    mnewsym(zx,zy);
X			    zx += u.dx;
X			    zy += u.dy;
X			}
X			mnewsym(zx,zy);	/* not always necessary */
X			Tmp_at2(-1,-1);	/* closing call */
X			if(!Blind) prl(u.ux+u.dx, u.uy+u.dy);
X			if(shopdoor)
X				pay_for_door(dlx, dly, "destroy");
X			break;
X			}
X		default:
X#ifdef SPELLS
X			if((int) obj->otyp >= SPE_MAGIC_MISSILE) {
X
X			    buzz((int) obj->otyp - SPE_MAGIC_MISSILE + 10,
X				 (int)u.ulevel / 2 + 1, u.ux, u.uy, u.dx, u.dy);
X			} else
X#endif
X
X			    buzz((int) obj->otyp - WAN_MAGIC_MISSILE, 6,
X				 u.ux, u.uy, u.dx, u.dy);
X			break;
X		}
X		if(!objects[obj->otyp].oc_name_known) {
X			makeknown(obj->otyp);
X			more_experienced(0,10);
X		}
X	}
X	return;
X}
X
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(mtmp->mx,mtmp->my) || !flags.verbose) pline("The %s hits it.", str);
X	else pline("The %s hits %s%s", str, mon_nam(mtmp), force);
X}
X
Xvoid
Xmiss(str,mtmp)
Xregister const char *str;
Xregister struct monst *mtmp;
X{
X	pline("The %s misses %s.", str,
X	      (cansee(mtmp->mx,mtmp->my) && flags.verbose) ? mon_nam(mtmp) : "it");
X}
X
X/* bhit: called when a weapon is thrown (sym = obj->olet) or when an
X   IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of
X   range or when a monster is hit; the monster is returned, and bhitpos
X   is set to the final position of the weapon thrown; the ray of a wand
X   may affect several objects and monsters on its path - for each of
X   these an argument function is called. */
X/* check !u.uswallow before calling bhit() */
X
Xstruct monst *
Xbhit(ddx,ddy,range,sym,fhitm,fhito,obj)
Xregister int ddx,ddy,range;		/* direction and range */
Xchar sym;				/* symbol displayed on path */
Xint FDECL((*fhitm), (struct monst *, struct obj *)),
X    FDECL((*fhito), (struct obj *, struct obj *));		/* fns called when mon/obj hit */
Xstruct obj *obj;			/* 2nd arg to fhitm/fhito */
X{
X	register struct monst *mtmp;
X	register struct obj *otmp;
X	register uchar typ;
X	boolean shopdoor = FALSE;
X#ifdef __GNULINT__
X	xchar dlx=0, dly=0;
X#else
X	xchar dlx, dly;
X#endif
X
X	bhitpos.x = u.ux;
X	bhitpos.y = u.uy;
X
X	if(sym) {
X		tmp_at(-1, sym);	/* open call */
X#ifdef TEXTCOLOR
X		tmp_at(-3, (int)objects[obj->otyp].oc_color);
X#else
X		tmp_at(-3, (int)AT_OBJ);
X#endif
X	}
X	while(range-- > 0) {
X#ifdef STRONGHOLD
X		int x,y;
X#endif
X		bhitpos.x += ddx;
X		bhitpos.y += ddy;
X#ifdef STRONGHOLD
X		x = bhitpos.x; y = bhitpos.y;
X		if (find_drawbridge(&x,&y) && !sym)
X		    switch (obj->otyp) {
X			case WAN_OPENING:
X# ifdef SPELLS
X			case SPE_KNOCK:
X# endif
X			    if (is_db_wall(bhitpos.x, bhitpos.y))
X				(void) open_drawbridge(x,y);
X			    break;
X			case WAN_LOCKING:
X# ifdef SPELLS
X			case SPE_WIZARD_LOCK:
X# endif
X			    (void) close_drawbridge(x,y);
X			    break;
X			case WAN_STRIKING:
X# ifdef SPELLS
X			case SPE_FORCE_BOLT:
X# endif
X			    if (levl[bhitpos.x][bhitpos.y].typ != 
X			   	DRAWBRIDGE_UP)
X			        destroy_drawbridge(x,y);
X		    }
X#endif /* STRONGHOLD /**/
X		if(MON_AT(bhitpos.x, bhitpos.y)){
X			mtmp = m_at(bhitpos.x,bhitpos.y);
X			if(sym) {
X				tmp_at(-1, -1);	/* close call */
X				return(mtmp);
X			}
X			(*fhitm)(mtmp, obj);
X			range -= 3;
X		}
X		/* modified by GAN to hit all objects */
X		if(fhito){
X		    int hitanything = 0;
X		    register struct obj *next_obj = (struct obj *)0;
X
X		    if((fhito == bhito) && levl[bhitpos.x][bhitpos.y].gmask)
X			hitanything += bhitgold(g_at(bhitpos.x,bhitpos.y),obj);
X		    /* pre-reverse the polymorph pile,  -dave- 3/90 */
X		    if (obj->otyp == WAN_POLYMORPH
X#ifdef SPELLS
X			    || obj->otyp == SPE_POLYMORPH
X#endif
X							) {
X			otmp = level.objects[bhitpos.x][bhitpos.y];
X			level.objects[bhitpos.x][bhitpos.y] = next_obj;
X			while(otmp) {
X			    next_obj = otmp->nexthere;
X			    otmp->nexthere = level.objects[bhitpos.x][bhitpos.y];
X			    level.objects[bhitpos.x][bhitpos.y] = otmp;
X			    otmp = next_obj; 
X			}
X		    }
X		    for(otmp = level.objects[bhitpos.x][bhitpos.y];
X							otmp; otmp = next_obj) {
X			/* Fix for polymorph bug, Tim Wright */
X			next_obj = otmp->nexthere;
X			hitanything += (*fhito)(otmp, obj);
X		    }
X		    if(hitanything)	range--;
X		}
X		typ = levl[bhitpos.x][bhitpos.y].typ;
X		if((IS_DOOR(typ) || typ == SDOOR) && !sym) {
X		    switch (obj->otyp) {
X			case WAN_OPENING:
X			case WAN_LOCKING:
X			case WAN_STRIKING:
X#ifdef SPELLS
X			case SPE_KNOCK:
X			case SPE_WIZARD_LOCK:
X			case SPE_FORCE_BOLT:
X#endif
X			    if (doorlock(obj, bhitpos.x, bhitpos.y)) {
X				makeknown(obj->otyp);
X				if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
X				    && in_shop(bhitpos.x, bhitpos.y)) {
X					shopdoor = TRUE;
X					dlx = bhitpos.x; dly = bhitpos.y;
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(sym) tmp_at(bhitpos.x, bhitpos.y);
X#ifdef SINKS
X		if(sym && IS_SINK(typ))
X			break;	/* physical objects fall onto sink */
X#endif
X	}
X
X	/* leave last symbol unless in a pool */
X	if(sym)
X	   tmp_at(-1, is_pool(bhitpos.x,bhitpos.y) ? -1 : 0);
X
X	if(shopdoor)
X		pay_for_door(dlx, dly, "destroy");
X
X	return (struct monst *)0;
X}
X
Xstruct monst *
Xboomhit(dx, dy)
Xint dx, dy;
X{
X	register int i, ct;
X	char sym = ')';
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(-1, sym);	/* open call */
X#ifndef TEXTCOLOR
X	tmp_at(-3, (int)AT_OBJ);
X#else
X	tmp_at(-3, HI_METAL);
X#endif
X	for(ct=0; ct<10; ct++) {
X		if(i == 8) i = 0;
X		sym = ')' + '(' - sym;
X		tmp_at(-2, sym);	/* change let call */
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			tmp_at(-1,-1);
X			return(m_at(bhitpos.x,bhitpos.y));
X		}
X		if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) {
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(-1,-1);
X				pline("Skillfully, you catch the boomerang.");
X				return(&youmonst);
X			}
X		}
X		tmp_at(bhitpos.x, bhitpos.y);
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(-1, -1);	/* do not leave last symbol */
X	return (struct monst *)0;
X}
X
Xstatic uchar
Xdirlet(dx, dy)
Xregister int dx, dy;
X{
X	return
X	    (dx == dy) ? LSLANT_SYM :
X	    (dx && dy) ? RSLANT_SYM :
X	    dx ? HBEAM_SYM : VBEAM_SYM;
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 0:			/* magic missile */
X		tmp = d(nd,6);
X		break;
X	case 1:			/* 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 2:			/* sleep */
X		tmp = 0;
X		if(resists_sleep(mon->data) ||
X		   resist(mon, (type == 2) ? WAND_SYM : '\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 (mon->mfrozen + tmp2 > 127) mon->mfrozen = 127;
X			else mon->mfrozen += tmp2;
X		}
X		break;
X	case 3:			/* 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 4:			/* death/disintegration */
X		if(abs(type) != 24) {	/* death */
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 if (resists_disint(mon->data)) {
X		    shieldeff(mon->mx, mon->my);
X		    break;
X		}
X		tmp = mon->mhp+1;
X		break;
X	case 5:			/* lightning */
X		if(resists_elec(mon->data)) {
X		    shieldeff(mon->mx, mon->my);
X		    break;
X		}
X		tmp = d(nd,6);
X		{
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 6:			/* poison */
X		if(resists_poison(mon->data)) {
X		    shieldeff(mon->mx, mon->my);
X		    break;
X		}
X		tmp = d(nd,6);
X		break;
X	case 7:			/* 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	if (type >= 0)
X	    if (resist(mon, (type < 10) ? WAND_SYM : '\0', 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 scrquan, i, cnt = 0;
X
X	for(obj = level.objects[x][y]; obj; obj = obj2) {
X	    obj2 = obj->nexthere;
X	    /* Bug fix - KAA */
X#ifdef SPELLS
X	    if((obj->olet == SCROLL_SYM || obj->olet == SPBOOK_SYM)) {
X#else
X	    if(obj->olet == SCROLL_SYM) {
X#endif
X		if (obj->otyp == SCR_FIRE
X#ifdef SPELLS
X					|| obj->otyp == SPE_FIREBALL
X#endif
X		    )
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 > 1) 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/* 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 abstype = abs(type) % 10;
X	register const char *fltxt = fl[abs(type)];
X	struct rm *lev;
X	register xchar lsx, lsy;
X#ifdef __GNULINT__
X	xchar range, olx=0, oly=0;
X#else
X	xchar range, olx, oly;
X#endif
X	struct monst *mon;
X	register boolean bodyhit = FALSE;
X	register boolean shopdoor = FALSE;
X
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("The %s rips into %s%s",
X				fltxt, mon_nam(u.ustuck), exclam(tmp));
X		if (u.ustuck->mhp < 1)
X			killed(u.ustuck);
X		return;
X	}
X	if(type < 0) pru();
X	range = rn1(7,7);
X	Tmp_at2(-1, (int) dirlet(dx,dy));	/* open call */
X#ifdef TEXTCOLOR
X	Tmp_at2(-3, zapcolor[abstype]);
X#endif
X	while(range-- > 0) {
X		lsx = sx; sx += dx;
X		lsy = sy; sy += dy;
X		if((lev = &levl[sx][sy])->typ) {
X			if((cansee(lsx,lsy) && cansee(sx,sy)) ||
X				(!cansee(lsx,lsy) && cansee(sx,sy) &&
X				 (IS_DOOR(lev->typ) || IS_ROOM(lev->typ))))
X			    Tmp_at2(sx,sy);
X		} else {
X			int bounce = 0;
X			if(cansee(sx-dx,sy-dy))
X				pline("The %s bounces!", fltxt);
X			if(ZAP_POS(levl[sx][sy-dy].typ))
X				bounce = 1;
X			if(ZAP_POS(levl[sx-dx][sy].typ)) {
X				if(!bounce || rn2(2)) bounce = 2;
X			}
X			switch(bounce){
X			case 0:
X				dx = -dx;
X				dy = -dy;
X				continue;
X			case 1:
X				dy = -dy;
X				sx -= dx;
X				break;
X			case 2:
X				dx = -dx;
X				sy -= dy;
X				break;
X			}
X			Tmp_at2(-2,(int) dirlet(dx,dy));
X			continue;
X		}
X		if(abstype == 1 /* fire */ &&
X		   (is_pool(sx,sy) || (lev->typ == ROOM && lev->icedpool))) {
X		    if(lev->typ == ROOM) {
X#ifdef STUPID
X			if (lev->icedpool == ICED_POOL)
X				lev->typ = POOL;
X			else
X				lev->typ = MOAT;
X#else
X			lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
X#endif
X			lev->icedpool = 0;
X			pline("The ice crackles and melts.");
X			mnewsym(sx,sy);
X		    } else {
X#ifdef STRONGHOLD
X			if(lev->typ != POOL) {	/* MOAT or DRAWBRIDGE_UP */
X			    if(cansee(sx,sy))
X				pline("Some water evaporates.");
X			    else if(flags.soundok)
X				You("hear a hissing sound.");
X			} else {
X#endif
X			    register struct trap *ttmp;
X
X			    range -= 3;
X			    lev->typ = ROOM;
X			    mnewsym(sx,sy);
X			    if(cansee(sx,sy)) pline("The water evaporates.");
X			    else if(flags.soundok)
X				You("hear a hissing sound.");
X			    ttmp = maketrap(sx, sy, PIT);
X			    ttmp->tseen = 1;
X#ifdef STRONGHOLD
X			}
X#endif
X		    }
X		}
X		if(abstype == 3 /* cold */ && is_pool(sx,sy)) {
X			boolean moat = (lev->typ != POOL);
X
X			range -= 3;
X#ifdef STRONGHOLD
X			if(lev->typ == DRAWBRIDGE_UP) {
X				lev->drawbridgemask |= DB_ICE;
X			} else {
X#endif
X				lev->typ = ROOM;
X				lev->icedpool = (moat ? ICED_MOAT : ICED_POOL);
X#ifdef STRONGHOLD
X			}
X#endif
X			mnewsym(sx,sy);
X			if(cansee(sx,sy)) {
X				if(moat)
X					pline("The moat is bridged with ice!");
X				else 	pline("The water freezes.");
X			} else if(flags.soundok)
X				You("hear a crackling sound.");
X		}
X		if(closed_door(sx, sy)) {
X			range = 0;
X			switch(abstype) {
X			case 1:
X			   lev->doormask = D_NODOOR;
X			   mnewsym(sx,sy);
X			   if(cansee(sx,sy)) {
X				pline("The door is consumed in flames!");
X				prl(sx,sy);
X			   }
X			   else You("smell smoke.");
X			   if(type >= 0 && in_shop(sx, sy)) {
X				shopdoor = TRUE;
X				olx = sx;
X				oly = sy;
X			   }
X			   break;
X			case 3:
X			   lev->doormask = D_NODOOR;
X			   mnewsym(sx,sy);
X			   if(cansee(sx,sy)) {
X				pline("The door freezes and shatters!");
X				prl(sx,sy);
X			   }
X			   else You("feel cold.");
X			   if(type >= 0 && in_shop(sx, sy)) {
X				shopdoor = TRUE;
X				olx = sx;
X				oly = sy;
X			   }
X			   break;
X			case 4:
X			   lev->doormask = D_NODOOR;
X			   mnewsym(sx,sy);
X			   if(cansee(sx,sy)) {
X				pline("The door disintegrates!");
X				prl(sx,sy);
X			   }
X			   else if(flags.soundok)
X				You("hear a crashing sound.");
X			   if(type >= 0 && in_shop(sx, sy)) {
X				shopdoor = TRUE;
X				olx = sx;
X				oly = sy;
X			   }
X			   break;
X			case 5:
X			   lev->doormask = D_BROKEN;
X			   mnewsym(sx,sy);
X			   if(cansee(sx,sy)) {
X				pline("The door splinters!");
X				prl(sx,sy);
X			   }
X			   else if(flags.soundok)
X				You("hear a crackling sound.");
X			   if(type >= 0 && in_shop(sx, sy)) {
X				shopdoor = TRUE;
X				olx = sx;
X				oly = sy;
X			   }
X			   break;
X			default:
X			   if(cansee(sx,sy)) {
X			       if (type >= 0 && type <= 9)
X				   pline("The door absorbs your bolt!");
X			       else if (type >= 10 && type <= 19)
X				   pline("The door absorbs your spell!");
X#ifdef POLYSELF
X			       else if (type >= 20 && type <= 29)
X				   pline("The door absorbs your blast!");
X#endif
X			       else if (type >= -19 && type <= -10)
X				   pline("The door absorbs the spell!");
X			       else
X				   pline("The door absorbs the blast!");
X			   } else You("feel vibrations.");
X			   break;
X			}
X		}
X		if(OBJ_AT(sx, sy) && abstype == 1)
X			if(burn_floor_paper(sx,sy) && cansee(sx,sy))  {
X			    mnewsym(sx,sy);
X			    if(!Blind)
X				You("see a puff of smoke.");
X			}
X		if(MON_AT(sx, sy)){
X			mon = m_at(sx,sy);
X			/* Cannot use wakeup() which also angers the monster */
X			mon->msleep = 0;
X			if(mon->mimic) seemimic(mon);
X			if(type >= 0) {
X			    setmangry(mon);
X#if defined(ALTARS) && defined(THEOLOGY)
X			    if(mon->ispriest && in_temple(mon->mx, mon->my))
X				priesthit = TRUE;
X#endif
X			}
X			if(rnd(20) < 18 + mon->data->ac) {
X			    register int tmp = zhit(mon, type, nd);
X			    if(mon->mhp < 1) {
X				if(type < 0) {
X				    if(cansee(mon->mx,mon->my))
X				      pline("%s is killed by the %s!",
X					    Monnam(mon), fltxt);
X				    mondied(mon);
X				} else
X				    killed(mon);
X			     } else
X				hit(fltxt, mon, exclam(tmp));
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("The %s hits you!",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				    if (dx) dx = -dx;
X				    if (dy) dy = -dy;
X				    shieldeff(sx, sy);
X				}
X				else switch(abstype) {
X				case 0:		/* magic missile */
X				    if(Antimagic) {
X					shieldeff(sx, sy);
X					pline("The missiles bounce off!");
X				    } else dam = d(nd,6);
X				    break;
X				case 1:		/* fire */
X				    if(Fire_resistance) {
X					shieldeff(sx, sy);
X					You("don't feel hot!");
X#ifdef POLYSELF
X#ifdef GOLEMS
X					ugolemeffects(AD_FIRE, d(nd, 6));
X#endif /* GOLEMS */
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)) continue;
X					    break;
X					case 1:
X					    bodyhit = TRUE;
X					    if (uarmc) break;
X		if (uarm) (void)(rust_dmg(uarm, xname(uarm), 0, FALSE));
X					    break;
X					case 2:
X		if (!rust_dmg(uarms, "wooden shield", 0, FALSE)) 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_SYM, AD_FIRE);
X				    if(!rn2(3) && bodyhit)
X					destroy_item(SCROLL_SYM, AD_FIRE);
X#ifdef SPELLS
X				    if(!rn2(5) && bodyhit)
X					destroy_item(SPBOOK_SYM, AD_FIRE);
X#endif
X				    break;
X				case 2:		/* sleep */
X				    if(Sleep_resistance) {
X					shieldeff(u.ux, u.uy);
X					You("don't feel sleepy.");
X				    } else nomul(-d(nd,25)); /* sleep ray */
X				    break;
X				case 3:		/* cold */
X				    if(Cold_resistance) {
X					shieldeff(sx, sy);
X					You("don't feel cold.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X					ugolemeffects(AD_COLD, d(nd, 6));
X#endif /* GOLEMS */
X#endif
X				    } else
X					dam = d(nd, 6);
X				    if(!rn2(3))
X					destroy_item(POTION_SYM, AD_COLD);
X				    break;
X				case 4:		/* death */
X				    if(type == -24
X#ifdef POLYSELF
X					|| type == 24
X#endif
X						) { /* disintegration */
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				    u.uhp = -1;
X				    break;
X				case 5:		/* lightning */
X				    if (Shock_resistance) {
X					shieldeff(sx, sy);
X					You("aren't affected.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X					ugolemeffects(AD_ELEC, d(nd, 6));
X#endif /* GOLEMS */
X#endif
X				    } else
X					dam = d(nd, 6);
X				    if(!rn2(3))
X					destroy_item(WAND_SYM, AD_ELEC);
X				    if(!rn2(3))
X					destroy_item(RING_SYM, AD_ELEC);
X				    break;
X				case 6:		/* poison */
X				    poisoned("blast", A_DEX, "poisoned blast", 15);
X				    break;
X				case 7:		/* acid */
X				    pline("The acid burns!");
X				    dam = d(nd,6);
X				    if(!rn2(6)) corrode_weapon();
X				    if(!rn2(6)) corrode_armor();
X				    break;
X				}
X				losehp(dam,fltxt, KILLED_BY_AN);
X			} else pline("The %s whizzes by you!",fltxt);
X			if (abstype == 5 && !Blind) { /* LIGHTNING */
X		    		You("are blinded by the flash!");
X				make_blinded((long)d(nd,50),FALSE);
X				seeoff(0);
X			}
X			stop_occupation();
X		}
X		if(!ZAP_POS(lev->typ)) {
X			int bounce = 0;
X			uchar rmn;
X			if(cansee(sx,sy)) pline("The %s bounces!", fltxt);
X			range--;
X			if(!dx || !dy || !rn2(20)){
X				dx = -dx;
X				dy = -dy;
X			} else {
X			  if(ZAP_POS(rmn = levl[sx][sy-dy].typ) &&
X			    (IS_ROOM(rmn) || ZAP_POS(levl[sx+dx][sy-dy].typ)))
X				bounce = 1;
X			  if(ZAP_POS(rmn = levl[sx-dx][sy].typ) &&
X			    (IS_ROOM(rmn) || ZAP_POS(levl[sx-dx][sy+dy].typ)))
X				if(!bounce || rn2(2))
X					bounce = 2;
X
X			  switch(bounce){
X			  case 0:
X				dy = -dy;
X				dx = -dx;
X				break;
X			  case 1:
X				dy = -dy;
X				break;
X			  case 2:
X				dx = -dx;
X				break;
X			  }
X			  Tmp_at2(-2, (int) dirlet(dx,dy));
X			}
X		}
X	}
X	Tmp_at2(-1,-1);
X	if(shopdoor) pay_for_door(olx, oly, abstype == 1 ? "burn away" :
X				       abstype == 3 ? "shatter" :
X				       abstype == 4 ? "disintegrate" :
X				       "destroy");
X}
X
Xvoid
Xrlocgold(gold)
Xregister struct gold *gold;
X{
X	register int tx, ty, otx, oty;
X	long val = gold->amount;
X
X	otx = gold->gx;
X	oty = gold->gy;
X	do {
X		tx = rn1(COLNO-3,2);
X		ty = rn2(ROWNO);
X	} while(!goodpos(tx,ty,(struct permonst *)0));
X	freegold(g_at(otx,oty));
X	mkgold(val, tx, ty);
X	if(cansee(otx,oty))
X		newsym(otx,oty);
X	if(cansee(tx,ty))
X		newsym(tx,ty);
X}
X
Xvoid
Xrloco(obj)
Xregister struct obj *obj;
X{
X	register int 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 permonst *)0));
X	move_object(obj, tx, ty);
X	mnewsym(otx, oty);
X	if(cansee(otx,oty) && !vism_at(otx,oty) && !Blind &&
X			(Invisible || u.ux != otx || u.uy != oty))
X		newsym(otx,oty);
X	mnewsym(tx, ty);
X	if(cansee(tx,ty) && !vism_at(tx,ty) && !Blind &&
X			(Invisible || u.ux != tx || u.uy != ty))
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	/* unpobj(obj); */
X	obj->otyp = ROCK;
X	obj->quan = 7 + rn2(60);
X	obj->owt = weight(obj);
X	obj->olet = GEM_SYM;
X	obj->known = FALSE;
X	obj->onamelth = 0;		/* no names */
X	if(cansee(obj->ox,obj->oy))
X		prl(obj->ox,obj->oy);
X}
X
Xboolean
Xbreak_statue(obj)
Xregister struct obj *obj;
X{
X	struct trap *trap;
X
X	if(trap = t_at(obj->ox,obj->oy))
X	    if(obj->corpsenm == trap->pm)
X		if(makemon(&mons[trap->pm], 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	if (obj->spe) {
X	    struct obj *magazine;
X#ifdef SPELLS
X	    magazine = mkobj_at(SPBOOK_SYM, obj->ox, obj->oy, TRUE);
X#else
X	    magazine = mkobj_at(SCROLL_SYM, obj->ox, obj->oy, TRUE);
X#endif
X	    magazine->blessed = obj->blessed;
X	    magazine->cursed = obj->cursed;
X	}
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 quan, i, cnt, dmg, xresist, skip;
X	register int dindx;
X	const char *mult;
X
X	for(obj = invent; obj; obj = obj2) {
X
X	    obj2 = obj->nobj;
X	    if(obj->olet != osym) continue; /* test only objs of type osym */
X	    xresist = skip = 0;
X#ifdef __GNULINT__
X	    quan = dmg = dindx = 0;
X#endif
X	    switch(dmgtyp) {
X		case AD_COLD:
X		    if(osym == POTION_SYM) {
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->olet != POTION_SYM);
X
X		    if (obj->otyp == SCR_FIRE
X#ifdef SPELLS
X					|| obj->otyp == SPE_FIREBALL
X#endif
X								)
X		      skip++;
X		    quan = obj->quan;
X		    switch(osym) {
X			case POTION_SYM:
X			    dindx = 1;
X			    dmg = rnd(6);
X			    break;
X			case SCROLL_SYM:
X			    dindx = 2;
X			    dmg = 1;
X			    break;
X#ifdef SPELLS
X			case SPBOOK_SYM:
X			    dindx = 3;
X			    dmg = 1;
X			    break;
X#endif
X			default:
X			    skip++;
X			    break;
X		    }
X		    break;
X		case AD_ELEC:
X		    xresist = (Shock_resistance && obj->olet != RING_SYM);
X		    quan = obj->quan;
X		    switch(osym) {
X			case RING_SYM:
X			    if(obj->otyp == RIN_SHOCK_RESISTANCE)
X				    { skip++; break; }
X			    dindx = 4;
X			    dmg = 0;
X			    break;
X			case WAND_SYM:
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 = 0; i < quan; i++)
X		    if(!rn2(3)) cnt++;
X
X		if(!cnt) continue;
X		if(cnt == quan)	mult = "Your";
X		else	mult = (cnt == 1) ? "One of your" : "Some of your";
X		pline("%s %s %s!", mult, xname(obj),
X			(cnt > 1) ? destroy_strings[dindx*3 + 1]
X				  : destroy_strings[dindx*3]);
X		if(osym == POTION_SYM && dmgtyp != AD_COLD)
X		    potionbreathe(obj);
X		for(i = 0; i < cnt; i++) {
X		    if (obj->owornmask) setnotworn(obj);
X		    useup(obj);
X		}
X		if(dmg) {
X		    if(xresist)	You("aren't hurt!");
X		    else	losehp(dmg,
X			(cnt==1) ? destroy_strings[dindx*3 + 2] :
X				(const char *)makeplural(destroy_strings[dindx*3 + 2]),
X			(cnt==1) ? KILLED_BY_AN : KILLED_BY);
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 quan, i, cnt, skip, tmp = 0;
X	register int dindx;
X
X	for(obj = mtmp->minvent; obj; obj = obj2) {
X
X	    obj2 = obj->nobj;
X	    if(obj->olet != osym) continue; /* test only objs of type osym */
X	    skip = 0;
X#ifdef __GNULINT__
X	    quan = dindx = 0;
X#endif
X	    switch(dmgtyp) {
X		case AD_COLD:
X		    if(osym == POTION_SYM) {
X			quan = obj->quan;
X			dindx = 0;
X			tmp++;
X		    } else skip++;
X	    	    break;
X		case AD_FIRE:
X		    if (obj->otyp == SCR_FIRE
X#ifdef SPELLS
X					|| obj->otyp == SPE_FIREBALL
X#endif
X								)
X		      skip++;
X		    quan = obj->quan;
X		    switch(osym) {
X			case POTION_SYM:
X			    dindx = 1;
X			    tmp++;
X			    break;
X			case SCROLL_SYM:
X			    dindx = 2;
X			    tmp++;
X			    break;
X#ifdef SPELLS
X			case SPBOOK_SYM:
X			    dindx = 3;
X			    tmp++;
X			    break;
X#endif
X			default:
X			    skip++;
X			    break;
X		    }
X		    break;
X		case AD_ELEC:
X		    quan = obj->quan;
X		    switch(osym) {
X			case RING_SYM:
X			    if(obj->otyp == RIN_SHOCK_RESISTANCE)
X				    { skip++; break; }
X			    dindx = 4;
X			    break;
X			case WAND_SYM:
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 = 0; i < quan; i++)
X		    if(!rn2(3)) cnt++;
X
X		if(!cnt) continue;
X		pline("%s's %s %s!", Monnam(mtmp), xname(obj),
X			(cnt > 1) ? 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, olet, damage, tell)
Xregister struct monst	*mtmp;
Xregister char	olet;
Xregister int	damage, tell;
X{
X	register int	resisted = 0;
X#ifdef HARD
X	register int	lev;
X
X	switch(olet)  {
X
X	    case WAND_SYM:
X			lev = 8;
X			break;
X
X	    case SCROLL_SYM:
X			lev = 6;
X			break;
X
X	    case POTION_SYM:
X			lev = 5;
X			break;
X
X	    default:	lev = u.ulevel;
X			break;
X	}
X
X	resisted = (rn2(100) - mtmp->m_lev + lev) < mtmp->data->mr;
X	if(resisted) {
X
X		if(tell) {
X		    shieldeff(mtmp->mx, mtmp->my);
X		    pline("%s resists!", canseemon(mtmp) ? Monnam(mtmp) : "It");
X		}
X		mtmp->mhp -= damage/2;
X	} else
X#endif
X		mtmp->mhp -= damage;
X
X	if(mtmp->mhp < 1) killed(mtmp);
X	return(resisted);
X}
X
Xvoid
Xmakewish()
X{
X	char buf[BUFSZ];
X	register struct obj *otmp;
X	unsigned wishquan, mergquan;
X	int tries = 0;
X
Xretry:
X	You("may wish for an object.  What do you want? ");
X	getlin(buf);
X	if(buf[0] == '\033') buf[0] = 0;
X/* Note: if they wished for and got a non-object successfully, such as gold,
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 (!Blind) otmp->dknown = 1; /* needed for merge to work */
X	    wishquan = otmp->quan;
X	    otmp = addinv(otmp);
X	    if(inv_cnt() > 52) {
X	        pline("Oops!  The %s to the floor!", aobjnam(otmp, "drop"));
X	        dropx(otmp);
X	    } else {
X	    	mergquan = otmp->quan;
X	    	otmp->quan = wishquan; /* to fool prinv() */
X	    	prinv(otmp);
X	    	otmp->quan = mergquan;
X	    }
X#ifdef THEOLOGY
X	    u.ublesscnt += rn1(100,50);  /* the gods take notice */
X#endif
X	}
X}
END_OF_FILE
if test 50988 -ne `wc -c <'src/zap.c'`; then
    echo shar: \"'src/zap.c'\" unpacked with wrong size!
fi
# end of 'src/zap.c'
fi
echo shar: End of archive 3 \(of 56\).
cp /dev/null ark3isdone
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 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 56 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