[comp.sources.games] v07i084: NetHack3 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 84
Archive-name: NetHack3/Part29



#! /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 29 (of 38)."
# Contents:  amiga/Makefile.ami src/dog.c src/mkroom.c src/mthrowu.c
#   src/spell.c
# Wrapped by billr@saab on Sun Jul 23 21:33:12 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'amiga/Makefile.ami' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amiga/Makefile.ami'\"
else
echo shar: Extracting \"'amiga/Makefile.ami'\" \(10847 characters\)
sed "s/^X//" >'amiga/Makefile.ami' <<'END_OF_FILE'
X#	Hack Makefile.
X#	SCCS Id: @(#)Makefile.ami       3.0     89/04/23
X
X# This makefile is specifically for the Amiga.
X
XCFLAGS	  = +cd -e200
XCPPFLAGS  = -I -Iamiga: -Iinclude:
XCC	  = cc
X
X#   Use my special modified Cpp (-w flag writes all #defines)
X#   since the one built in Manx CC is too stupid for now.
X
X.c.o:
X	Cpp $(CPPFLAGS) $< ram:_$*.c
X	cc  $(CFLAGS) -o $*.o ram:_$*.c
X	delete ram:_$*.c
X
X#   Search path for default rules: (for my special modified Make)
X
X.PATH:	src1: src2:
X
X.PRECIOUS:  include:config.h include:decl.h include:_hack.h \
X	    include:permonst.h include:you.h
X
X
X# object files for makedefs
XMAKEOBJS = makedefs.o monst.o objects.o
X
X# object files for level compiler
XSPLEVOBJS = lev_comp.o lev_lex.o lev_main.o monst.o objects.o
X
X# make NetHack
XGAME	 = nethack
X
X# if you defined RANDOM in unixconf.h/pcconf.h since your system did not come
X# with a reasonable random number generator
XRANDOBJ = random.o
X
X# nothing below this line should have to be changed
X#
X# other things that have to be reconfigured are in config.h,
X# {unixconf.h, pcconf.h, amiconf.h}, and possibly system.h
X
X# HACKCSRC = alloc.c apply.c artifact.c attrib.c bones.c cmd.c dbridge.c \
X#	    decl.c demon.c do.c do_name.c do_wear.c dog.c dogmove.c dokick.c \
X#	    dothrow.c eat.c end.c engrave.c exper.c extralev.c fountain.c \
X#	    getline.c hack.c invent.c lock.c mail.c makemon.c mcastu.c mhitm.c \
X#	    mhitu.c mklev.c mkmaze.c mkobj.c mkroom.c mon.c mondata.c \
X#	    monmove.c monst.c mthrowu.c music.c o_init.c objects.c objnam.c \
X#	    options.c pager.c pickup.c polyself.c potion.c pray.c pri.c \
X#	    priest.c prisym.c read.c restore.c rip.c rnd.c rumors.c save.c \
X#	    search.c shk.c shknam.c sit.c sounds.c sp_lev.c spell.c steal.c \
X#	    termcap.c timeout.c topl.c topten.c track.c trap.c u_init.c \
X#	    uhitm.c vault.c version.c weapon.c were.c wield.c wizard.c worm.c \
X#	    worn.c write.c zap.c
X
X# all .c files but msdos.c, tos.c, *main.c, *tty.c, *unix.c, (system specific)
X# and makedefs.c, lev_comp.c, panic.c (not part of any nethack)
X
X# CSOURCES = $(HACKCSRC) pcmain.c makedefs.c panic.c
X
X# HACKINCL = artifact.h attrib.h config.h coord.h decl.h edog.h epri.h eshk.h \
X#	    extern.h flag.h func_tab.h global.h gold.h hack.h lev.h mfndpos.h \
X#	    mkroom.h monattk.h mondata.h monflag.h monst.h monsym.h msdos.h \
X#	    obj.h objclass.h permonst.h prop.h rm.h sp_lev.h spell.h \
X#	    tradstdc.h trapname.h vault.h wseg.h you.h youprop.h
X
X# all .h files except date.h, onames.h, pm.h & trap.h which would cause
X# dependency loops if run through "make depend".
X
X# HSOURCES = $(HACKINCL) date.h onames.h pm.h trap.h
X
X# SOURCES = $(CSOURCES) $(HSOURCES)
X
XAOBJ  = amidos.o amitcap.o amitty.o amiunix.o amiwind.o
XHOBJ1 = alloc.o apply.o artifact.o attrib.o bones.o cmd.o dbridge.o decl.o \
X	demon.o do.o do_name.o do_wear.o dog.o dogmove.o dokick.o dothrow.o \
X	eat.o end.o engrave.o exper.o extralev.o fountain.o getline.o hack.o \
X	invent.o lock.o
XHOBJ2 = mail.o main.o makemon.o mcastu.o mhitm.o mhitu.o mklev.o mkmaze.o \
X	mkobj.o mkroom.o mon.o mondata.o monmove.o monst.o mthrowu.o music.o \
X	o_init.o objects.o objnam.o options.o pager.o pickup.o polyself.o \
X	potion.o pray.o pri.o priest.o prisym.o read.o restore.o rip.o rnd.o \
X	rumors.o save.o
XHOBJ3 = search.o shk.o shknam.o sit.o sounds.o sp_lev.o spell.o steal.o \
X	timeout.o topl.o topten.o track.o trap.o u_init.o \
X	uhitm.o vault.o version.o weapon.o were.o wield.o wizard.o \
X	worm.o worn.o write.o zap.o $(RANDOBJ)
X
XHOBJ =	$(AOBJ) $(HOBJ1) $(HOBJ2) $(HOBJ3)
X
X# the .o files from the HACKCSRC list, plus main.o tty.o unix.o
X
X$(GAME): $(HOBJ)
X	ln -f ami.lnk
X
Xlink:
X	ln -f ami.lnk
X
Xobj1:	$(HOBJ1)
Xobj2:	$(HOBJ2)
Xobj3:	$(HOBJ3)
X
X#
X#	Please note:	The dependency lines for the modules here are
X#			deliberately incorrect.  Including "hack.h" in
X#			the dependency list would cause a dependency
X#			loop.
X#
Xmakedefs:	$(MAKEOBJS)
X	ln -o makedefs $(MAKEOBJS) -lcl
X
Xmakedefs.o:  include:config.h include:permonst.h include:objclass.h
X
Xlev_comp:  $(SPLEVOBJS)
X	ln -o lev_comp $(SPLEVOBJS) -lcl
X
Xlev_comp.o:  include:hack.h include:sp_lev.h
X	Cpp $(CPPFLAGS) src1:lev_comp.c ram:_lev_comp.c
X	cc  +cd -e300 -o lev_comp.o ram:_lev_comp.c
X	delete ram:_lev_comp.c
Xlev_lex.o:  include:lev_comp.h include:hack.h include:sp_lev.h
X	Cpp $(CPPFLAGS) src1:lev_lex.c ram:_lev_lex.c
X	cc  +cd -e300 -o lev_lex.o ram:_lev_lex.c
X	delete ram:_lev_lex.c
Xlev_main.o:  include:hack.h include:sp_lev.h
X	Cpp $(CPPFLAGS) src1:lev_main.c ram:_lev_main.c
X	cc  +cd -e300 -o lev_main.o ram:_lev_main.c
X	delete ram:_lev_main.c
X
X#
X#	The following include files depend on makedefs to be created.
X#	As a result, they are not defined in HACKINCL, instead, their
X#	dependencies are explicitly outlined here.
X#
X
X#
X#	date.h should be remade any time any of the source or include code
X#	is modified.  Unfortunately, this would make the contents of this
X#	file far more complex.	Since "hack.h" depends on most of the include
X#	files, we kludge around this by making date.h dependent on hack.h,
X#	even though it doesn't include this file.
X#
Xinclude:date.h:      include:hack.h makedefs $(AOBJ)
X	-makedefs -v
X
Xinclude:trap.h:      include:config.h makedefs
X	-makedefs -t
X	copy makedefs.1 include:trap.h
X
Xinclude:onames.h:    makedefs
X	-makedefs -o
X
Xinclude:pm.h:	     makedefs
X	-makedefs -p
X
X#
X#	The following programs vary depending on what OS you are using.
X#	As a result, they are not defined in HACKSRC, and their dependancies
X#	are explicitly outlined here.
X#
X
Xamidos.o: include:hack.h amiga:amidos.c
X	$(CC) $(CFLAGS) amiga:amidos.c -o amidos.o
X
Xamitcap.o: include:hack.h amiga:amitcap.c
X	$(CC) $(CFLAGS) amiga:amitcap.c -o amitcap.o
X
Xamitty.o: include:hack.h amiga:amitty.c
X	$(CC) $(CFLAGS) amiga:amitty.c -o amitty.o
X
Xamiunix.o: include:hack.h amiga:amiunix.c
X	$(CC) $(CFLAGS) amiga:amiunix.c -o amiunix.o
X
Xamiwind.o: include:hack.h amiga:amiwind.c amiga:amimenu.c
X	$(CC) $(CFLAGS) +IData:syms/amiga.syms amiga:amiwind.c -o amiwind.o
X
Xmain.o: include:hack.h src2:pcmain.c
X	Cpp $(CPPFLAGS) src2:pcmain.c ram:_main.c
X	cc  $(CFLAGS) -o main.o ram:_main.c
X	delete ram:_main.c
X
X# Pre-include hack.h to save disk I/O. Rename the original hack.h
X# to _hack.h though. The -w option makes Cpp write out all
X# necessary #defines at the end of the output.
X
Xinclude:hack.h: include:_hack.h makedefs
X	-Cpp -Iinclude: -Iamiga: -w include:_hack.h hack.h
X	-copy hack.h include:hack.h
X
Xclean:
X	delete *.o ram:_*.c ram:ctmp*
X
Xspotless: clean
X	delete $(GAME) lev_comp makedefs
X	delete include:onames.h include:pm.h
X	setdate include:onames.h include:pm.h
X	setdate makedefs.c
X#(make sure files exist and have timestamps in the right order for next compile)
X
X
X# DO NOT DELETE THIS LINE
X
Xalloc.o:  include:config.h
Xapply.o:  include:hack.h include:edog.h
Xartifact.o:  include:hack.h include:artifact.h
Xattrib.o:  include:hack.h
Xbones.o:  include:hack.h
Xcmd.o:	include:hack.h include:func_tab.h
Xdbridge.o:  include:hack.h
Xdecl.o:  include:hack.h
Xdemon.o:  include:hack.h
Xdo.o:  include:hack.h
Xdo_name.o:  include:hack.h
Xdo_wear.o:  include:hack.h
Xdog.o:	include:hack.h include:edog.h
Xdogmove.o:  include:hack.h include:mfndpos.h include:edog.h
Xdokick.o:  include:hack.h
Xdothrow.o:  include:hack.h
Xeat.o:	include:hack.h
Xend.o:	include:hack.h include:eshk.h
Xengrave.o:  include:hack.h
Xexper.o:  include:hack.h
Xextralev.o:  include:hack.h
Xfountain.o:  include:hack.h
Xgetline.o: include:hack.h include:func_tab.h
Xhack.o:  include:hack.h
Xinvent.o:  include:hack.h include:lev.h include:wseg.h
Xlock.o:  include:hack.h
Xmail.o:  include:hack.h
Xmakemon.o:  include:hack.h
Xmcastu.o:  include:hack.h
Xmhitm.o:  include:hack.h include:artifact.h
Xmhitu.o:  include:hack.h include:artifact.h include:edog.h
Xmklev.o:  include:hack.h
Xmkmaze.o:  include:hack.h
Xmkobj.o:  include:hack.h
Xmkroom.o:  include:hack.h
Xmon.o:	include:hack.h include:mfndpos.h include:artifact.h
Xmondata.o:  include:hack.h include:eshk.h include:epri.h
Xmonmove.o:  include:hack.h include:mfndpos.h include:artifact.h
Xmonst.o:  include:config.h include:permonst.h include:monsym.h include:eshk.h include:vault.h include:epri.h
X	Cpp $(CPPFLAGS) src2:monst.c ram:_monst.c
X	cc  $(CFLAGS) -z4000 -o monst.o ram:_monst.c
X	delete ram:_monst.c
Xmthrowu.o:  include:hack.h
Xmusic.o:  include:hack.h
Xo_init.o:  include:hack.h
Xobjects.o:  include:config.h include:obj.h include:objclass.h include:prop.h
X	Cpp $(CPPFLAGS) src2:objects.c ram:_objects.c
X	cc  $(CFLAGS) -z8000 +q -o objects.o ram:_objects.c
X	delete ram:_objects.c
Xobjnam.o:  include:hack.h
Xoptions.o:  include:hack.h
Xpager.o:  include:hack.h
Xpickup.o:  include:hack.h
Xpolyself.o:  include:hack.h
Xpotion.o:  include:hack.h
Xpray.o:  include:hack.h
Xpri.o:	include:hack.h
Xpriest.o:  include:hack.h include:mfndpos.h include:eshk.h include:epri.h
Xprisym.o:  include:hack.h include:wseg.h include:lev.h
Xread.o:  include:hack.h
Xrestore.o:  include:hack.h include:lev.h include:wseg.h
Xrip.o:	include:hack.h
X	Cpp $(CPPFLAGS) src2:rip.c ram:_rip.c
X	cc  $(CFLAGS) +q -o rip.o ram:_rip.c
X	delete ram:_rip.c
Xrnd.o:	include:hack.h
Xrumors.o:  include:hack.h
Xsave.o:  include:hack.h include:lev.h include:wseg.h
Xsearch.o:  include:hack.h include:artifact.h
Xshk.o:	include:hack.h include:eshk.h
Xshknam.o:  include:hack.h include:eshk.h
Xsit.o:	include:hack.h
Xsounds.o:  include:hack.h include:edog.h include:eshk.h
Xsp_lev.o:  include:hack.h include:sp_lev.h
Xspell.o:  include:hack.h
Xsteal.o:  include:hack.h
Xtimeout.o:  include:hack.h
Xtopl.o:  include:hack.h
Xtopten.o:  include:hack.h
Xtrack.o:  include:hack.h
Xtrap.o:  include:hack.h include:edog.h include:trapname.h
Xu_init.o:  include:hack.h
Xuhitm.o:  include:hack.h include:artifact.h
Xvault.o:  include:hack.h include:vault.h
Xversion.o:  include:hack.h include:date.h
Xweapon.o:  include:hack.h
Xwere.o:  include:hack.h
Xwield.o:  include:hack.h
Xwizard.o:  include:hack.h
Xworm.o:  include:hack.h include:wseg.h
Xworn.o:  include:hack.h
Xwrite.o:  include:hack.h
Xzap.o:	include:hack.h
Xinclude:config.h:  include:tradstdc.h include:global.h
X	-setdate include:config.h
Xinclude:decl.h:  include:spell.h include:obj.h include:you.h include:onames.h include:pm.h
X	-setdate include:decl.h
Xinclude:global.h:  include:coord.h include:unixconf.h include:pcconf.h include:tosconf.h include:amiconf.h
X	-setdate include:global.h
Xinclude:_hack.h:  include:config.h include:decl.h include:monsym.h include:mkroom.h include:objclass.h include:gold.h include:trap.h include:flag.h include:rm.h
X	-setdate include:_hack.h
Xinclude:permonst.h:  include:monattk.h include:monflag.h
X	-setdate include:permonst.h
Xinclude:you.h:	include:attrib.h include:monst.h include:youprop.h
X	-setdate include:you.h
Xinclude:youprop.h:  include:prop.h include:permonst.h include:mondata.h include:pm.h
X	-setdate include:youprop.h
X# DEPENDENCIES MUST END AT END OF FILE
X# IF YOU PUT STUFF HERE IT WILL GO AWAY
X# see make depend above
END_OF_FILE
if test 10847 -ne `wc -c <'amiga/Makefile.ami'`; then
    echo shar: \"'amiga/Makefile.ami'\" unpacked with wrong size!
