From decwrl!ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!zephyr.ens.tek.com!tektronix!tekgen!tekred!saab!billr Thu Aug 3 07:53:29 PDT 1989 Article 696 of comp.sources.games: Path: decwrl!ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!zephyr.ens.tek.com!tektronix!tekgen!tekred!saab!billr From: billr@saab.CNA.TEK.COM (Bill Randle) Newsgroups: comp.sources.games Subject: v07i084: NetHack3 - display oriented dungeons & dragons (Ver. 3.0), Part29/38 Message-ID: <4341@tekred.CNA.TEK.COM> Date: 24 Jul 89 19:06:58 GMT Sender: nobody@tekred.CNA.TEK.COM Lines: 2060 Approved: billr@saab.CNA.TEK.COM Submitted-by: Izchak Miller 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 '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