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