fi
# end of 'amiga/Makefile.ami'
fi
if test -f 'src/dog.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/dog.c'\"
else
echo shar: Extracting \"'src/dog.c'\" \(7862 characters\)
sed "s/^X//" >'src/dog.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)dog.c	3.0	89/06/12
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X#include "edog.h"
X
Xchar dogname[63] = DUMMY;
Xchar catname[63] = DUMMY;
X
X#define domestic(mtmp)	(mtmp->data->msound == MS_BARK || mtmp->data->msound == MS_MEW)
X
Xvoid
Xinitedog(mtmp)
Xregister struct monst *mtmp;
X{
X	mtmp->mtame = domestic(mtmp) ? 10 : 5;
X	mtmp->mpeaceful = 1;
X	mtmp->mleashed = 0;
X	mtmp->meating = 0;
X	EDOG(mtmp)->droptime = 0;
X	EDOG(mtmp)->dropdist = 10000;
X	EDOG(mtmp)->apport = 10;
X	EDOG(mtmp)->whistletime = 0;
X	EDOG(mtmp)->hungrytime = 1000 + moves;
X}
X
Xvoid
Xmake_familiar(otmp)
Xregister struct obj *otmp;
X{
X	register struct monst *mtmp;
X	register struct permonst *pm;
X
Xtop:
X	if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */
X	else if (rn2(3)) {
X	    if (!(pm = rndmonst())) {
X		pline("There seems to be nothing available for a familiar.");
X		return;
X	    }
X	}
X	else if ((pl_character[0]=='W' || rn2(2)) && pl_character[0]!='C')
X		pm = &mons[PM_KITTEN];
X	else pm = &mons[PM_LITTLE_DOG];
X
X	pm->pxlth += sizeof(struct edog);
X	mtmp = makemon(pm, u.ux, u.uy);
X	pm->pxlth -= sizeof(struct edog);
X	if (!mtmp) { /* monster was genocided */
X	    if (otmp)
X		pline("The figurine writhes and then shatters into pieces!");
X	    else goto top;
X		/* rndmonst() returns something not genocided always, so this
X		 * means it was a cat or dog; loop back to try again until
X		 * either rndmonst() is called, or if only one of cat/dog
X		 * was genocided, they get the other.
X		 */
X	    return;
X	}
X	initedog(mtmp);
X	if (otmp && otmp->cursed) { /* cursed figurine */
X		You("get a bad feeling about this.");
X		mtmp->mtame = mtmp->mpeaceful = 0;
X	}
X}
X
Xstruct monst *
Xmakedog() {
X	register struct monst *mtmp;
X	register char *petname;
X
X	if (pl_character[0]=='C' || (pl_character[0] != 'W' && rn2(2))) {
X		mons[PM_LITTLE_DOG].pxlth = sizeof(struct edog);
X		mtmp = makemon(&mons[PM_LITTLE_DOG], u.ux, u.uy);
X		mons[PM_LITTLE_DOG].pxlth = 0;
X		petname = dogname;
X	} else {
X		mons[PM_KITTEN].pxlth = sizeof(struct edog);
X		mtmp = makemon(&mons[PM_KITTEN], u.ux, u.uy);
X		mons[PM_KITTEN].pxlth = 0;
X		petname = catname;
X	}
X
X	if(!mtmp) return((struct monst *) 0); /* dogs were genocided */
X
X	if (petname[0]) {
X		register struct monst *mtmp2;
X
X		mtmp->mnamelth = strlen(petname) + 1;
X		mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
X		*mtmp2 = *mtmp;
X
X		replmon(mtmp, mtmp2);
X		mtmp = mtmp2;
X		Strcpy(NAME(mtmp), petname);
X		petname[0] = '\0'; /* name first only; actually unnecessary */
X	}
X	initedog(mtmp);
X	return(mtmp);
X}
X
X/* attach the monsters that went down (or up) together with @ */
Xstruct monst *mydogs = 0;
X/* monsters that fell through a trapdoor or stepped on a tele-trap. */
X/* 'down' is now true only of trapdooor falling, not for tele-trap. */
Xstruct monst *fallen_down = 0;
X				
Xvoid
Xlosedogs(){
X	register struct monst *mtmp,*mtmp0,*mtmp2;
X
X	while(mtmp = mydogs){
X		mydogs = mtmp->nmon;
X		mtmp->nmon = fmon;
X		fmon = mtmp;
X		mnexto(mtmp);
X	}
X#ifdef LINT
X	mtmp0 = (struct monst *)0;
X#endif
X	for(mtmp = fallen_down; mtmp; mtmp = mtmp2) {
X		mtmp2 = mtmp->nmon;
X		if(mtmp->mx == dlevel) {
X		    mtmp->mx = 0;
X		    if(mtmp == fallen_down)
X			fallen_down = mtmp->nmon;
X		    else
X			mtmp0->nmon = mtmp->nmon;
X		    mtmp->nmon = fmon;
X		    fmon = mtmp;
X		    if (mtmp->isshk)
X			home_shk(mtmp);
X		    else
X			rloc(mtmp);
X		} else
X		    mtmp0 = mtmp;
X	}
X}
X
Xvoid
Xkeepdogs(){
Xregister struct monst *mtmp;
X	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X	    if(((dist(mtmp->mx,mtmp->my) < 3 && levl_follower(mtmp)) ||
X		/* the wiz will level t-port from anywhere to chase
X		   the amulet; if you don't have it, will chase you
X		   only if in range. -3. */
X			(u.uhave_amulet && mtmp->iswiz))
X			&& !mtmp->msleep && !mtmp->mfroz) {
X#ifdef WORM
X		/* Bug "fix" for worm changing levels collapsing dungeon
X		 */
X		if (mtmp->data == &mons[PM_LONG_WORM]) {
X			if (canseemon(mtmp) || (Blind && Telepat))
X				pline("The worm can't fit down the stairwell.");
X# ifdef WALKIES
X			if (mtmp->mleashed) {
X				pline("The leash slides off the slimy worm.");
X				m_unleash(mtmp);
X			}
X# endif
X			continue;
X		}
X#endif
X		if (mon_has_amulet(mtmp)) {
X			pline("%s seems very disoriented for a moment.",
X				Monnam(mtmp));
X#ifdef WALKIES
X			if (mtmp->mleashed) {
X				pline("%s leash suddenly comes loose.",
X					is_female(mtmp) ? "Her" :
X					humanoid(mtmp->data) ? "His" : "Its");
X				m_unleash(mtmp);
X			}
X#endif
X			continue;
X		}
X		relmon(mtmp);
X		mtmp->mx = mtmp->my = 0; /* to avoid mnexto()/mmask problem */
X		mtmp->nmon = mydogs;
X		mydogs = mtmp;
X		unpmon(mtmp);
X		keepdogs();	/* we destroyed the link, so use recursion */
X		return;		/* (admittedly somewhat primitive) */
X	}
X}
X
Xvoid
Xfall_down(mtmp, tolev) 
Xregister struct monst *mtmp; 
Xregister int tolev;
X{
X	relmon(mtmp);
X	mtmp->nmon = fallen_down;
X	fallen_down = mtmp;
X#ifdef WALKIES
X	if (mtmp->mleashed)  {
X		pline("The leash comes off!");
X		m_unleash(mtmp);
X	}
X#endif
X	unpmon(mtmp);
X	mtmp->mtame = 0;
X	mtmp->mx = tolev; 
X	mtmp->my = 0;
X		/* make sure to reset mtmp->mx to 0 when releasing, */
X		/* so rloc() on next level doesn't affect mmask */
X}
X
X/* return quality of food; the lower the better */
X/* fungi will eat even tainted food */
Xint
Xdogfood(mon,obj)
Xstruct monst *mon;
Xregister struct obj *obj;
X{
X	boolean carn = carnivorous(mon->data);
X
X	switch(obj->olet) {
X	case FOOD_SYM:
X	    if (obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE &&
X		!resists_ston(mon->data))
X		    return TABU;
X
X	    if (!carn && !herbivorous(mon->data))
X		    return (obj->cursed ? UNDEF : APPORT);
X
X	    switch (obj->otyp) {
X		case TRIPE_RATION:
X		    return (carn ? DOGFOOD : MANFOOD);
X		case CORPSE:
X		case EGG:
X		    if ((obj->age + 50 <= moves && mon->data->mlet != S_FUNGUS) ||
X			(poisonous(&mons[obj->corpsenm]) && !resists_poison(mon->data)) ||
X			(obj->corpsenm == PM_COCKATRICE && !resists_ston(mon->data)))
X			return POISON;
X		    else return (carn ? CADAVER : MANFOOD);
X		case DEAD_LIZARD:
X		    return (carn ? ACCFOOD : MANFOOD);
X		default:
X		    return (obj->otyp < CARROT ? ACCFOOD : MANFOOD);
X	    }
X	default:
X	    if(!obj->cursed) return(APPORT);
X	    /* fall into next case */
X	case BALL_SYM:
X	case CHAIN_SYM:
X	case ROCK_SYM:
X	    return(UNDEF);
X	}
X}
X
X/* return roomnumber or -1 */
Xint
Xinroom(x,y) xchar x,y; {
X	register struct mkroom *croom = &rooms[0];
X	while(croom->hx >= 0){
X		if(croom->hx >= x-1 && croom->lx <= x+1 &&
X		   croom->hy >= y-1 && croom->ly <= y+1)
X			return(croom - rooms);
X		croom++;
X	}
X	return(-1);	/* not in room or on door */
X}
X
Xint
Xtamedog(mtmp, obj)
Xregister struct monst *mtmp;
Xregister struct obj *obj;
X{
X	register struct monst *mtmp2;
X
X	/* worst case, at least he'll be peaceful. */
X	mtmp->mpeaceful = 1;
X	if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
X						&& mtmp->data->mlet == S_DOG)
X		return(0);
X
X	/* If we cannot tame him, at least he's no longer afraid. */
X	mtmp->mflee = 0;
X	mtmp->mfleetim = 0;
X	if(mtmp->mtame || mtmp->mfroz ||
X#ifdef WORM
X	   mtmp->wormno ||
X#endif
X	   mtmp->isshk || mtmp->isgd ||
X#if defined(ALTARS) && defined(THEOLOGY)
X	   mtmp->ispriest ||
X#endif
X#ifdef POLYSELF
X	   is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon)))
X#else
X	   is_human(mtmp->data) || is_demon(mtmp->data))
X#endif
X		return(0);
X	/* no tame long worms so they don't try to follow you down stairs
X	   or get in your way */
X	if(obj) {
X		if(dogfood(mtmp, obj) >= MANFOOD) return(0);
X		if(cansee(mtmp->mx,mtmp->my)){
X			pline("%s devours the %s.", Monnam(mtmp),
X				objects[obj->otyp].oc_name);
X		}
X		obfree(obj, (struct obj *)0);
X	}
X	mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
X	*mtmp2 = *mtmp;
X	mtmp2->mxlth = sizeof(struct edog);
X	if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
X	initedog(mtmp2);
X	replmon(mtmp,mtmp2);
X	return(1);
X}
END_OF_FILE
if test 7862 -ne `wc -c <'src/dog.c'`; then
    echo shar: \"'src/dog.c'\" unpacked with wrong size!
