billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 7, Issue 65 Archive-name: NetHack3/Part10 #! /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 10 (of 38)." # Contents: auxil/nethack.sh src/mhitm.c src/uhitm.c # Wrapped by billr@saab on Sun Jul 23 21:32:53 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'auxil/nethack.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'auxil/nethack.sh'\" else echo shar: Extracting \"'auxil/nethack.sh'\" \(219 characters\) sed "s/^X//" >'auxil/nethack.sh' <<'END_OF_FILE' X#!/bin/sh X# SCCS Id: @(#)nethack.sh 1.4 87/08/08 XHACKDIR=/usr/games/lib/nethackdir XHACK=$HACKDIR/nethack XMAXNROFPLAYERS=4 X Xcd $HACKDIR Xcase $1 in X -s*) X exec $HACK $@ X ;; X *) X exec $HACK $@ $MAXNROFPLAYERS X ;; Xesac END_OF_FILE if test 219 -ne `wc -c <'auxil/nethack.sh'`; then echo shar: \"'auxil/nethack.sh'\" unpacked with wrong size! fi # end of 'auxil/nethack.sh' fi if test -f 'src/mhitm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/mhitm.c'\" else echo shar: Extracting \"'src/mhitm.c'\" \(17168 characters\) sed "s/^X//" >'src/mhitm.c' <<'END_OF_FILE' X/* SCCS Id: @(#)mhitm.c 3.0 88/11/10 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X#ifdef NAMED_ITEMS X# include "artifact.h" X#endif X Xstatic boolean vis, far_noise; Xstatic long noisetime; Xstatic struct obj *otmp; X Xstatic void mrustm P((struct monst *, struct monst *, struct obj *)); Xstatic int hitmm P((struct monst *,struct monst *,struct attack *)); Xstatic int gazemm P((struct monst *,struct monst *,struct attack *)); Xstatic int gulpmm P((struct monst *,struct monst *,struct attack *)); Xstatic int explmm P((struct monst *,struct attack *)); Xstatic int mdamagem P((struct monst *,struct monst *,struct attack *)); Xstatic void mswingsm P((struct monst *, struct monst *, struct obj *)); X Xstatic boolean Xm_incompat(magr, mdef) X/* This must work like in mhitu.c. Specifically, if it's a shopkeeper X * polymorphed into a monster of a specific gender, the specific gender X * overrides. Thus, do not use is_female(), since then a female shopkeeper X * polymorphed into an incubus, or any shopkeeper turned into something X * genderless, would be treated improperly. X * This nonsense could be avoided if every monster had a gender field... X */ Xregister struct monst *magr, *mdef; X{ X return(gender(magr) != 1-gender(mdef)); X} X Xstatic void Xnoises(magr, mattk) X register struct monst *magr; X register struct attack *mattk; X{ X boolean farq = (dist(magr->mx, magr->my) > 15); X X if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) { X far_noise = farq; X noisetime = moves; X You("hear %s%s.", X (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises", X farq ? " in the distance" : ""); X } X} X Xstatic Xvoid Xmissmm(magr, mdef, mattk) X register struct monst *magr, *mdef; X struct attack *mattk; X{ X char buf[BUFSZ]; X X if(vis) { X if(mdef->mimic) seemimic(mdef); X if(magr->mimic) seemimic(magr); X if (sp_melee(magr) && !magr->mcan && X (is_nymph(magr) || !m_incompat(magr,mdef))) { X Sprintf(buf, "%s pretends to be friendly to", X Monnam(magr)); X } else X Sprintf(buf,"%s misses", Monnam(magr)); X pline("%s %s.", buf, mon_nam(mdef)); X } else noises(magr, mattk); X} X Xint Xfightm(mtmp) /* have monsters fight each other */ X register struct monst *mtmp; X{ Xregister struct monst *mon; X/* TODO: this loop needs to be restructured, as we don't know if X * either "mon" or "mon->nmon" will exist after the attack. X */ X for(mon = fmon; mon; mon = mon->nmon) X if(mon != mtmp) { X if(dist2(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3) X return(mattackm(mtmp,mon)); X } X return(-1); X} X X/* X * mattackm returns -1 (magr died), 0 (miss), 1 (mdef hit), or 2 (mdef killed) X * X * Each successive attack has a lower probability of hitting. Some X * rely on the success of previous attacks. X * X * In the case of exploding monsters, the monster dies as well. X */ Xint Xmattackm(magr, mdef) X register struct monst *magr,*mdef; X{ X int i, tmp, nsum, sum[NATTK]; X struct attack *mattk; X struct permonst *pa, *pd; X schar strike; X X if(!magr || !mdef) return(0); /* mike@genat */ X pa = magr->data; pd = mdef->data; X if(magr->mfroz) return(0); /* riv05!a3 */ X X/* Calculate the armour class differential. */ X X tmp = pd->ac + magr->m_lev; X if(mdef->mconf || mdef->mfroz || mdef->msleep){ X tmp += 4; X if(mdef->msleep) mdef->msleep = 0; X } X X if (is_elf(magr->data) && is_orc(mdef->data)) tmp++; X X/* Set up visibility of action */ X vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); X X/* Set flag indicating monster has moved this turn. Necessary since a X * monster might get an attack out of sequence (i.e. before its move) in X * some cases, in which case this still counts as its move for the round X * and it shouldn't move again. X */ X magr->mlstmv = moves; X X/* Now perform all attacks for the monster. */ X X for(i=0; i<NATTK; i++) sum[i] = 0; X for(i = nsum = 0; i < NATTK; nsum |= sum[i++]) { X mattk = &(pa->mattk[i]); X otmp = (struct obj *)0; X switch(mattk->aatyp) { X X case AT_WEAP: /* "hand to hand" attacks */ X otmp = select_hwep(magr); X if(otmp) { X if (vis) mswingsm(magr, mdef, otmp); X tmp += hitval(otmp, pd); X } X case AT_CLAW: X case AT_KICK: X case AT_BITE: X case AT_STNG: X case AT_TUCH: X case AT_BUTT: X if((strike = (tmp > rnd(20+i)))) { X sum[i] = hitmm(magr, mdef, mattk); X if(sum[i] == -1) return(-1); X } else missmm(magr, mdef, mattk); X break; X X case AT_HUGS: /* automatic if prev two attacks succeed */ X strike = 1; X if(sum[i-1] && sum[i-2]) { X sum[i] = hitmm(magr, mdef, mattk); X if(sum[i] == -1) return(-1); X } X break; X X case AT_GAZE: /* will not wake up a sleeper */ X strike = 0; X sum[i] = gazemm(magr, mdef, mattk); X break; X X case AT_EXPL: /* automatic hit if next to */ X strike = -1; X sum[i] = explmm(magr, mattk); X break; X X case AT_ENGL: X if((strike = (tmp > rnd(20+i)))) X sum[i]= gulpmm(magr, mdef, mattk); X else missmm(magr, mdef, mattk); X break; X X default: /* no attack */ X strike = 0; X break; X } X if(sum[i] == 2) return(2); /* defender dead */ X if(strike) mdef->msleep = 0; X if(strike == -1) return(-1); /* attacker dead */ X nsum |= sum[i]; X } X return(nsum); X} X X/* hitmm returns 0 (miss), 1 (hit), 2 (kill), or -1 (magr died) */ Xstatic int Xhitmm(magr, mdef, mattk) X register struct monst *magr,*mdef; X struct attack *mattk; X{ X X if(vis){ X char buf[BUFSZ]; X if(mdef->mimic) seemimic(mdef); X if(magr->mimic) seemimic(magr); X if(sp_melee(magr) && !magr->mcan) { X if(!is_nymph(magr) && m_incompat(magr,mdef)) X goto strike; X Sprintf(buf, "%s %s", Monnam(magr), X mdef->mblinded ? "talks to" : "smiles at"); X pline("%s %s %s.", buf, mon_nam(mdef), X m_incompat(magr,mdef) ? X "engagingly" : "seductively"); X } else { X strike: X switch (mattk->aatyp) { X case AT_BITE: X Sprintf(buf,"%s bites", Monnam(magr)); X break; X case AT_STNG: X Sprintf(buf,"%s stings", Monnam(magr)); X break; X case AT_BUTT: X Sprintf(buf,"%s butts", Monnam(magr)); X break; X case AT_TUCH: X Sprintf(buf,"%s touches", Monnam(magr)); X break; X case AT_HUGS: X if (magr != u.ustuck) { X Sprintf(buf,"%s squeezes", Monnam(magr)); X break; X } X default: X Sprintf(buf,"%s hits", Monnam(magr)); X } X } X pline("%s %s.", buf, mon_nam(mdef)); X } else noises(magr, mattk); X return(mdamagem(magr, mdef, mattk)); X} X Xstatic int Xgazemm(magr, mdef, mattk) X register struct monst *magr, *mdef; X struct attack *mattk; X{ X char buf[BUFSZ]; X X if(vis) { X Sprintf(buf,"%s gazes at", Monnam(magr)); X pline("%s %s.", buf, mon_nam(mdef)); X } X X if (mdef->mblinded || mdef->msleep) { X X if(vis) pline("but nothing happens."); X return(0); X } X X return(mdamagem(magr, mdef, mattk)); X} X Xstatic int Xgulpmm(magr, mdef, mattk) X register struct monst *magr, *mdef; X register struct attack *mattk; X{ X int mx, my, tmp; X char buf[BUFSZ]; X X if(vis) { X Sprintf(buf,"%s swallows", Monnam(magr)); X pline("%s %s.", buf, mon_nam(mdef)); X } X X mx = magr->mx; X my = magr->my; X /* move over top of the defender */ X if(cansee(mdef->mx, mdef->my)) unpmon(mdef); X if(cansee(magr->mx, magr->my)) unpmon(magr); X magr->mx = mdef->mx; X magr->my = mdef->my; X if(cansee(magr->mx, magr->my)) pmon(magr); X if((tmp = mdamagem(magr, mdef, mattk)) == 2) { X levl[mx][my].mmask = 0; X return(2); /* defender died */ X } else { /* defender survived */ X if(cansee(magr->mx, magr->my)) unpmon(magr); X magr->mx = mx; X magr->my = my; X /* move off of defender */ X if(cansee(magr->mx, magr->my)) pmon(magr); X if(cansee(mdef->mx, mdef->my)) pmon(mdef); X return(tmp); X } X} X Xstatic int Xexplmm(magr, mattk) X register struct monst *magr; X register struct attack *mattk; X{ X register struct monst *mon; X X if(cansee(magr->mx, magr->my)) X pline("%s explodes!", Monnam(magr)); X else noises(magr, mattk); X X for(mon = fmon; mon; mon = mon->nmon) X if(mon != magr) { X if(dist2(mon->mx, mon->my, magr->mx, magr->my) < 3) X (void) mdamagem(magr, mon, mattk); X } X X if(dist2(magr->mx, magr->my, u.ux, u.uy) < 3) X (void) mdamageu(magr, d((int)mattk->damn, (int)mattk->damd)); X X mondied(magr); X return(2); X} X Xstatic int Xmdamagem(magr, mdef, mattk) X register struct monst *magr, *mdef; X register struct attack *mattk; X{ X struct permonst *ptr, *pd = mdef->data; X int tmp = d((int)mattk->damn,(int)mattk->damd); X char buf[BUFSZ]; X X switch(mattk->adtyp) { X case AD_DGST: X if(flags.verbose && flags.soundok) pline("\"Burrrrp!\""); X tmp = mdef->mhp; X break; X case AD_STUN: X if (magr->mcan) break; X if(vis) pline("%s staggers for a moment.", Monnam(mdef)); X mdef->mstun = 1; X case AD_PHYS: X if (mattk->aatyp == AT_KICK && thick_skinned(mdef->data)) X tmp = 0; X else if(mattk->aatyp == AT_WEAP) { X if(otmp) { X tmp += dmgval(otmp, pd); X#ifdef NAMED_ITEMS X if(spec_ability(otmp, SPFX_DRLI) && X !resists_drli(mdef->data)) { X int dam = rnd(8); X X tmp += dam; X if(vis) X pline("The %s blade drains the life from %s!", X Hallucination ? hcolor() : black, X mon_nam(mdef)); X mdef->mhpmax -= dam; X if (mdef->m_lev == 0) X tmp = mdef->mhp; X else mdef->m_lev--; X } X#endif X mrustm(magr, mdef, otmp); X } X } X break; X case AD_FIRE: X if (magr->mcan) { X tmp = 0; X break; X } X#ifdef GOLEMS X golemeffects(mdef, AD_FIRE, tmp); X#endif /* GOLEMS */ X if(resists_fire(pd)) { X shieldeff(mdef->mx, mdef->my); X tmp = 0; X } else { X tmp += destroy_mitem(mdef, SCROLL_SYM, AD_FIRE); X tmp += destroy_mitem(mdef, POTION_SYM, AD_FIRE); X#ifdef SPELLS X tmp += destroy_mitem(mdef, SPBOOK_SYM, AD_FIRE); X#endif X } X break; X case AD_COLD: X if (magr->mcan) { X tmp = 0; X break; X } X#ifdef GOLEMS X golemeffects(mdef, AD_COLD, tmp); X#endif /* GOLEMS */ X if(resists_cold(pd)) { X shieldeff(mdef->mx, mdef->my); X tmp = 0; X } else tmp += destroy_mitem(mdef, POTION_SYM, AD_COLD); X break; X case AD_ELEC: X if (magr->mcan) { X tmp = 0; X break; X } X#ifdef GOLEMS X golemeffects(mdef, AD_ELEC, tmp); X#endif /* GOLEMS */ X if(resists_elec(pd)) { X shieldeff(mdef->mx, mdef->my); X tmp = 0; X } X break; X case AD_ACID: X if (magr->mcan) { X tmp = 0; X break; X } X if(resists_acid(pd)) tmp = 0; X break; X case AD_RUST: X#ifdef GOLEMS X if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) { X if (vis) pline("%s falls to pieces!", Monnam(mdef)); X else if(mdef->mtame) X pline("May %s rust in peace.", mon_nam(mdef)); X mondied(mdef); X magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); X ptr = grow_up(magr); X if(!ptr) return(-1); X return(2); X } X#endif /* GOLEMS */ X tmp = 0; X break; X case AD_DCAY: X#ifdef GOLEMS X if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] || X pd == &mons[PM_LEATHER_GOLEM])) { X if (vis) pline("%s falls to pieces!", Monnam(mdef)); X else if(mdef->mtame) X pline("May %s rot in peace.", mon_nam(mdef)); X mondied(mdef); X magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); X ptr = grow_up(magr); X if(!ptr) return(-1); X return(2); X } X#endif /* GOLEMS */ X tmp = 0; X break; X case AD_STON: X if(!resists_ston(pd)) { X magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); X if(vis) pline("%s turns to stone!", Monnam(mdef)); X else if(mdef->mtame) X You("have a peculiarly sad feeling for a moment, then it passes."); X monstone(mdef); X ptr = grow_up(magr); X if(!ptr) return(-1); X return(2); X } X tmp = 0; /* no damage if this fails */ X break; X case AD_TLPT: X if(!magr->mcan && tmp >= mdef->mhp) { X rloc(mdef); X if(vis && !cansee(mdef->mx, mdef->my)) X pline("%s suddenly disappears!", Monnam(mdef)); X } X break; X case AD_SLEE: X if(!resists_sleep(pd) && !magr->mcan && vis && !mdef->msleep) { X pline("%s falls asleep.", Monnam(mdef)); X mdef->msleep = 1; X } X break; X case AD_PLYS: X if(!magr->mcan && vis && !mdef->mfroz) { X pline("%s stops moving.", Monnam(mdef)); X mdef->mfroz = 1; X } X break; X case AD_SLOW: X if(!magr->mcan && vis && mdef->mspeed != MSLOW) { X pline("%s slows down.", Monnam(mdef)); X if (mdef->mspeed == MFAST) mdef->mspeed = 0; X else mdef->mspeed = MSLOW; X } X break; X case AD_CONF: X /* Since confusing another monster doesn't have a real time X * limit, setting spec_used would not really be right (though X * we still should check for it). X */ X if(!magr->mcan && vis && !mdef->mconf && !magr->mspec_used) { X pline("%s looks confused.", Monnam(mdef)); X mdef->mconf = 1; X } X break; X case AD_BLND: X if(!magr->mcan && haseyes(pd)) { X X if(vis && !mdef->mblinded) X pline("%s is blinded.", Monnam(mdef)); X { X register unsigned rnd_tmp; X rnd_tmp = d((int)mattk->damn, (int)mattk->damd); X mdef->mcansee = 0; X if((mdef->mblinded + rnd_tmp) > 127) X mdef->mblinded = 127; X else mdef->mblinded += rnd_tmp; X } X } X tmp = 0; X break; X case AD_CURS: X if(!night() && (magr->data == &mons[PM_GREMLIN])) break; X if(!magr->mcan && !rn2(10)) { X if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN) X were_change(mdef); X#ifdef GOLEMS X if (mdef->data == &mons[PM_CLAY_GOLEM]) { X if (vis) { X pline("Some writing vanishes from %s's head!", X mon_nam(mdef)); X pline("%s dies!", Monnam(mdef)); X } X else if (mdef->mtame) X You("have a strangely sad feeling for a moment, then it passes."); X mondied(mdef); X magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); X ptr = grow_up(magr); X if(!ptr) return(-1); X return(2); X } X#endif /* GOLEMS */ X mdef->mcan = 1; X if (flags.soundok) { X if (!vis) You("hear laughter."); X else pline("%s chuckles.", Monnam(magr)); X } X } X break; X case AD_SGLD: X tmp = 0; X if (magr->mcan || !mdef->mgold) break; X /* technically incorrect; no check for stealing gold from X * between mdef's feet... X */ X magr->mgold += mdef->mgold; X mdef->mgold = 0; X if (vis) { X Strcpy(buf, Monnam(magr)); X pline("%s steals some gold from %s.", buf, X mon_nam(mdef)); X } X break; X case AD_DRLI: X if(rn2(2) && !resists_drli(mdef->data)) { X tmp = d(2,6); X if (vis) X kludge("%s suddenly seems weaker!", Monnam(mdef)); X mdef->mhpmax -= tmp; X if (mdef->m_lev == 0) X tmp = mdef->mhp; X else mdef->m_lev--; X /* Automatic kill if drained past level 0 */ X } X break; X#ifdef SEDUCE X case AD_SSEX: X#endif X case AD_SITM: /* for now these are the same */ X case AD_SEDU: X if (!magr->mcan && mdef->minvent) { X otmp = mdef->minvent; X mdef->minvent = otmp->nobj; X otmp->nobj = magr->minvent; X magr->minvent = otmp; X if (vis) { X Strcpy(buf, Monnam(magr)); X pline("%s steals %s from %s!", buf, X doname(otmp), mon_nam(mdef)); X } X } X tmp = 0; X break; X case AD_DRST: X case AD_DRDX: X case AD_DRCO: X if (!magr->mcan && !rn2(8)) { X if (vis) X pline("%s's %s was poisoned!", Monnam(magr), X mattk->aatyp==AT_BITE ? "bite" : "sting"); X if (resists_poison(mdef->data)) { X if (vis) X pline("The poison doesn't seem to affect %s.", X mon_nam(mdef)); X } else { X if (rn2(10)) tmp += rn1(10,6); X else { X if (vis) pline("The poison was deadly..."); X tmp = mdef->mhp; X } X } X } X break; X case AD_STCK: X case AD_WRAP: /* monsters cannot grab one another, it's too hard */ X break; X default: tmp = 0; X break; X } X if(!tmp) return(1); X X if((mdef->mhp -= tmp) < 1) { X magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); X if(vis) pline("%s is killed!", Monnam(mdef)); X else if(mdef->mtame) X You("have a sad feeling for a moment, then it passes."); X mondied(mdef); X ptr = grow_up(magr); X if(!ptr) return(-1); X return(2); X } X /* fixes a bug where max monster hp could overflow. */ X if(magr->mhpmax <= 0 || magr->mhpmax > MHPMAX) magr->mhpmax = MHPMAX; X X return(1); X} X Xint Xnoattacks(ptr) /* returns 1 if monster doesn't attack */ X struct permonst *ptr; X{ X int i; X X for(i = 0; i < NATTK; i++) X if(ptr->mattk[i].aatyp) return(0); X X return(1); X} X Xstatic void Xmrustm(magr, mdef, obj) Xregister struct monst *magr, *mdef; Xregister struct obj *obj; X{ X if (!magr || !mdef || !obj) return; /* just in case */ X if (mdef->data == &mons[PM_RUST_MONSTER] && X objects[obj->otyp].oc_material == METAL && X !obj->rustfree && obj->spe > -2) { X if(obj->blessed && rn2(3)) { X if (cansee(mdef->mx, mdef->my)) X pline("%s's weapon is not affected.", Monnam(magr)); X } else { X if (cansee(mdef->mx, mdef->my)) X pline("%s's %s!", Monnam(magr), X aobjnam(obj, "corrode")); X obj->spe--; X } X } X} X Xstatic void Xmswingsm(magr, mdef, otemp) Xregister struct monst *magr, *mdef; Xregister struct obj *otemp; X{ X char buf[BUFSZ]; X Strcpy(buf, mon_nam(mdef)); X if (!flags.verbose || Blind || otemp->olet != WEAPON_SYM) return; X pline("%s %s %s %s at %s.", Monnam(magr), X (otemp->otyp == SPEAR || X otemp->otyp == LANCE || X otemp->otyp == GLAIVE || X otemp->otyp == TRIDENT) ? "thrusts" : "swings", X is_female(magr) ? "her" : X is_human(magr->data) ? "his" : "its", X xname(otemp), buf); X} END_OF_FILE if test 17168 -ne `wc -c <'src/mhitm.c'`; then echo shar: \"'src/mhitm.c'\" unpacked with wrong size! fi # end of 'src/mhitm.c' fi if test -f 'src/uhitm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/uhitm.c'\" else echo shar: Extracting \"'src/uhitm.c'\" \(33761 characters\) sed "s/^X//" >'src/uhitm.c' <<'END_OF_FILE' X/* SCCS Id: @(#)uhitm.c 3.0 88/04/11 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X#ifdef NAMED_ITEMS X# include "artifact.h" X#endif X Xstatic boolean hitum(); X#ifdef POLYSELF Xstatic boolean hmonas(); X#endif Xstatic int passive(); X X#ifdef WORM Xextern boolean notonhead; X#endif X Xstruct monst * Xclone_mon(mon) Xstruct monst *mon; X{ X coord mm; X struct monst *m2; X X mm.x = mon->mx; X mm.y = mon->my; X enexto(&mm, mm.x, mm.y); X if (levl[mm.x][mm.y].mmask || mon->mhp <= 1) return (struct monst *)0; X m2 = newmonst(0); X *m2 = *mon; /* copy condition of old monster */ X m2->nmon = fmon; X fmon = m2; X m2->m_id = flags.ident++; X m2->mx = mm.x; X m2->my = mm.y; X X m2->minvent = (struct obj *) 0; /* objects don't clone */ X m2->mleashed = FALSE; X m2->mgold = 0L; X /* Max HP the same, but current HP halved for both. The caller X * might want to override this by halving the max HP also. X */ X m2->mhpmax = mon->mhpmax; X m2->mhp = mon->mhp /= 2; X X /* since shopkeepers and guards will only be cloned if they've been X * polymorphed away from their original forms, the clone doesn't have X * room for the extra information. we also don't want two shopkeepers X * around for the same shop. X * similarly, clones of named monsters don't have room for the name, X * so we just make the clone unnamed instead of bothering to create X * a clone with room and copying over the name from the right place X * (which changes if the original was a shopkeeper or guard). X */ X if (mon->isshk) m2->isshk = FALSE; X if (mon->isgd) m2->isgd = FALSE; X#if defined(ALTARS) && defined(THEOLOGY) X if (mon->ispriest) m2->ispriest = FALSE; X#endif X m2->mxlth = 0; X m2->mnamelth = 0; X m2->mdispl = 0; X pmon(m2); /* display the new monster */ X levl[m2->mx][m2->my].mmask = 1; X if (mon->mtame) (void) tamedog(m2, (struct obj *)0); X return m2; X} X Xboolean Xspecial_case(mtmp) X/* Moved this code from attack() in order to */ X/* avoid having to duplicate it in dokick. */ Xregister struct monst *mtmp; X{ X if (flags.confirm && (mtmp->mpeaceful || mtmp->mtame) && !Confusion X && !Hallucination && (!mtmp->mhide || !mtmp->mundetected) X && (!mtmp->mimic || Protection_from_shape_changers)) { X if (Blind ? Telepat : (!mtmp->minvis || See_invisible)) { X pline("Really attack %s? ", mon_nam(mtmp)); X (void) fflush(stdout); X if (yn() != 'y') { X flags.move = 0; X return(TRUE); X } X } X } X X if(mtmp->mimic && !Protection_from_shape_changers) { X if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK)) X u.ustuck = mtmp; X if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == DOOR_SYM) X#ifdef SPELLS X { X if (okdoor(u.ux+u.dx, u.uy+u.dy)) X#endif X pline("The door actually was %s.", defmonnam(mtmp)); X#ifdef SPELLS X else X pline("That spellbook was %s.", defmonnam(mtmp)); X } X#endif X else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == GOLD_SYM) X pline("That gold was %s!", defmonnam(mtmp)); X else X pline("Wait! That's %s!", defmonnam(mtmp)); X wakeup(mtmp); /* clears mtmp->mimic */ X return(TRUE); X } X X if(mtmp->mhide && mtmp->mundetected && !canseemon(mtmp)) { X mtmp->mundetected = 0; X if (!(Blind ? Telepat : (HTelepat & WORN_HELMET))) { X register struct obj *obj; X X if(levl[mtmp->mx][mtmp->my].omask == 1) { X if(obj = o_at(mtmp->mx,mtmp->my)) X pline("Wait! There's %s hiding under %s!", X defmonnam(mtmp), doname(obj)); X } else if (levl[mtmp->mx][mtmp->my].gmask == 1) X pline("Wait! There's %s hiding under some gold!", X defmonnam(mtmp)); X wakeup(mtmp); X return(TRUE); X } X } X return(FALSE); X} X X X/* try to attack; return FALSE if monster evaded */ X/* u.dx and u.dy must be set */ Xboolean Xattack(mtmp) Xregister struct monst *mtmp; X{ X schar tmp = 0; X register struct permonst *mdat = mtmp->data; X X if(unweapon) { X unweapon=FALSE; X if(flags.verbose) X if(uwep) X You("begin bashing monsters with your %s.", X aobjnam(uwep, NULL)); X else X#ifdef POLYSELF X if (!cantwield(uasmon)) X#endif X You("begin bashing monsters with your %s hands.", X uarmg ? "gloved" : "bare"); /* Del Lamb */ X } X /* andrew@orca: prevent unlimited pick-axe attacks */ X u_wipe_engr(3); X X if(mdat->mlet == S_LEPRECHAUN && !mtmp->mfroz && !mtmp->msleep && X !mtmp->mconf && mtmp->mcansee && !rn2(7) && X (m_move(mtmp, 0) == 2 || /* he died */ X mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* he moved */ X return(FALSE); X X /* This section of code provides protection against accidentally X * hitting peaceful (like '@') and tame (like 'd') monsters. X * There is protection only if you're not blind, confused, or hallu- X * cinating. X */ X /* changes by wwp 5/16/85 */ X if (!Blind && !Confusion && !Hallucination && flags.safe_dog && X (mdat->mlet == S_DOG || mdat->mlet == S_FELINE) && mtmp->mtame) { X mtmp->mflee = 1; X mtmp->mfleetim = rnd(6); X if (mtmp->mnamelth) X You("stop to avoid hitting %s.", NAME(mtmp)); X else X You("stop to avoid hitting your %s.", X mdat->mname); X return(TRUE); X } X X /* moved code to a separate function to share with dokick */ X if(special_case(mtmp)) return(TRUE); X X#ifdef POLYSELF X if(u.umonnum >= 0) { /* certain "pacifist" monsters don't attack */ X set_uasmon(); X if(noattacks(uasmon)) { X You("have no way to attack monsters physically."); X return(TRUE); X } X } X tmp = Luck + mdat->ac + abon() + X ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel); X#else X tmp = Luck + u.ulevel + mdat->ac + abon(); X#endif X X/* it is unchivalrous to attack the defenseless or from behind */ X if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL && X (mtmp->mfroz || mtmp->msleep || mtmp->mflee) && X u.ualign > -10) adjalign(-1); X X/* Adjust vs. (and possibly modify) monster state. */ X X if(mtmp->mstun) tmp += 2; X if(mtmp->mflee) tmp += 2; X X if(mtmp->msleep) { X mtmp->msleep = 0; X tmp += 2; X } X if(mtmp->mfroz) { X tmp += 4; X if(!rn2(10)) mtmp->mfroz = 0; X } X if (is_orc(mtmp->data) && pl_character[0]=='E') tmp++; X X/* with a lot of luggage, your agility diminishes */ X tmp -= (inv_weight() + 40)/20; X if(u.utrap) tmp -= 3; X X#ifdef POLYSELF X if(u.umonnum >= 0) (void) hmonas(mtmp, tmp); X else { X#endif X if(uwep) tmp += hitval(uwep, mdat); X (void) hitum(mtmp, tmp); X#ifdef POLYSELF X } X#endif X X return(TRUE); X} X Xstatic boolean Xknown_hitum(mon, mhit) /* returns TRUE if monster still lives */ X/* Made into a separate function because in some cases we want to know X * in the calling function whether we hit. X */ Xregister struct monst *mon; Xregister int mhit; X{ X register boolean malive = TRUE; X X stoned = FALSE; /* this refers to the thing hit, not you */ X X if(!mhit) { X if(!Blind && flags.verbose) You("miss %s.", mon_nam(mon)); X else You("miss it."); X if(is_human(mon->data) && !(mon->msleep || mon->mfroz)) X wakeup(mon); X } else { X /* we hit the monster; be careful: it might die! */ X X#ifdef WORM X if (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy) X notonhead = TRUE; X#endif X if((malive = hmon(mon, uwep, 0)) == TRUE) { X /* monster still alive */ X if(!rn2(25) && mon->mhp < mon->mhpmax/2) { X mon->mflee = 1; X if(!rn2(3)) mon->mfleetim = rnd(100); X if(u.ustuck == mon && !u.uswallow X#ifdef POLYSELF X && !sticks(uasmon) X#endif X ) X u.ustuck = 0; X } X#ifdef WORM X if(mon->wormno) X cutworm(mon, u.ux+u.dx, u.uy+u.dy, X uwep ? uwep->otyp : 0); X#endif X } X#if defined(ALTARS) && defined(THEOLOGY) X if(mon->ispriest && !rn2(2)) ghod_hitsu(); X#endif X } X return(malive); X} X Xstatic boolean Xhitum(mon, tmp) /* returns TRUE if monster still lives */ Xstruct monst *mon; Xint tmp; X{ X static int malive; X boolean mhit = !((tmp <= rnd(20)) && !u.uswallow); X X malive = known_hitum(mon, mhit); X (void) passive(mon, mhit, malive); X return(malive); X} X Xboolean /* general "damage monster" routine */ Xhmon(mon, obj, thrown) /* return TRUE if mon still alive */ Xregister struct monst *mon; Xregister struct obj *obj; Xregister int thrown; X{ X register int tmp; X boolean hittxt = FALSE; X boolean get_dmg_bonus = TRUE; X boolean ispoisoned = FALSE; X X wakeup(mon); X if(!obj) { X tmp = rnd(2); /* attack with bare hands */ X if(mon->data == &mons[PM_COCKATRICE] && !uarmg X#ifdef POLYSELF X && !resists_ston(uasmon) X#endif X ) { X X kludge("You hit %s with your bare %s.", X mon_nam(mon), makeplural(body_part(HAND))); X You("turn to stone..."); X done_in_by(mon); X } X } else { X if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE || X obj->olet == ROCK_SYM) { X X if(mon->data == &mons[PM_RUST_MONSTER] && obj == uwep && X objects[obj->otyp].oc_material == METAL && X obj->spe > -2) { X if(obj->rustfree) { X pline("The rust on your %s vanishes instantly!", X is_sword(obj) ? "sword" : "weapon"); X } else if(obj->blessed && rnl(4)) X pline("Somehow your %s is not affected!", X is_sword(obj) ? "sword" : "weapon"); X else { X Your("%s!", aobjnam(uwep, "corrode")); X uwep->spe--; X } X } X X if(obj == uwep && (obj->otyp > VOULGE || obj->otyp < BOOMERANG) X && obj->otyp != PICK_AXE) X tmp = rnd(2); X else { X tmp = dmgval(obj, mon->data); X#ifdef NAMED_ITEMS X if(spec_ability(obj, SPFX_DRLI) && X !resists_drli(mon->data)) { X if (!Blind) { X pline("The %s blade draws the life from %s!", X Hallucination ? hcolor() : black, X mon_nam(mon)); X hittxt = TRUE; X } X if (mon->m_lev == 0) tmp = mon->mhp; X else { X int drain = rnd(8); X tmp += drain; X mon->mhpmax -= drain; X mon->m_lev--; X } X } X#endif X if(!thrown && obj == uwep && obj->otyp == BOOMERANG && X !rnl(3)) { X kludge("As you hit %s, the boomerang breaks into splinters.", X mon_nam(mon)); X useup(obj); X hittxt = TRUE; X tmp++; X } X if(thrown && (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)){ X if(((uwep && objects[obj->otyp].w_propellor == X -objects[uwep->otyp].w_propellor) X || obj->otyp==DART || obj->otyp==SHURIKEN) && X obj->opoisoned) X ispoisoned = TRUE; X } X } X } else if(obj->olet == POTION_SYM) { X if (obj->quan > 1) setuwep(splitobj(obj, 1)); X else setuwep((struct obj *)0); X freeinv(obj); X potionhit(mon,obj); X hittxt = TRUE; X tmp = 1; X } else switch(obj->otyp) { X case HEAVY_IRON_BALL: X tmp = rnd(25); break; X case BOULDER: X tmp = rnd(20); break; X#ifdef MEDUSA X case MIRROR: X You("break your mirror. That's bad luck!"); X change_luck(-2); X useup(obj); X return(TRUE); X#endif X case EXPENSIVE_CAMERA: X You("succeed in destroying your camera. Congratulations!"); X useup(obj); X return(TRUE); X case CORPSE: /* fixed by polder@cs.vu.nl */ X if(obj->corpsenm == PM_COCKATRICE) { X kludge("You hit %s with the cockatrice corpse.", X mon_nam(mon)); X if(resists_ston(mon->data)) { X tmp = 1; X hittxt = TRUE; X break; X } X kludge("%s turns to stone.", Monnam(mon)); X stoned = TRUE; X xkilled(mon,0); X return(FALSE); X } X tmp = bigmonst(&mons[obj->corpsenm]) ? 5 : 2 ; X break; X case EGG: /* only possible if hand-to-hand */ X if(obj->corpsenm > -1 X && obj->corpsenm != PM_COCKATRICE X && mon->data==&mons[PM_COCKATRICE]) { X kludge("You hit %s with the %s egg%s.", X mon_nam(mon), X mons[obj->corpsenm].mname, X (obj->quan==1) ? "" : "s"); X hittxt = TRUE; X pline("The egg%sn't live any more...", X (obj->quan==1) ? " is" : "s are"); X obj->otyp = ROCK; X obj->olet = GEM_SYM; X obj->known = obj->dknown = 0; X obj->owt = weight(obj); X } X tmp = 1; X break; X case CLOVE_OF_GARLIC: /* no effect against demons */ X if(is_undead(mon->data)) mon->mflee = 1; X tmp = 1; X break; X case CREAM_PIE: X#ifdef POLYSELF X case BLINDING_VENOM: X if(Blind) X pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!"); X else if (obj->otyp == BLINDING_VENOM) X pline("The venom blinds %s%s!", mon_nam(mon), X mon->mcansee ? "" : " further"); X#else X if(Blind) pline("Splat!"); X#endif X else X pline("The cream pie splashes over %s%s!", X mon_nam(mon), X (haseyes(mon->data) && X mon->data != &mons[PM_FLOATING_EYE]) X ? "'s face" : ""); X if(mon->msleep) mon->msleep = 0; X setmangry(mon); X mon->mcansee = 0; X if((mon->mblinded + tmp) > 127) mon->mblinded = 127; X else mon->mblinded += tmp; X hittxt = TRUE; X get_dmg_bonus = FALSE; X tmp = 0; X break; X#ifdef POLYSELF X case ACID_VENOM: /* only possible if thrown */ X if(resists_acid(mon->data)) { X kludge("Your venom hits %s harmlessly.", X mon_nam(mon)); X tmp = 0; X } else { X kludge("Your venom burns %s!", mon_nam(mon)); X tmp = dmgval(obj, mon->data); X } X hittxt = TRUE; X get_dmg_bonus = FALSE; X break; X#endif X default: X /* non-weapons can damage because of their weight */ X /* (but not too much) */ X tmp = obj->owt/10; X if(tmp < 1) tmp = 1; X else tmp = rnd(tmp); X if(tmp > 6) tmp = 6; X } X } X X /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) X * *OR* if attacking bare-handed!! */ X X if (get_dmg_bonus) { X tmp += u.udaminc; X /* If you throw using a propellor, you don't get a strength X * bonus but you do get an increase-damage bonus. X */ X if(!obj || !uwep || X (obj->olet != GEM_SYM && obj->olet != WEAPON_SYM) || X objects[obj->otyp].w_propellor != X -objects[uwep->otyp].w_propellor) X tmp += dbon(); X } X X/* TODO: Fix this up. multiple engulf attacks now exist. X if(u.uswallow) { X if((tmp -= u.uswldtim) <= 0) { X Your("%s are no longer able to hit.", X makeplural(body_part(ARM))); X return(TRUE); X } X } X */ X if (ispoisoned) { X /* OK to reference obj because ispoisoned can only be set X * when obj is a throwing weapon */ X hit(xname(obj), mon, exclam(tmp)); X hittxt = TRUE; X if(resists_poison(mon->data)) X kludge("The poison doesn't seem to affect %s.", mon_nam(mon)); X else if (rn2(10)) X tmp += rnd(6); X else { X pline("The poison was deadly..."); X xkilled(mon,0); X return FALSE; X } X } X if(tmp < 1) tmp = 1; X X mon->mhp -= tmp; X if(mon->mhp < 1) { X killed(mon); X return(FALSE); X } X if(mon->mtame && (!mon->mflee || mon->mfleetim)) { X#ifdef SOUNDS X if (rn2(8)) yelp(mon); X else growl(mon); /* give them a moment's worry */ X#endif X mon->mtame--; X mon->mflee = 1; /* Rick Richardson */ X mon->mfleetim += 10*rnd(tmp); X } X if((mon->data == &mons[PM_BLACK_PUDDING] || X mon->data == &mons[PM_BROWN_PUDDING]) && uwep && X uwep == obj && objects[obj->otyp].oc_material == METAL X && mon->mhp > 1 && !thrown && !mon->mcan) { X X if (clone_mon(mon)) { X pline("%s divides as you hit it!", Monnam(mon)); X hittxt = TRUE; X } X } X X if(!hittxt) { X if(thrown) X /* thrown => obj exists */ X hit(xname(obj), mon, exclam(tmp) ); X else if(Blind || !flags.verbose) You("hit it."); X else You("hit %s%s", mon_nam(mon), exclam(tmp)); X } X X if(u.umconf && !thrown) { X if(!Blind) { X Your("%s stop glowing %s.", X makeplural(body_part(HAND)), X Hallucination ? hcolor() : red); X } X if(!resist(mon, '+', 0, NOTELL)) mon->mconf = 1; X if(!mon->mstun && !mon->mfroz && !mon->msleep && X !Blind && mon->mconf) X pline("%s appears confused.", Monnam(mon)); X u.umconf = 0; X } X return(TRUE); /* mon still alive */ X} X X#ifdef POLYSELF Xstatic int Xdamageum(mdef, mattk) Xregister struct monst *mdef; Xregister struct attack *mattk; X{ X register struct permonst *pd = mdef->data; X register int tmp = d((int)mattk->damn, (int)mattk->damd); X X stoned = FALSE; X if (is_demon(uasmon) && !rn2(13) && !uwep X#ifdef HARD X && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS X && u.umonnum != PM_BALROG X#endif X ) { X struct monst *dtmp; X pline("Some hell-p has arrived!"); X/* if((dtmp = mkmon_at(uasmon, u.ux, u.uy)))*/ X/* if((dtmp = makemon(uasmon, u.ux, u.uy)))*/ X if((dtmp = makemon(&mons[ndemon()], u.ux, u.uy))) X (void)tamedog(dtmp, (struct obj *)0); X return(0); X } X X switch(mattk->adtyp) { X case AD_STUN: X if(!Blind) X pline("%s staggers for a moment.", Monnam(mdef)); X mdef->mstun = 1; X /* fall through to next case */ X case AD_WERE: /* no effect on monsters */ X case AD_PHYS: X if(mattk->aatyp == AT_WEAP) { X if(uwep) tmp = 0; X } else if(mattk->aatyp == AT_KICK) X if(thick_skinned(mdef->data)) tmp = 0; X break; X case AD_FIRE: X#ifdef GOLEMS X golemeffects(mdef, AD_FIRE, tmp); X#endif /* GOLEMS */ X if(resists_fire(pd)) { X shieldeff(mdef->mx, mdef->my); X tmp = 0; X } else { X if(!Blind) pline("%s is on fire!", Monnam(mdef)); X tmp += destroy_mitem(mdef, SCROLL_SYM, AD_FIRE); X tmp += destroy_mitem(mdef, POTION_SYM, AD_FIRE); X#ifdef SPELLS X tmp += destroy_mitem(mdef, SPBOOK_SYM, AD_FIRE); X#endif X } X break; X case AD_COLD: X#ifdef GOLEMS X golemeffects(mdef, AD_COLD, tmp); X#endif /* GOLEMS */ X if(resists_cold(pd)) { X shieldeff(mdef->mx, mdef->my); X tmp = 0; X } else { X if(!Blind) pline("%s is covered in frost.", Monnam(mdef)); X tmp += destroy_mitem(mdef, POTION_SYM, AD_COLD); X } X break; X case AD_ELEC: X#ifdef GOLEMS X golemeffects(mdef, AD_ELEC, tmp); X#endif /* GOLEMS */ X if(resists_elec(pd)) { X shieldeff(mdef->mx, mdef->my); X tmp = 0; X } X break; X case AD_ACID: X if(resists_acid(pd)) tmp = 0; X break; X case AD_STON: X if(!resists_ston(pd)) { X stoned = TRUE; X if(!Blind) pline("%s turns to stone.", Monnam(mdef)); X xkilled(mdef, 0); X return(2); X } X tmp = 0; /* no damage if this fails */ X break; X#ifdef SEDUCE X case AD_SSEX: X#endif X case AD_SEDU: X case AD_SITM: X if(mdef->minvent) { X struct obj *otmp, *addinv(), *stealoid; X int isize = inv_cnt(); X X stealoid = (struct obj *)0; X if (is_mercenary(pd)) { X for(otmp = mdef->minvent; otmp; otmp=otmp->nobj) X if (otmp->otyp >= PLATE_MAIL && otmp->otyp X <= ELVEN_CLOAK) stealoid = otmp; X } X if (stealoid) { X boolean stolen = FALSE; X /* Is "he"/"his" always correct? */ X kludge("You seduce %s and he starts to take off his clothes.", X mon_nam(mdef)); X while(mdef->minvent) { X otmp = mdef->minvent; X mdef->minvent = otmp->nobj; X if (!stolen && otmp==stealoid) { X if(isize < 52) { X otmp = addinv(otmp); X isize++; X } else dropy(otmp); X stealoid = otmp; X stolen = TRUE; X } else { X if(isize < 52) { X otmp = addinv(otmp); X isize++; X } else dropy(otmp); X You("steal: "); X prinv(otmp); X } X } X if (!stolen) X impossible("Player steal fails!"); X else { X kludge("%s finishes taking off his suit.", X Monnam(mdef)); X You("steal a %s.", xname(stealoid)); X#ifdef ARMY X mdef->data = &mons[PM_UNARMORED_SOLDIER]; X#endif X } X } else { X otmp = mdef->minvent; X mdef->minvent = otmp->nobj; X if(isize < 52) otmp = addinv(otmp); X else dropy(otmp); X You("steal: "); X prinv(otmp); X } X } X tmp = 0; X break; X case AD_SGLD: X if (mdef->mgold) { X u.ugold += mdef->mgold; X mdef->mgold = 0; X Your("purse feels heavier."); X } X tmp = 0; X break; X case AD_TLPT: X if(tmp <= 0) tmp = 1; X if(tmp < mdef->mhp) { X rloc(mdef); X if(!Blind) pline("%s suddenly disappears!", Monnam(mdef)); X } X break; X case AD_BLND: X if(haseyes(pd)) { X X if(!Blind) pline("%s is blinded.", Monnam(mdef)); X mdef->mcansee = 0; X mdef->mblinded += tmp; X } X tmp = 0; X break; X case AD_CURS: X if (night() && !rn2(10) && !mdef->mcan) { X#ifdef GOLEMS X if (mdef->data == &mons[PM_CLAY_GOLEM]) { X if (!Blind) X pline("Some writing vanishes from %s's head!", X mon_nam(mdef)); X xkilled(mdef, 0); X return 2; X } X#endif /* GOLEMS */ X mdef->mcan = 1; X You("chuckle."); X } X tmp = 0; X break; X case AD_DRLI: X if(rn2(2) && !resists_drli(pd)) { X int xtmp = d(2,6); X kludge("%s suddenly seems weaker!", Monnam(mdef)); X mdef->mhpmax -= xtmp; X if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev--) { X kludge("%s dies.", Monnam(mdef)); X xkilled(mdef,0); X return(2); X } X } X tmp = 0; X break; X case AD_RUST: X#ifdef GOLEMS X if (pd == &mons[PM_IRON_GOLEM]) { X kludge("%s falls to pieces!", Monnam(mdef)); X xkilled(mdef,0); X return(2); X } X#endif /* GOLEMS */ X tmp = 0; X break; X case AD_DCAY: X#ifdef GOLEMS X if (pd == &mons[PM_WOOD_GOLEM] || X pd == &mons[PM_LEATHER_GOLEM]) { X kludge("%s falls to pieces!", Monnam(mdef)); X xkilled(mdef,0); X return(2); X } X#endif /* GOLEMS */ X case AD_DRST: X case AD_DRDX: X case AD_DRCO: X if (!rn2(8)) { X Your("%s was poisoned!", mattk->aatyp==AT_BITE ? X "bite" : "sting"); X if (resists_poison(mdef->data)) X kludge("The poison doesn't seem to affect %s.", X mon_nam(mdef)); X else { X if (!rn2(10)) { X Your("poison was deadly..."); X tmp = mdef->mhp; X } else tmp += rn1(10,6); X } X } X break; X case AD_WRAP: X case AD_STCK: X if (!sticks(mdef->data)) X u.ustuck = mdef; /* it's now stuck to you */ X break; X default: tmp = 0; X break; X } X if(!tmp) return(1); X X if((mdef->mhp -= tmp) < 1) { X X if(mdef->mtame) { X if(!Blind) You("killed your %s!", mon_nam(mdef)); X else You("feel embarrassed for a moment."); X } else { X if(!Blind && flags.verbose) pline("%s is killed!", Monnam(mdef)); X else You("kill it!"); X } X xkilled(mdef, 0); X return(2); X } X return(1); X} X Xstatic int Xexplum(mdef, mattk) Xregister struct monst *mdef; Xregister struct attack *mattk; X{ X switch(mattk->adtyp) { X case AD_BLND: X if(mdef->data->mlet != S_YLIGHT) { X kludge("%s is blinded by your flash of light!", Monnam(mdef)); X if (!mdef->mblinded) { X mdef->mblinded += rn2(25); X mdef->mcansee = 0; X } X } X break; X case AD_COLD: X You("explode!"); X if (!resists_cold(mdef->data)) { X kludge("%s gets blasted!", Monnam(mdef)); X mdef->mhp -= d(6,6); X if (mdef->mhp <= 0) { X killed(mdef); X return(2); X } X#ifdef GOLEMS X } else if (is_golem(mdef->data)) { X golemeffects(mdef, AD_COLD, d(6,6)); X shieldeff(mdef->mx, mdef->my); X#endif /* GOLEMS */ X } else { X shieldeff(mdef->mx, mdef->my); X kludge("The blast doesn't seem to affect %s.", X mon_nam(mdef)); X } X break; X default: break; X } X return(1); X} X Xstatic int Xgulpum(mdef,mattk) Xregister struct monst *mdef; Xregister struct attack *mattk; X{ X register int tmp; X register int dam = d((int)mattk->damn, (int)mattk->damd); X /* Not totally the same as for real monsters. Specifically, these X * don't take multiple moves. (It's just too hard, for too little X * result, to program monsters which attack from inside you, which X * would be necessary if done accurately.) Instead, we arbitrarily X * kill the monster immediately for AD_DGST and we regurgitate them X * after exactly 1 round of attack otherwise. -KAA X */ X X#ifdef WORM X if(mdef->wormno) return 0; X#endif X if(u.uhunger < 1500 && !u.uswallow) { X X if(mdef->data->mlet != S_COCKATRICE) { X#ifdef LINT /* static char msgbuf[BUFSZ]; */ X char msgbuf[BUFSZ]; X#else X static char msgbuf[BUFSZ]; X#endif X/* TODO: get the symbol display also to work (monster symbol is removed from X * the screen and you moved onto it, then you get moved back and it gets X * moved back if the monster survives--just like when monsters swallow you. X */ X kludge("You engulf %s!", mon_nam(mdef)); X switch(mattk->adtyp) { X case AD_DGST: X u.uhunger += 20*mdef->mhpmax; X newuhs(FALSE); X xkilled(mdef,2); X Sprintf(msgbuf, "You totally digest %s.", X Blind ? "it" : mon_nam(mdef)); X if ((tmp = mdef->mhpmax/5)) { X kludge("You digest %s.", mon_nam(mdef)); X nomul(-tmp); X nomovemsg = msgbuf; X } else pline(msgbuf); X return(2); X case AD_PHYS: X kludge("%s is pummeled with your debris!",Monnam(mdef)); X break; X case AD_ACID: X kludge("%s is covered with your goo!", Monnam(mdef)); X if (resists_acid(mdef->data)) { X kludge("It seems harmless to %s.", mon_nam(mdef)); X dam = 0; X } X break; X case AD_BLND: X if (mdef->mcansee) X kludge("%s can't see in there!", Monnam(mdef)); X mdef->mcansee = 0; X dam += mdef->mblinded; X if (dam > 127) dam = 127; X mdef->mblinded = dam; X dam = 0; X break; X case AD_ELEC: X if (rn2(2)) { X kludge("The air around %s crackles with electricity.", mon_nam(mdef)); X if (resists_elec(mdef->data)) { X kludge("%s seems unhurt.", Monnam(mdef)); X dam = 0; X } X#ifdef GOLEMS X golemeffects(mdef,(int)mattk->adtyp,dam); X#endif X } else dam = 0; X break; X case AD_COLD: X if (rn2(2)) { X if (resists_cold(mdef->data)) { X kludge("%s seems mildly chilly.", Monnam(mdef)); X dam = 0; X } else X kludge("%s is freezing to death!",Monnam(mdef)); X#ifdef GOLEMS X golemeffects(mdef,(int)mattk->adtyp,dam); X#endif X } else dam = 0; X break; X case AD_FIRE: X if (rn2(2)) { X if (resists_fire(mdef->data)) { X kludge("%s seems mildly hot.", Monnam(mdef)); X dam = 0; X } else X kludge("%s is burning to a crisp!",Monnam(mdef)); X#ifdef GOLEMS X golemeffects(mdef,(int)mattk->adtyp,dam); X#endif X } else dam = 0; X break; X } X if ((mdef->mhp -= dam) <= 0) { X kludge("%s is killed!", Monnam(mdef)); X xkilled(mdef,0); X return(2); X } X kludge("You regurgitate %s!", mon_nam(mdef)); X if (Blind) X pline("Obviously, you didn't like its taste."); X else X pline("Obviously, you didn't like %s's taste.", X mon_nam(mdef)); X } else { X kludge("You bite into %s", mon_nam(mdef)); X You("turn to stone..."); X killer = "poor choice of food"; X done("stoned"); X } X } X return(0); X} X Xstatic void Xmissum(mdef) Xregister struct monst *mdef; X{ X#ifdef POLYSELF X if (u.usym==S_NYMPH X# ifdef SEDUCE X|| ((u.umonnum==PM_INCUBUS || u.umonnum==PM_SUCCUBUS) && !incompatible(mdef)) X# endif X ) X kludge("You pretend to be friendly to %s.", mon_nam(mdef)); X else X#endif X if(!Blind && flags.verbose) You("miss %s.", mon_nam(mdef)); X else You("miss it."); X if(is_human(mdef->data) && !(mdef->msleep || mdef->mfroz)) X wakeup(mdef); X} X Xstatic boolean Xhmonas(mon, tmp) /* attack monster as a monster. */ Xregister struct monst *mon; Xregister int tmp; X{ X register struct attack *mattk; X int i, sum[NATTK]; X int nsum = 0; X schar dhit; X X for(i = 0; i < NATTK; i++) { X X mattk = &(uasmon->mattk[i]); X switch(mattk->aatyp) { X case AT_WEAP: Xuse_weapon: X /* Certain monsters don't use weapons when encountered as enemies, X * but players who polymorph into them have hands or claws and thus X * should be able to use weapons. This shouldn't prohibit the use X * of most special abilities, either. X */ X /* Potential problem: if the monster gets multiple weapon attacks, X * we currently allow the player to get each of these as a weapon X * attack. Is this really desirable? X */ X if(uwep) tmp += hitval(uwep, mon->data); X dhit = !((tmp <= rnd(20)) && !u.uswallow); X /* Enemy dead, before any special abilities used */ X if (!known_hitum(mon,dhit)) return 0; X /* Do not print "You hit" message, since known_hitum X * already did it. X */ X if (dhit && mattk->adtyp != AD_SPEL X && mattk->adtyp != AD_PHYS) X sum[i] = damageum(mon,mattk); X else sum[i] = 0; X break; X case AT_CLAW: X if (i==0 && uwep && humanoid(uasmon)) goto use_weapon; X case AT_KICK: X case AT_BITE: X case AT_STNG: X case AT_TUCH: X case AT_BUTT: X if (i==0 && uwep && (u.usym==S_LICH X )) goto use_weapon; X if(dhit = (tmp > rnd(20) || u.uswallow)) { X/* <----- <----- <----- <----- <----- <----- <----- <----- <----- */ Xif (!u.uswallow && (u.usym==S_NYMPH X#ifdef SEDUCE X || ((u.umonnum==PM_INCUBUS || u.umonnum==PM_SUCCUBUS) && !incompatible(mon)) X#endif X )) { X kludge("You %s %s %s.", mon->mblinded ? "talk to" : "smile at", X mon_nam(mon), X incompatible(mon) ? "engagingly" : "seductively"); X} X/* <----- <----- <----- <----- <----- <----- <----- <----- <----- */ X else if (mattk->aatyp == AT_KICK) X kludge("You kick %s.", mon_nam(mon)); X else if (mattk->aatyp == AT_BITE) X kludge("You bite %s.", mon_nam(mon)); X else if (mattk->aatyp == AT_STNG) X kludge("You sting %s.", mon_nam(mon)); X else if (mattk->aatyp == AT_BUTT) X kludge("You butt %s.", mon_nam(mon)); X else if (mattk->aatyp == AT_TUCH) X kludge("You touch %s.", mon_nam(mon)); X else kludge("You hit %s.", mon_nam(mon)); X sum[i] = damageum(mon, mattk); X } else { X missum(mon); X sum[i] = 0; X } X break; X X case AT_HUGS: X /* automatic if prev two attacks succeed, or if X * already grabbed in a previous attack X */ X dhit = 1; X if (sticks(mon->data)) sum[i] = 0; X else if (mon==u.ustuck) { X kludge("%s is being %s.", Monnam(mon), X#ifdef GOLEMS X u.umonnum==PM_ROPE_GOLEM ? "choked": X#endif X "crushed"); X sum[i] = damageum(mon, mattk); X } else if(sum[i-1] && sum[i-2]) { X kludge("You grab %s!", mon_nam(mon)); X u.ustuck = mon; X sum[i] = damageum(mon, mattk); X } else sum[i] = 0; X break; X X case AT_EXPL: /* automatic hit if next to */ X dhit = -1; X sum[i] = explum(mon, mattk); X break; X X case AT_ENGL: X if((dhit = (tmp > rnd(20+i)))) X sum[i]= gulpum(mon,mattk); X else { X missum(mon); X sum[i] = 0; X } X break; X X case AT_MAGC: X /* No check for uwep; if wielding nothing we want to X * do the normal 1-2 points bare hand damage... X */ X if (i==0 && (u.usym==S_KOBOLD X || u.usym==S_ORC X || u.usym==S_GNOME X )) goto use_weapon; X X case AT_NONE: X sum[i] = 0; X continue; X /* Not break--avoid passive attacks from enemy */ X X default: /* Strange... */ X impossible("strange attack of yours (%d)", X mattk->aatyp); X case AT_BREA: X case AT_SPIT: X case AT_GAZE: /* all done using #monster command */ X sum[i] = dhit = 0; X break; X } X if (dhit == -1) X rehumanize(); X if(sum[i] == 2) return(passive(mon, 1, 0)); /* defender dead */ X else { X (void) passive(mon, sum[i], 1); X nsum |= sum[i]; X } X if (uasmon == &playermon) X break; /* No extra attacks if no longer a monster */ X if (multi < 0) X break; /* If paralyzed while attacking, i.e. floating eye */ X } X return(nsum); X} X X#endif X X/* Special (passive) attacks on you by monsters done here. */ X Xstatic int Xpassive(mon, mhit, malive) Xregister struct monst *mon; Xregister boolean mhit; Xregister int malive; X{ X register struct permonst *ptr = mon->data; X register int i, tmp; X X for(i = 0; ; i++) { X if(i >= NATTK) return(malive | mhit); /* no passive attacks */ X if(ptr->mattk[i].aatyp == AT_NONE) break; /* try this one */ X } X X/* These affect you even if they just died */ X X switch(ptr->mattk[i].adtyp) { X X case AD_ACID: X if(mhit && rn2(2)) { X if (Blind || !flags.verbose) You("are splashed!"); X else You("are splashed by %s's acid!", mon_nam(mon)); X X tmp = d((int)mon->m_lev, (int)ptr->mattk[i].damd); X#ifdef POLYSELF X if(!resists_acid(uasmon)) X#endif X mdamageu(mon, tmp); X if(!rn2(30)) corrode_armor(); X } X if(mhit && !rn2(6)) corrode_weapon(); X break; X case AD_MAGM: X /* wrath of gods for attacking Oracle */ X if(Antimagic) { X shieldeff(u.ux, u.uy); X pline("A hail of magic missiles narrowly misses you!"); X } else { X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd); X You("are hit by magic missiles appearing from thin air!"); X mdamageu(mon, tmp); X } X break; X default: X break; X } X X/* These only affect you if they still live */ X X if(malive && !mon->mcan && rn2(3)) { X X switch(ptr->mattk[i].adtyp) { X X case AD_PLYS: /* specifically floating eye */ X if(canseemon(mon)) { X X tmp = -d((int)mon->m_lev+1, (int)ptr->mattk[i].damd); X if(mon->mcansee) { X if(Reflecting & W_AMUL) { X makeknown(AMULET_OF_REFLECTION); X pline("%s's gaze is reflected by your medallion.", X Monnam(mon)); X } else if(Reflecting & W_ARMS) { X makeknown(SHIELD_OF_REFLECTION); X pline("%s's gaze is reflected by your shield.", X Monnam(mon)); X } else { X You("are frozen by %s's gaze!", mon_nam(mon)); X nomul((ACURR(A_WIS) > 12 || rn2(4)) ? tmp : -120); X } X } else { X pline("%s cannot defend itself.", Amonnam(mon,"blind")); X if(!rn2(500)) change_luck(-1); X } X } X break; X case AD_COLD: /* brown mold or blue jelly */ X if(dist(mon->mx, mon->my) <= 3) { X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd); X if(Cold_resistance) { X shieldeff(u.ux, u.uy); X You("feel a mild chill."); X#ifdef POLYSELF X#ifdef GOLEMS X ugolemeffects(AD_COLD, tmp); X#endif /* GOLEMS */ X#endif X tmp = 0; X break; X } X You("are suddenly very cold!"); X mdamageu(mon, tmp); X /* monster gets stronger with your heat! */ X mon->mhp += tmp / 2; X if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp; X /* at a certain point, the monster will reproduce! */ X if(mon->mhpmax > ((mon->m_lev+1) * 8)) { X register struct monst *mtmp; X X if(mtmp = clone_mon(mon)) { X mtmp->mhpmax = mon->mhpmax /= 2; X if(!Blind) X pline("%s multiplies from your heat!", X Monnam(mon)); X } X } X } X break; X case AD_STUN: /* specifically yellow mold */ X if(!Stunned) X make_stunned((long)d((int)mon->m_lev+1, (int)ptr->mattk[i].damd), TRUE); X break; X case AD_FIRE: X if(dist(mon->mx, mon->my) <= 3) { X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd); X if(Fire_resistance) { X shieldeff(u.ux, u.uy); X You("feel mildly warm."); X#ifdef POLYSELF X#ifdef GOLEMS X ugolemeffects(AD_FIRE, tmp); X#endif /* GOLEMS */ X#endif X tmp = 0; X break; X } X You("are suddenly very hot!"); X mdamageu(mon, tmp); X } X break; X default: X break; X } X } X return(malive | mhit); X} END_OF_FILE if test 33761 -ne `wc -c <'src/uhitm.c'`; then echo shar: \"'src/uhitm.c'\" unpacked with wrong size! fi # end of 'src/uhitm.c' fi echo shar: End of archive 10 \(of 38\). cp /dev/null ark10isdone 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