fi
# end of 'src/dog.c'
fi
if test -f 'src/mkroom.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/mkroom.c'\"
else
echo shar: Extracting \"'src/mkroom.c'\" \(10546 characters\)
sed "s/^X//" >'src/mkroom.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)mkroom.c	3.0	88/11/24
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/*
X * Entry points:
X *	mkroom() -- make and stock a room of a given type
X *	nexttodoor() -- return TRUE if adjacent to a door
X *	has_dnstairs() -- return TRUE if given room has a down staircase
X *	has_upstairs() -- return TRUE if given room has an up staircase
X *	dist2() -- Euclidean square-of-distance function
X *	courtmon() -- generate a court monster
X */
X#include "hack.h"
X
Xstatic void mkshop(), mkzoo(), mkswamp();
X#ifdef ORACLE
Xstatic void mkdelphi();
X#endif
X#if defined(ALTARS) && defined(THEOLOGY)
Xstatic void mktemple();
X#endif
X
Xstatic struct permonst *morguemon();
X#ifdef ARMY
Xstatic struct permonst *squadmon();
X#endif
X
X#define sq(x) ((x)*(x))
X
Xstatic boolean
Xisbig(sroom)
Xregister struct mkroom *sroom;
X{
X	register int area = (sroom->hx - sroom->lx) * (sroom->hy - sroom->ly);
X	return( area > 20 );
X}
X
Xvoid
Xmkroom(roomtype)
X/* make and stock a room of a given type */
Xint	roomtype;
X{
X
X    if (roomtype >= SHOPBASE)
X	mkshop();	/* someday, we should be able to specify shop type */
X    else switch(roomtype) {
X#ifdef THRONES
X	case COURT:	mkzoo(COURT); break;
X#endif
X	case ZOO:	mkzoo(ZOO); break;
X	case BEEHIVE:	mkzoo(BEEHIVE); break;
X	case MORGUE:	mkzoo(MORGUE); break;
X	case BARRACKS:	mkzoo(BARRACKS); break;
X	case SWAMP:	mkswamp(); break;
X#ifdef ORACLE
X	case DELPHI:	mkdelphi(); break;
X#endif
X#if defined(ALTARS) && defined(THEOLOGY)
X	case TEMPLE:	mktemple(); break;
X#endif
X	default:	impossible("Tried to make a room of type %d.", roomtype);
X    }
X}
X
Xstatic void
Xmkshop()
X{
X	register struct mkroom *sroom;
X	int i = -1;
X#ifdef WIZARD
X	register char *ep;
X
X	/* first determine shoptype */
X	if(wizard){
X		ep = getenv("SHOPTYPE");
X		if(ep){
X			if(*ep == 'z' || *ep == 'Z'){
X				mkzoo(ZOO);
X				return;
X			}
X			if(*ep == 'm' || *ep == 'M'){
X				mkzoo(MORGUE);
X				return;
X			}
X			if(*ep == 'b' || *ep == 'B'){
X				mkzoo(BEEHIVE);
X				return;
X			}
X#ifdef THRONES
X			if(*ep == 't' || *ep == 'T'){
X				mkzoo(COURT);
X				return;
X			}
X#endif
X#ifdef ARMY
X			if(*ep == 's' || *ep == 'S'){
X				mkzoo(BARRACKS);
X				return;
X			}
X#endif /* ARMY */
X#if defined(ALTARS) && defined(THEOLOGY)
X			if(*ep == '_'){
X				mktemple();
X				return;
X			}
X#endif
X			if(*ep == '}'){
X				mkswamp();
X				return;
X			}
X			for(i=0; shtypes[i].name; i++)
X				if(*ep == shtypes[i].symb) goto gottype;
X			i = -1;
X		}
X	}
Xgottype:
X#endif
X	for(sroom = &rooms[0]; ; sroom++){
X		if(sroom->hx < 0) return;
X		if(sroom - rooms >= nroom) {
X			pline("rooms not closed by -1?");
X			return;
X		}
X		if(sroom->rtype != OROOM) continue;
X		if(!sroom->rlit || has_dnstairs(sroom) || has_upstairs(sroom))
X			continue;
X		if(
X#ifdef WIZARD
X		   (wizard && ep && sroom->doorct != 0) ||
X#endif
X			sroom->doorct == 1) break;
X	}
X
X	if(i < 0) {			/* shoptype not yet determined */
X	    register int j;
X
X	    /* pick a shop type at random */
X	    for(j = rn2(100), i = 0; j -= shtypes[i].prob; i++)
X		if (j < 0)	break;
X
X	    /* big rooms cannot be wand or book shops,
X	     * - so make them general stores
X	     */
X	    if(isbig(sroom) && (shtypes[i].symb == WAND_SYM
X#ifdef SPELLS
X				|| shtypes[i].symb == SPBOOK_SYM
X#endif
X								)) i = 0;
X	}
X	sroom->rtype = SHOPBASE + i;
X
X	/* stock the room with a shopkeeper and artifacts */
X	stock_room(&(shtypes[i]), sroom);
X}
X
Xstatic struct mkroom *
Xpick_room()
X/* pick an unused room, preferably with only one door */
X{
X	register struct mkroom *sroom;
X	register int i = nroom;
X
X	for(sroom = &rooms[rn2(nroom)]; i--; sroom++) {
X		if(sroom == &rooms[nroom])
X			sroom = &rooms[0];
X		if(sroom->hx < 0)
X			return (struct mkroom *)0;
X		if(sroom->rtype != OROOM)	continue;
X		if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
X			continue;
X		if(sroom->doorct == 1 || !rn2(5))
X			return sroom;
X	}
X	return (struct mkroom *)0;
X}
X
Xstatic void
Xmkzoo(type)
Xint type;
X{
X	register struct mkroom *sroom;
X	struct monst *mon;
X	register int sx,sy,i;
X	int sh, tx, ty, goldlim = 500 * dlevel;
X
X	if(!(sroom = pick_room())) return;
X
X	sroom->rtype = type;
X	sh = sroom->fdoor;
X	switch(type) {
X	    case COURT:
X		tx = somex(sroom); ty = somey(sroom); break;
X		/* TODO: try to ensure the enthroned monster is an M2_PRINCE */
X	    case BEEHIVE:
X		tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2;
X		ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2;
X		break;
X	}
X	for(sx = sroom->lx; sx <= sroom->hx; sx++)
X	    for(sy = sroom->ly; sy <= sroom->hy; sy++){
X		if((sx == sroom->lx && doors[sh].x == sx-1) ||
X		   (sx == sroom->hx && doors[sh].x == sx+1) ||
X		   (sy == sroom->ly && doors[sh].y == sy-1) ||
X		   (sy == sroom->hy && doors[sh].y == sy+1)) continue;
X		mon = makemon(
X#ifdef THRONES
X		    (type == COURT) ? courtmon() :
X#endif
X#ifdef ARMY
X		    (type == BARRACKS) ? squadmon() :
X#endif
X		    (type == MORGUE) ? morguemon() :
X		    (type == BEEHIVE) ?
X			(sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : 
X			 &mons[PM_KILLER_BEE]) :
X		    (struct permonst *) 0,
X		   sx, sy);
X		if(mon) {
X			mon->msleep = 1;
X#ifdef THRONES
X			if (type==COURT && mon->mpeaceful) {
X				mon->mpeaceful = 0;
X				mon->malign = max(3,abs(mon->data->maligntyp));
X			}
X#endif
X		}
X		switch(type) {
X		    case ZOO:
X			i = sq(dist2(sx,sy,doors[sh].x,doors[sh].y));
X			if(i >= goldlim) i = 5*dlevel;
X			goldlim -= i;
X			mkgold((long)(10 + rn2(i)), sx, sy);
X			break;
X		    case MORGUE:
X			if(!rn2(5))
X			    (void) mk_tt_corpse(sx, sy);
X			if(!rn2(10))	/* lots of treasure buried with dead */
X			    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy);
X			break;
X		    case BEEHIVE:
X			if(!rn2(3))
X			    (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy);
X			break;
X		    case BARRACKS:
X			if(!rn2(20))	/* the payroll and some loot */
X			    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy);
X			break;
X		}
X	}
X#ifdef THRONES
X	if(type == COURT)  {
X		levl[tx][ty].typ = THRONE;
X		levl[tx][ty].scrsym = THRONE_SYM;
X
X		tx = somex(sroom);
X		ty = somey(sroom);
X		mkgold((long) rn1(50 * dlevel,10), sx, sy);
X		(void) mksobj_at(CHEST, sx, sy);    /* the royal coffers */
X	}
X#endif
X
X}
X
Xstatic struct permonst *
Xmorguemon()
X{
X	register int i = rn2(100), hd = rn2(dlevel);
X
X	if(hd > 10 && i < 10)
X		return((Inhell) ? mkclass(S_DEMON) : &mons[ndemon()]);
X	if(hd > 8 && i > 85)
X		return(mkclass(S_VAMPIRE));
X
X	return((i < 20) ? &mons[PM_GHOST]
X			: (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE));
X}
X
Xstatic void
Xmkswamp()	/* Michiel Huisjes & Fred de Wilde */
X{
X	register struct mkroom *sroom;
X	register int sx,sy,i,eelct = 0;
X
X	for(i=0; i<5; i++) {		/* 5 tries */
X		sroom = &rooms[rn2(nroom)];
X		if(sroom->hx < 0 || sroom->rtype != OROOM ||
X		   has_upstairs(sroom) || has_dnstairs(sroom))
X			continue;
X
X		/* satisfied; make a swamp */
X		sroom->rtype = SWAMP;
X		for(sx = sroom->lx; sx <= sroom->hx; sx++)
X		for(sy = sroom->ly; sy <= sroom->hy; sy++)
X		if(levl[sx][sy].omask == 0 && levl[sx][sy].gmask == 0 &&
X		   levl[sx][sy].mmask == 0 &&
X		   !t_at(sx,sy) && !nexttodoor(sx,sy)) {
X		    if((sx+sy)%2) {
X			levl[sx][sy].typ = POOL;
X			levl[sx][sy].scrsym = POOL_SYM;
X			if(!eelct || !rn2(4)) {
X				(void) makemon(mkclass(S_EEL), sx, sy);
X				eelct++;
X			}
X		    } else if(!rn2(4))	/* swamps tend to be moldy */
X			(void) makemon(mkclass(S_FUNGUS), sx, sy);
X		}
X	}
X}
X
X#ifdef ORACLE
Xstatic void
Xmkdelphi()
X{
X	register struct mkroom *sroom;
X	register struct monst *oracl;
X	int dy,xx,yy;
X
X	if(doorindex >= DOORMAX) return;
X	if(!(sroom = pick_room())) return;
X
X	if(!place_oracle(sroom,&dy,&xx,&yy)) return;
X
X	/* set up Oracle and environment */
X	if(!(oracl = makemon(&mons[PM_ORACLE],xx,yy))) return;
X	sroom->rtype = DELPHI;
X	oracl->mpeaceful = 1;
X
X	yy -= dy;
X	if(ACCESSIBLE(levl[xx-1][yy].typ))
X		(void) mkstatue(&mons[PM_FOREST_CENTAUR], xx-1, yy);
X	if(ACCESSIBLE(levl[xx][yy].typ))
X		(void) mkstatue(&mons[PM_MOUNTAIN_CENTAUR], xx, yy);
X	if(ACCESSIBLE(levl[xx+1][yy].typ))
X		(void) mkstatue(&mons[PM_PLAINS_CENTAUR], xx+1, yy);
X# ifdef FOUNTAINS
X	mkfount(0,sroom);
X# endif
X}
X#endif
X
X#if defined(ALTARS) && defined(THEOLOGY)
Xvoid
Xshrine_pos(sx,sy,troom)
Xint *sx,*sy;
Xstruct mkroom *troom;
X{
X	*sx = troom->lx + ((troom->hx - troom->lx) / 2);
X	*sy = troom->ly + ((troom->hy - troom->ly) / 2);
X}
X
Xstatic void
Xmktemple()
X{
X	register struct mkroom *sroom;
X	int sx,sy;
X
X	if(!(sroom = pick_room())) return;
X
X	/* set up Priest and shrine */
X	sroom->rtype = TEMPLE;
X	shrine_pos(&sx,&sy,sroom);
X	/*
X	 * In temples, shrines are blessed altars
X	 * located in the center of the room
X	 */
X	levl[sx][sy].typ = ALTAR;
X	levl[sx][sy].scrsym = ALTAR_SYM;
X	levl[sx][sy].altarmask = rn2((int)A_LAW+1) | A_SHRINE;
X	priestini(dlevel, sx, sy, (int) levl[sx][sy].altarmask);
X}
X#endif
X
Xboolean
Xnexttodoor(sx,sy)
Xregister int sx, sy;
X{
X	register int dx, dy;
X	register struct rm *lev;
X	for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
X		if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) ||
X		    lev->typ == SDOOR)
X			return(TRUE);
X	return(FALSE);
X}
X
Xboolean
Xhas_dnstairs(sroom)
Xregister struct mkroom *sroom;
X{
X	return(sroom->lx <= xdnstair && xdnstair <= sroom->hx &&
X		   sroom->ly <= ydnstair && ydnstair <= sroom->hy);
X}
X
Xboolean
Xhas_upstairs(sroom)
Xregister struct mkroom *sroom;
X{
X	return(sroom->lx <= xupstair && xupstair <= sroom->hx &&
X		   sroom->ly <= yupstair && yupstair <= sroom->hy);
X}
X
Xint
Xdist2(x0,y0,x1,y1)
Xint x0, y0, x1, y1;
X{
X	register int dx = x0 - x1, dy = y0 - y1;
X	return sq(dx) + sq(dy);
X}
X
X#ifdef THRONES
Xstruct permonst *
Xcourtmon()
X{
X	int     i = rn2(60) + rn2(3*dlevel);
X	if (i > 100)		return(mkclass(S_DRAGON));
X	else if (i > 95)	return(mkclass(S_GIANT));
X	else if (i > 85)	return(mkclass(S_TROLL));
X	else if (i > 75)	return(mkclass(S_CENTAUR));
X	else if (i > 60)	return(mkclass(S_ORC));
X	else if (i > 45)	return(&mons[PM_BUGBEAR]);
X	else if (i > 30)	return(&mons[PM_HOBGOBLIN]);
X	else if (i > 15)	return(mkclass(S_GNOME));
X	else			return(mkclass(S_KOBOLD));
X}
X#endif /* THRONES /**/
X
X#ifdef ARMY
X#define	    NSTYPES	(PM_CAPTAIN-PM_SOLDIER+1)
X
Xstruct {
X    unsigned	pm;
X    unsigned	prob;
X}   squadprob[NSTYPES] = {
X    PM_SOLDIER, 80, PM_SERGEANT, 15, PM_LIEUTENANT, 4, PM_CAPTAIN, 1
X};
X
Xstatic struct permonst *
Xsquadmon() {	    /* return soldier types. */
X
X	register struct permonst *ptr;
X	register int	i, cpro, sel = rnd(80+dlevel);
X
X	for(cpro = i = 0; i < NSTYPES; i++)
X	    if((cpro += squadprob[i].prob) > sel) {
X
X		ptr = &mons[squadprob[i].pm];
X		goto gotone;
X	    }
X	ptr = &mons[squadprob[rn2(NSTYPES)].pm];
Xgotone:
X	if(!(ptr->geno & G_GENOD))  return(ptr);
X	else			    return((struct permonst *) 0);
X}
X#endif /* ARMY /* */
END_OF_FILE
if test 10546 -ne `wc -c <'src/mkroom.c'`; then
    echo shar: \"'src/mkroom.c'\" unpacked with wrong size!
fi
# end of 'src/mkroom.c'
fi
if test -f 'src/mthrowu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/mthrowu.c'\"
else
echo shar: Extracting \"'src/mthrowu.c'\" \(10474 characters\)
sed "s/^X//" >'src/mthrowu.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)mthrowu.c	3.0	88/04/13
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include	"hack.h"
X
Xstatic int movedist();
X
X#define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
X
Xboolean lined_up();
X
Xschar	tbx = 0, tby = 0;	/* used for direction of throw, buzz, etc. */
X
Xconst char *breathwep[] = {	"fragments",
X				"fire",
X				"sleep gas",
X				"frost",
X				"death",
X				"lightning",
X				"poison gas",
X				"acid"
X};
X
Xint
Xthitu(tlev, dam, name)	/* u is hit by sth, but not a monster */
X	register int tlev, dam;
X	register char *name;
X{
X	char buf[BUFSZ];
X	boolean acidic = (!strcmp(name, "splash of venom") && dam);
X	/* A horrible kludge... the problem is that we want to do something
X	 * special--and we can't do it after returning since we might die and
X	 * not return, but the special stuff should be done anyway...
X	 */
X
X	setan(name, buf);
X	if(u.uac + tlev <= rnd(20)) {
X		if(Blind || !flags.verbose) pline("It misses.");
X		else You("are almost hit by %s!", buf);
X		return(0);
X	} else {
X		if(Blind || !flags.verbose) You("are hit!");
X		else You("are hit by %s!", buf);
X		Strcpy(buf,name);
X		/* If name came from xname() we must copy it, otherwise if
X		 * you die, the possession identify will call xname(),
X		 * overwriting xname's buffer, and your tombstone will say
X		 * you were killed by a green gem or some such.
X		 */
X#ifdef POLYSELF
X		if (acidic && resists_acid(uasmon))
X			pline("It doesn't seem to hurt you.");
X		else {
X#endif
X			if (acidic) pline("It burns!");
X			losehp(dam, buf);
X#ifdef POLYSELF
X		}
X#endif
X		return(1);
X	}
X}
X
X/* Be sure this corresponds with what happens to player-thrown objects in
X * dothrow.c (for consistency). --KAA
X */
Xstatic void
Xdrop_throw(obj, ohit, x, y)
Xregister struct obj *obj;
Xboolean ohit;
Xint x,y;
X{
X	int create;
X
X	if (obj->otyp == CREAM_PIE || obj->olet == VENOM_SYM)
X		create = 0;
X	else if (ohit &&
X		 ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) ||
X		  obj->otyp == ROCK))
X		create = !rn2(3);
X	else create = 1;
X	if (create && !flooreffects(obj,x,y)) {
X		obj->ox = x;
X		obj->oy = y;
X		obj->nobj = fobj;
X		fobj = obj;
X		stackobj(fobj);
X		levl[x][y].omask = 1;
X	} else free((genericptr_t)obj);
X}
X
Xstatic void
Xm_throw(x, y, dx, dy, range, obj)
X	register int x,y,dx,dy,range;		/* direction and range */
X	register struct obj *obj;
X{
X	register struct monst *mtmp;
X	struct obj *singleobj;
X	char sym = obj->olet;
X	int damage;
X	int hitu, blindinc=0;
X
X	bhitpos.x = x;
X	bhitpos.y = y;
X
X	singleobj = splitobj(obj, (int)obj->quan-1);
X	/* splitobj leaves the new object in the chain (i.e. the monster's
X	 * inventory).  Remove it.  We can do this in 1 line, but it's highly
X	 * dependent on the fact that we know splitobj() places it immediately
X	 * after obj.
X	 */
X	obj->nobj = singleobj->nobj;
X
X	if(sym) {
X		tmp_at(-1, sym);	/* open call */
X		tmp_at(-3, (int)AT_OBJ);
X	}
X	while(range-- > 0) { /* Actually the loop is always exited by break */
X		bhitpos.x += dx;
X		bhitpos.y += dy;
X		if(levl[bhitpos.x][bhitpos.y].mmask) {
X		    mtmp = m_at(bhitpos.x,bhitpos.y);
X
X		    if(mtmp->data->ac + 8 + obj->spe <= rnd(20)) {
X			miss(distant_name(singleobj,xname), mtmp);
X			if (!range) { /* Last position; object drops */
X			    drop_throw(singleobj, 0, mtmp->mx, mtmp->my);
X			    break;
X			}
X		    } else {
X			damage = dmgval(obj, mtmp->data);
X			if (damage < 1) damage = 1;
X			if (obj->otyp==ACID_VENOM && resists_acid(mtmp->data))
X			    damage = 0;
X			hit(distant_name(singleobj,xname), mtmp,exclam(damage));
X			if (obj->opoisoned) {
X			    if (resists_poison(mtmp->data))
X				kludge("The poison doesn't seem to affect %s.",
X								mon_nam(mtmp));
X			    else {
X				if (rn2(10)) damage += rnd(6);
X				else {
X				    pline("The poison was deadly...");
X				    damage = mtmp->mhp;
X				}
X			    }
X			}
X			if (obj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){
X			    if (resists_acid(mtmp->data)) {
X				pline("%s is unaffected.", Monnam(mtmp));
X				damage = 0;
X			    } else pline("The acid burns %s!", mon_nam(mtmp));
X			}
X			mtmp->mhp -= damage;
X			if(mtmp->mhp < 1) {
X			    if (cansee(mtmp->mx, mtmp->my))
X				pline("%s is killed!", Monnam(mtmp));
X			    mondied(mtmp);
X			}
X
X			if((obj->otyp == CREAM_PIE) ||
X			   (obj->otyp == BLINDING_VENOM)) {
X			    if (cansee(mtmp->mx, mtmp->my))
X				pline("%s is blinded by the %s.",
X				      Monnam(mtmp), xname(singleobj));
X			    if(mtmp->msleep) mtmp->msleep = 0;
X			    mtmp->mcansee = 0;
X			    {
X				register unsigned rnd_tmp = rnd(25) + 20;
X				if((mtmp->mblinded + rnd_tmp) > 127)
X					mtmp->mblinded = 127;
X				else mtmp->mblinded += rnd_tmp;
X			    }
X			}
X			drop_throw(singleobj, 1, bhitpos.x, bhitpos.y);
X			break;
X		    }
X		}
X		if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
X			if (multi) nomul(0);
X
X			switch(obj->otyp) {
X			    int dam;
X			    case CREAM_PIE:
X			    case BLINDING_VENOM:
X				hitu = thitu(8, 0, xname(singleobj));
X				break;
X			    default:
X				dam = dmgval(obj, uasmon);
X				if (dam < 1) dam = 1;
X				hitu = thitu(8+obj->spe, dam, xname(singleobj));
X			}
X			if (obj->opoisoned)
X			    /* it's safe to call xname twice because it's the
X			       same object both times... */
X			    poisoned(xname(singleobj), A_STR, xname(singleobj));
X			if(hitu && (obj->otyp == CREAM_PIE ||
X				     obj->otyp == BLINDING_VENOM)) {
X			    blindinc = rnd(25);
X			    if(obj->otyp == CREAM_PIE) {
X				if(!Blind) pline("Yecch!  You've been creamed.");
X				else	pline("There's something sticky all over your %s.", body_part(FACE));
X			    } else {	/* venom in the eyes */
X				if(Blindfolded) /* nothing */ ;
X				else if(!Blind) pline("The venom blinds you.");
X				else	Your("%s sting.",
X					makeplural(body_part(EYE)));
X			    }
X			}
X			if (hitu || !range) {
X			    drop_throw(singleobj, hitu, u.ux, u.uy);
X			    break;
X			}
X		} else if (!range	/* reached end of path */
X			/* missile hits edge of screen */
X			|| !isok(bhitpos.x+dx,bhitpos.y+dy)
X			/* missile hits the wall */
X			|| IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
X			|| levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
X			|| levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR
X#ifdef SINKS
X			/* Thrown objects "sink" */
X			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
X#endif
X								) {
X		    drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
X		    break;
X		}
X		tmp_at(bhitpos.x, bhitpos.y);
X	}
X	tmp_at(bhitpos.x, bhitpos.y);
X	tmp_at(-1, -1);
X	/* blindfold keeps substances out of your eyes */
X	if (blindinc && !Blindfolded) {
X		u.ucreamed += blindinc;
X		make_blinded(Blinded + blindinc,FALSE);
X	}
X}
X
X/* Remove an item from the monster's inventory.
X */
Xvoid
Xm_useup(mon, obj)
Xstruct monst *mon;
Xstruct obj *obj;
X{
X	struct obj *otmp, *prev;
X
X	prev = ((struct obj *) 0);
X	for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
X		if (otmp == obj) {
X			if (prev)
X				prev->nobj = obj->nobj;
X			else
X				mon->minvent = obj->nobj;
X			free((genericptr_t) obj);
X			break;
X		}
X		prev = otmp;
X	}
X}
X
X/* Always returns 0??? -SAC */
Xint
Xthrwmu(mtmp)	/* monster throws item at you */
Xregister struct monst *mtmp;
X{
X	struct obj *otmp, *select_rwep();
X	register xchar x, y;
X
X	if(lined_up(mtmp)) {
X
X	    if((otmp = select_rwep(mtmp))) {
X
X		/* If you are coming toward the monster, the monster
X		 * should try to soften you up with missiles.  If you are
X		 * going away, you are probably hurt or running.  Give
X		 * chase, but if you are getting too far away, throw.
X		 */
X		x = mtmp->mx;
X		y = mtmp->my;
X		if(!URETREATING(x,y) ||
X		   !rn2(BOLT_LIM-movedist(x,mtmp->mux,y,mtmp->muy)))
X		{
X		    m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
X			movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp);
X		    if (!otmp->quan) m_useup(mtmp, otmp);
X		    nomul(0);
X		    return 0;
X		}
X	    }
X	}
X	return 0;
X}
X
Xint
Xspitmu(mtmp)			/* monster spits substance at you */
Xregister struct monst *mtmp;
X{
X	register struct obj *otmp;
X
X	if(mtmp->mcan) {
X
X	    if(flags.soundok)
X		pline("A dry rattle comes from %s's throat", mon_nam(mtmp));
X	    return 0;
X	}
X	if(lined_up(mtmp)) {
X		otmp = mksobj(mtmp->data==&mons[PM_COBRA] ?
X			BLINDING_VENOM : ACID_VENOM, FALSE);
X		/* really incorrect; should check the attack type; this might
X		 * fail if someone introduces another monster with a venom
X		 * attack...
X		 */
X		if(!rn2(BOLT_LIM-movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy))) {
X
X		    m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
X			movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp);
X		    nomul(0);
X		    return 0;
X		}
X	}
X	return 0;
X}
X
Xint
Xbreamu(mtmp, mattk)			/* monster breathes at you (ranged) */
X	register struct monst *mtmp;
X	register struct attack  *mattk;
X{
X	if(lined_up(mtmp)) {
X
X	    if(mtmp->mcan) {
X		if(flags.soundok) {
X		    if(canseemon(mtmp))
X			pline("%s coughs.", Monnam(mtmp));
X		    else
X			You("hear a cough.");
X		}
X		return(0);
X	    }
X	    if(rn2(3)) {
X
X		if((mattk->adtyp >= 1) && (mattk->adtyp < 11)) {
X
X		    if(canseemon(mtmp))
X			pline("%s breathes %s!", Monnam(mtmp),
X			      breathwep[mattk->adtyp-1]);
X		    buzz((int) (-20 - (mattk->adtyp-1)), (int)mattk->damn,
X			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
X		    nomul(0);
X		} else impossible("Breath weapon %d used", mattk->adtyp-1);
X	    }
X	}
X	return(1);
X}
X
Xboolean
Xlinedup(ax, ay, bx, by)
Xregister xchar ax, ay, bx, by;
X{
X	register xchar x, y;
X
X	tbx = ax - bx;	/* These two values are set for use */
X	tby = ay - by;	/* after successful return.	    */
X
X	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
X	   && movedist(tbx, 0,  tby, 0) < BOLT_LIM) {
X
X		/* Check if there are any dead squares between.  If so,
X		 * it will not be possible to shoot.
X		 */
X		x = bx; y = by;
X		while(x != ax || y != ay) {
X
X		    if (!ACCESSIBLE(levl[x][y].typ) ||
X			  (IS_DOOR(levl[x][y].typ) && 
X				(levl[x][y].doormask & (D_LOCKED | D_CLOSED)))) 
X			return FALSE;
X		    x += sgn(tbx), y += sgn(tby);
X		}
X		return TRUE;
X	}
X	return FALSE;
X}
X
Xboolean
Xlined_up(mtmp)		/* is mtmp in position to use ranged attack? */
X	register struct monst *mtmp;
X{
X	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
X}
X
X/* Check if a monster is carrying a particular item.
X */
Xstruct obj *
Xm_carrying(mtmp, type)
Xstruct monst *mtmp;
Xint type;
X{
X	register struct obj *otmp;
X
X	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
X		if(otmp->otyp == type)
X			return(otmp);
X	return((struct obj *) 0);
X}
X
Xstatic int
Xmovedist(x0, x1, y0, y1)
X{
X	register int absdx, absdy;
X
X	absdx = abs(x1 - x0);
X	absdy = abs(y1 - y0);
X
X	return (max(absdx,absdy));
X}
END_OF_FILE
if test 10474 -ne `wc -c <'src/mthrowu.c'`; then
    echo shar: \"'src/mthrowu.c'\" unpacked with wrong size!
fi
# end of 'src/mthrowu.c'
fi
if test -f 'src/spell.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/spell.c'\"
else
echo shar: Extracting \"'src/spell.c'\" \(10739 characters\)
sed "s/^X//" >'src/spell.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)spell.c	3.0	88/09/18
X *
X *	Copyright (c) M. Stepheneon 1988
X */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X#ifdef SPELLS
Xstatic schar delay;		/* moves left for this spell */
Xstatic struct obj *book;	/* last/current book being xscribed */
X
X#ifdef HARD
X#define spelluses(spell)	spl_book[spell-1].sp_uses
X#define decrnuses(spell)	spl_book[spell-1].sp_uses--
X#endif /* HARD */
X#define spellev(spell)		spl_book[spell-1].sp_lev
X#define spellname(spell)	objects[spl_book[spell-1].sp_id].oc_name
X#define spellid(spell)		spl_book[spell-1].sp_id
X
Xstatic void
Xcursed_book(level)
X	register int	level;
X{
X	switch(rn2(level)) {
X	case 0:
X		You("feel a wrenching sensation.");
X		tele();		/* teleport him */
X		break;
X	case 1:
X		You("feel threatened.");
X		aggravate();
X		break;
X	case 2:
X		make_blinded(Blinded + rn1(100,250),TRUE);
X		break;
X	case 3:
X		take_gold();
X		break;
X	case 4:
X		pline("These runes were just too much to comprehend.");
X		make_confused(HConfusion + rn1(7,16),FALSE);
X		break;
X	case 5:
X		pline("The book was coated with contact poison!");
X		if (uarmg) {
X		    if (uarmg->rustfree)
X			Your("gloves seem unaffected.");
X		    else if (uarmg->spe > -6) {
X			Your("gloves corrode!");
X			uarmg->spe--;
X		    } else
X			Your("gloves look quite corroded.");
X		    break;
X		}
X		if(Poison_resistance) {
X		    losestr(rn1(1,2));
X		    losehp(rnd(6), "contact poison");
X		} else {
X		    losestr(rn1(4,3));
X		    losehp(rnd(10), "contact poison");
X		}
X		break;
X	case 6:
X		if(Antimagic) {
X		    shieldeff(u.ux, u.uy);
X		    pline("The book explodes, but you are unharmed!");
X		} else {
X		    pline("As you read the book, it explodes in your %s!",
X			body_part(FACE));
X		    losehp (2*rnd(10)+5, "exploding rune");
X		}
X		break;
X	default:
X		rndcurse();
X		break;
X	}
X	return;
X}
X
Xstatic int
Xlearn()
X{
X	register int	i;
X	register unsigned booktype;
X
X	if (delay) {	/* not if (delay++), so at end delay == 0 */
X		delay++;
X		return(1); /* still busy */
X	}
X
X	booktype = book->otyp;
X	for (i = 0; i < MAXSPELL; i++)  {
X		if (spl_book[i].sp_id == booktype)  {
X#ifdef HARD
X			Your("knowledge of that spell is keener.");
X			spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev);
X#else
X			pline("Oh, you already know that one!");
X#endif
X			break;
X		} else if (spl_book[i].sp_id == NO_SPELL)  {
X			spl_book[i].sp_id = booktype;
X			spl_book[i].sp_lev = objects[booktype].spl_lev;
X			spl_book[i].sp_flags = objects[booktype].bits;
X#ifdef HARD
X			/* spells have 2 .. 10-level uses. */
X			/* ie 2 or 3 uses w/ most potent */
X			spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev);
X#endif
X			You("add the spell to your repertoire.");
X			makeknown(booktype);
X			break;
X		}
X	}
X	if (i == MAXSPELL) impossible("Too many spells memorized!");
X
X	if (book->cursed) {	/* maybe a demon cursed it */
X		cursed_book(objects[booktype].spl_lev);
X	}
X
X	useup(book);
X	book = 0;
X	return(0);
X}
X
Xint
Xstudy_book(spellbook)
Xregister struct obj *spellbook;
X{
X	register int	 booktype = spellbook->otyp;
X	register boolean oops	  = !spellbook->blessed && (spellbook->cursed ||
Xrn2(20) > (ACURR(A_INT) + 4 + (int)(u.ulevel/2) - 2*objects[booktype].spl_lev));
X
X	if (delay && spellbook == book)
X		You("continue your efforts to memorize the spell.");
X	else {
X		switch(booktype)  {
X
X/* level 1 spells */
X	case SPE_HEALING:
X	case SPE_DETECT_MONSTERS:
X	case SPE_FORCE_BOLT:
X	case SPE_LIGHT:
X	case SPE_SLEEP:
X	case SPE_KNOCK:
X/* level 2 spells */
X	case SPE_MAGIC_MISSILE:
X	case SPE_CONFUSE_MONSTER:
X	case SPE_SLOW_MONSTER:
X	case SPE_CURE_BLINDNESS:
X	case SPE_CREATE_MONSTER:
X	case SPE_DETECT_FOOD:
X	case SPE_WIZARD_LOCK:
X		delay = -objects[booktype].oc_delay;
X		break;
X/* level 3 spells */
X	case SPE_HASTE_SELF:
X	case SPE_CAUSE_FEAR:
X	case SPE_CURE_SICKNESS:
X	case SPE_DETECT_UNSEEN:
X	case SPE_EXTRA_HEALING:
X	case SPE_CHARM_MONSTER:
X	case SPE_CLAIRVOYANCE:
X/* level 4 spells */
X	case SPE_LEVITATION:
X	case SPE_RESTORE_ABILITY:
X	case SPE_INVISIBILITY:
X	case SPE_FIREBALL:
X	case SPE_DETECT_TREASURE:
X		delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay;
X		break;
X/* level 5 spells */
X	case SPE_REMOVE_CURSE:
X	case SPE_MAGIC_MAPPING:
X	case SPE_CONE_OF_COLD:
X	case SPE_IDENTIFY:
X	case SPE_DIG:
X/* level 6 spells */
X	case SPE_TURN_UNDEAD:
X	case SPE_POLYMORPH:
X	case SPE_CREATE_FAMILIAR:
X	case SPE_TELEPORT_AWAY:
X		delay = -objects[booktype].spl_lev * objects[booktype].oc_delay;
X		break;
X/* level 7 spells */
X	case SPE_CANCELLATION:
X	case SPE_FINGER_OF_DEATH:
X	case SPE_GENOCIDE:
X		delay = -8 * objects[booktype].oc_delay;
X		break;
X/* impossible */
X	default:
X		impossible("Unknown spellbook, %d;", booktype);
X		return(0);
X	}
X
X		if (oops) {
X			cursed_book(objects[booktype].spl_lev);
X			nomul(delay);			/* study time */
X			delay = 0;
X			useup(spellbook);
X			return(1);
X		}
X
X		You("begin to memorize the runes.");
X	}
X
X	book = spellbook;
X	set_occupation(learn, "studying", 0);
X	return(1);
X}
X
Xstatic int
Xgetspell()  {
X
X	register int	maxs, ilet, i;
X	char	 lets[BUFSZ], buf[BUFSZ];
X
X	if (spl_book[0].sp_id == NO_SPELL)  {
X
X		You("don't know any spells right now.");
X		return(0);
X	} else  {
X
X	    for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
X	    if (maxs >= MAXSPELL)  {
X
X		impossible("Too many spells memorized.");
X		return(0);
X	    }
X
X	    for(i = 0; (i < maxs) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;
X	    for(i = 26; (i < maxs) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
X
X	    if (maxs == 1)  Strcpy(lets, "a");
X	    else if (maxs < 27)  Sprintf(lets, "a-%c", 'a' + maxs - 1);
X	    else if (maxs == 27)  Sprintf(lets, "a-z A");
X	    else Sprintf(lets, "a-z A-%c", 'A' + maxs - 27);
X	    for(;;)  {
X
X		pline("Cast which spell? [%s ?] ", lets);
X		if ((ilet = readchar()) == '?')  {
X			(void) dovspell();
X			continue;
X		} else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' '))
X			return(0);
X		else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i);
X		You("don't know that spell.");
X	    }
X	}
X}
X
Xint
Xdocast()
X{
X	register int	 spell;
X
X	spell = getspell();
X	if (!spell) return(0);
X
X	return(spelleffects(spell,FALSE));
X}
X
Xint
Xspelleffects(spell,atme)
Xregister int spell;
Xboolean atme;
X{
X	register int energy, damage;
X#ifdef HARD
X	boolean confused = (Confusion != 0);
X#endif
X	struct obj *pseudo;
X
X#ifdef HARD
X	/* note that trying to cast it decrements the # of uses,    */
X	/* even if the mage does not have enough food/energy to use */
X	/* the spell */
X	switch (spelluses(spell)) {
X		case 0:
X		    pline ("That spell is too hard to recall at the moment.");
X		    return(0);
X		case 1:
X		    pline ("You can barely remember the runes of this spell.");
X		    break;
X		case 2:
X		    pline ("This spell is starting to be over-used.");
X		    break;
X		default:
X		    break;
X	}
X	decrnuses(spell);
X#endif
X	energy = spellev(spell);
X	if (u.uhave_amulet) {
X		You("feel the amulet draining your energy away.");
X		energy *= rnd(6);
X	}
X	if(energy > u.uen)  {
X		You("are too weak to cast that spell.");
X		return(0);
X	} else	if ((u.uhunger <= 100 && spell != SPE_DETECT_FOOD) ||
X						(ACURR(A_STR) < 6))  {
X		You("lack the strength for that spell.");
X		return(0);
X	} else	{
X		if (spell != SPE_DETECT_FOOD)
X			morehungry(energy * 10);
X		u.uen -= energy;
X	}
X	flags.botl = 1;
X
X#ifdef HARD
X	if (confused ||
X	    ((int)(ACURR(A_INT) + u.uluck) - 3 * spellev(spell)) < 0) {
X
X		if (Hallucination)
X			pline("Far out... a light show!");
X		else	pline("The air around you crackles as you goof up.");
X		return(0);
X	}
X#endif
X
X/*	pseudo is a temporary "false" object containing the spell stats. */
X	pseudo = mksobj(spellid(spell),FALSE);
X	pseudo->blessed = pseudo->cursed = 0;
X	pseudo->quan = 20;			/* do not let useup get it */
X	switch(pseudo->otyp)  {
X
X/* These spells are all duplicates of wand effects */
X	case SPE_FORCE_BOLT:
X	case SPE_SLEEP:
X	case SPE_MAGIC_MISSILE:
X	case SPE_KNOCK:
X	case SPE_SLOW_MONSTER:
X	case SPE_WIZARD_LOCK:
X	case SPE_FIREBALL:
X	case SPE_CONE_OF_COLD:
X	case SPE_DIG:
X	case SPE_TURN_UNDEAD:
X	case SPE_POLYMORPH:
X	case SPE_TELEPORT_AWAY:
X	case SPE_CANCELLATION:
X	case SPE_FINGER_OF_DEATH:
X	case SPE_LIGHT:
X	case SPE_DETECT_UNSEEN:
X		if (!(objects[pseudo->otyp].bits & NODIR)) {
X			if (atme) u.dx = u.dy = u.dz = 0;
X			else (void) getdir(1);
X			if(!u.dx && !u.dy && !u.dz) {
X			    if((damage = zapyourself(pseudo)))
X				losehp(damage, "self-inflicted injury");
X			} else	weffects(pseudo);
X		} else weffects(pseudo);
X		break;
X/* These are all duplicates of scroll effects */
X	case SPE_CONFUSE_MONSTER:
X	case SPE_DETECT_FOOD:
X	case SPE_CAUSE_FEAR:
X	case SPE_CHARM_MONSTER:
X	case SPE_REMOVE_CURSE:
X	case SPE_MAGIC_MAPPING:
X	case SPE_CREATE_MONSTER:
X	case SPE_IDENTIFY:
X	case SPE_GENOCIDE:
X		(void) seffects(pseudo);
X		break;
X	case SPE_HASTE_SELF:
X	case SPE_DETECT_TREASURE:
X	case SPE_DETECT_MONSTERS:
X	case SPE_LEVITATION:
X	case SPE_RESTORE_ABILITY:
X	case SPE_INVISIBILITY:
X		(void) peffects(pseudo);
X		break;
X	case SPE_HEALING:
X		You("feel a bit better.");
X		healup(rnd(8), 0, 0, 0);
X		break;
X	case SPE_CURE_BLINDNESS:
X		healup(0, 0, 0, 1);
X		break;
X	case SPE_CURE_SICKNESS:
X		You("are no longer ill.");
X		healup(0, 0, 1, 0);
X		break;
X	case SPE_EXTRA_HEALING:
X		You("feel a fair bit better.");
X		healup(d(2,8), 1, 0, 0);
X		break;
X	case SPE_CREATE_FAMILIAR:
X		make_familiar((struct obj *)0);
X		break;
X	case SPE_CLAIRVOYANCE:
X		do_vicinity_map();
X		break;
X	default:
X		impossible("Unknown spell %d attempted.", spell);
X		obfree(pseudo, (struct obj *)0);
X		return(0);
X	}
X	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */
X	return(1);
X}
X
Xvoid
Xlosespells() {
X	register boolean confused = (Confusion != 0);
X	register int	 n, nzap, i;
X
X	book = 0;
X	for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
X	if (!n) return;
X	if (n < MAXSPELL) {
X		nzap = rnd(n);
X		if (nzap < n) nzap += confused;
X		for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL;
X	} else impossible("Too many spells memorized!");
X	return;
X}
X
Xstatic char
Xspellet(spl)
X{
X	return (spl < 27) ? ('a' + spl - 1) : ('A' + spl - 27);
X}
X
Xint
Xdovspell() {
X
X	register int maxs, i;
X	char     buf[BUFSZ], any[BUFSZ];
X
X	if (spl_book[0].sp_id == NO_SPELL)  {
X
X		You("don't know any spells right now.");
X		return 0;
X	}
X
X	for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
X	if (maxs >= MAXSPELL)  {
X
X		impossible("Too many spells memorized.");
X		return 0;
X	}
X	morc = 0;		/* just to be sure */
X	cornline(0, "Currently known spells:");
X
X	for(i = 1; i <= maxs; i++) {
X
X#ifdef HARD
X		Sprintf(buf, "%c %c %s (%d)",
X			spellet(i), (spelluses(i)) ? '-' : '*',
X			spellname(i), spellev(i));
X#else
X		Sprintf(buf, "%c %s (%d)",
X			spellet(i),
X			spellname(i), spellev(i));
X#endif
X		cornline(1, buf);
X		any[i-1] = spellet(i);
X  	}
X	any[i-1] = 0;
X	cornline(2, any);
X
X	return 0;
X}
X
X
X#endif /* SPELLS /**/
END_OF_FILE
if test 10739 -ne `wc -c <'src/spell.c'`; then
    echo shar: \"'src/spell.c'\" unpacked with wrong size!
fi
# end of 'src/spell.c'
fi
echo shar: End of archive 29 \(of 38\).
cp /dev/null ark29isdone
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 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 38 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