billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 58
Archive-name: NetHack3/Part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 38)."
# Contents: amiga/ami.lnk src/dbridge.c src/mhitu.c
# Wrapped by billr@saab on Sun Jul 23 21:32:47 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'amiga/ami.lnk' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'amiga/ami.lnk'\"
else
echo shar: Extracting \"'amiga/ami.lnk'\" \(761 characters\)
sed "s/^X//" >'amiga/ami.lnk' <<'END_OF_FILE'
X-w
X-o Ram:NetHack
X+ss
Xamidos.o amitcap.o amitty.o amiunix.o amiwind.o alloc.o apply.o artifact.o
Xattrib.o bones.o cmd.o dbridge.o decl.o demon.o do.o do_name.o do_wear.o
Xdog.o dogmove.o dothrow.o eat.o end.o engrave.o exper.o extralev.o
Xfountain.o hack.o invent.o lock.o main.o makemon.o mcastu.o mhitm.o mhitu.o
Xmklev.o mkmaze.o mkobj.o mkshop.o mon.o mondata.o monmove.o monst.o
Xmthrowu.o music.o o_init.o objects.o objnam.o options.o pager.o pickup.o
Xpolyself.o potion.o pray.o pri.o prisym.o random.o read.o restore.o rip.o
Xrnd.o rumors.o save.o search.o shk.o shknam.o sit.o sounds.o sp_lev.o
Xspell.o steal.o timeout.o topl.o topten.o track.o trap.o u_init.o uhitm.o
Xvault.o version.o weapon.o were.o wield.o wizard.o worm.o worn.o write.o
Xzap.o
X-lml -lcl
END_OF_FILE
if test 761 -ne `wc -c <'amiga/ami.lnk'`; then
echo shar: \"'amiga/ami.lnk'\" unpacked with wrong size!
fi
# end of 'amiga/ami.lnk'
fi
if test -f 'src/dbridge.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/dbridge.c'\"
else
echo shar: Extracting \"'src/dbridge.c'\" \(7852 characters\)
sed "s/^X//" >'src/dbridge.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)dbridge.c 3.0 88/18/12
X/* Copyright (c) 1989 by Jean-Christophe Collet */
X/* NetHack may be freely redistributed. See license for details. */
X
X/*
X * This file contains the drawbridge manipulation (create, open, close,
X * destroy).
X */
X
X#include "hack.h"
X
Xboolean
Xis_pool(x,y)
Xint x,y;
X{
X if(levl[x][y].typ == POOL || levl[x][y].typ == MOAT) return TRUE;
X#ifdef STRONGHOLD
X if(levl[x][y].typ == DRAWBRIDGE_UP &&
X (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
X#endif
X return FALSE;
X}
X
X#ifdef STRONGHOLD
Xvoid
Xinitsym(x,y)
Xint x,y;
X{
X char oldseen;
X struct rm *crm = &levl[x][y];
X
X oldseen = crm->seen;
X crm->seen = 1;
X crm->scrsym = news0(x,y);
X crm->seen = oldseen;
X}
X
Xstatic void
Xredosym(x,y)
Xint x,y;
X{
X if(cansee(x,y)) {
X if (Invisible || x != u.ux || y != u.uy)
X newsym(x,y);
X } else {
X initsym(x,y);
X levl[x][y].seen = 0;
X }
X}
X
X/*
X * We want to know whether a wall (or a door) is the portcullis (passageway)
X * of an eventual drawbridge.
X *
X * Return value: the direction of the drawbridge.
X */
X
Xint
Xis_drawbridge_wall(x,y)
Xint x,y;
X{
X struct rm *lev;
X
X lev = &levl[x][y];
X if ( lev->typ == VWALL || lev->typ == DOOR) {
X if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
X (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
X return (DB_WEST);
X if (IS_DRAWBRIDGE(levl[x-1][y].typ) &&
X (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
X return (DB_EAST);
X }
X if ( lev->typ == HWALL || lev->typ == DOOR) {
X if (IS_DRAWBRIDGE(levl[x][y-1].typ) &&
X (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
X return (DB_SOUTH);
X if (IS_DRAWBRIDGE(levl[x][y+1].typ) &&
X (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
X return (DB_NORTH);
X }
X return (-1);
X}
X
X/*
X* Use is_db_wall where you want to verify that a
X* drawbridge "wall" is UP in the location x, y
X* (instead of UP or DOWN, as with is_drawbridge_wall).
X*/
Xboolean
Xis_db_wall(x,y)
Xint x,y;
X{
X return( (levl[x][y].typ == VWALL || levl[x][y].typ == HWALL) &&
X levl[x][y].diggable & W_GATEWAY);
X}
X
X/*
X * Return true with x,y pointing to the drawbridge if x,y initially indicate
X * a drawbridge or drawbridge wall.
X */
Xboolean
Xfind_drawbridge(x,y)
Xint *x,*y;
X{
X int dir;
X
X if (IS_DRAWBRIDGE(levl[*x][*y].typ))
X return TRUE;
X dir = is_drawbridge_wall(*x,*y);
X if (dir >= 0) {
X switch(dir) {
X case DB_NORTH: (*y)++; break;
X case DB_SOUTH: (*y)--; break;
X case DB_EAST: (*x)--; break;
X case DB_WEST: (*x)++; break;
X }
X return TRUE;
X }
X return FALSE;
X}
X
X/*
X * Find the drawbridge wall associated with a drawbridge.
X */
Xstatic void
Xget_wall_for_db(x,y)
Xint *x,*y;
X{
X switch (levl[*x][*y].drawbridgemask & DB_DIR) {
X case DB_NORTH: (*y)--; break;
X case DB_SOUTH: (*y)++; break;
X case DB_EAST: (*x)++; break;
X case DB_WEST: (*x)--; break;
X }
X}
X
X/*
X * Creation of a drawbridge at pos x,y.
X * dir is the direction.
X * flag must be put to TRUE if we want the drawbridge to be opened.
X */
X
Xboolean
Xcreate_drawbridge(x,y,dir,flag)
Xint x,y,dir;
Xboolean flag;
X{
X int x2,y2;
X uchar wall;
X
X x2 = x; y2 = y;
X switch(dir) {
X case DB_NORTH:
X wall = HWALL;
X y2--;
X break;
X case DB_SOUTH:
X wall = HWALL;
X y2++;
X break;
X case DB_EAST:
X wall = VWALL;
X x2++;
X break;
X case DB_WEST:
X wall = VWALL;
X x2--;
X break;
X }
X if (!IS_WALL(levl[x2][y2].typ))
X return(FALSE);
X if (flag) { /* We want the bridge open */
X levl[x][y].typ = DRAWBRIDGE_DOWN;
X levl[x2][y2].typ = DOOR;
X levl[x2][y2].doormask = D_NODOOR;
X } else {
X levl[x][y].typ = DRAWBRIDGE_UP;
X levl[x2][y2].typ = wall;
X /* Beware, drawbridges are non-diggable. */
X levl[x2][y2].diggable = (W_NONDIGGABLE | W_GATEWAY);
X }
X levl[x][y].drawbridgemask = dir; /* always have DB_MOAT */
X initsym(x,y);
X initsym(x2,y2);
X return(TRUE);
X}
X
X/*
X * Close the drawbridge located at x,y
X */
X
Xvoid
Xclose_drawbridge(x,y)
Xint x,y;
X{
X register struct rm *lev1, *lev2;
X struct monst *mtmp;
X struct obj *otmp, *otmp2;
X int x2, y2;
X
X lev1 = &levl[x][y];
X if (lev1->typ != DRAWBRIDGE_DOWN) return;
X if (cansee(x,y))
X You("see a drawbridge going up!");
X lev1->typ = DRAWBRIDGE_UP;
X x2 = x; y2 = y;
X get_wall_for_db(&x2,&y2);
X lev2 = &levl[x2][y2];
X switch (lev1->drawbridgemask & DB_DIR) {
X case DB_NORTH:
X case DB_SOUTH:
X lev2->typ = HWALL;
X break;
X case DB_WEST:
X case DB_EAST:
X lev2->typ = VWALL;
X break;
X }
X lev2->diggable = (W_NONDIGGABLE | W_GATEWAY);
X if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT) {
X if (lev1->mmask && !is_flyer((mtmp = m_at(x,y))->data)) {
X if (is_swimmer(mtmp->data)) {
X if (flags.soundok) You("hear a splash.");
X } else {
X if (cansee(x,y))
X pline("%s drowns.",Monnam(mtmp));
X else if (flags.soundok)
X You("hear a splash!");
X xkilled(mtmp,2);
X }
X }
X if (u.ux == x && u.uy == y &&
X !(Levitation
X# ifdef POLYSELF
X || is_flyer(uasmon)
X# endif
X )) {
X /* is the player *THAT* stupid ? */
X You("fall from the drawbridge.");
X if (!Wwalking) drown();
X }
X }
X if (lev2->mmask && !noncorporeal((mtmp = m_at(x2, y2))->data)) {
X if (cansee(x2,y2))
X pline("%s is crushed by the portcullis.",Monnam(mtmp));
X else if (flags.soundok)
X You("hear a crushing sound.");
X xkilled(mtmp,2);
X }
X if (u.ux == x2 && u.uy == y2) { /* More stupidity ? */
X coord xy;
X
X You("are crushed by a falling portcullis.");
X killer = "closing drawbridge";
X done("died");
X /* So, you didn't die */
X pline("A %s force teleports you away...",
X Hallucination ? "normal" : "strange");
X enexto(&xy, x2, y2);
X teleds(xy.x, xy.y);
X }
X redosym(x,y);
X for (otmp=fobj;otmp;otmp = otmp2) {
X otmp2 = otmp->nobj;
X if ((otmp->ox == x && otmp->oy == y) ||
X (otmp->ox == x2 && otmp->oy == y2))
X delobj(otmp);
X }
X redosym(x2,y2);
X}
X
X/*
X * Open the drawbridge located at x,y
X */
X
Xvoid
Xopen_drawbridge(x,y)
Xint x,y;
X{
X register struct rm *lev1, *lev2;
X int x2, y2;
X
X lev1 = &levl[x][y];
X if (lev1->typ != DRAWBRIDGE_UP) return;
X if (cansee(x,y))
X You("see a drawbridge coming down!");
X lev1->typ = DRAWBRIDGE_DOWN;
X x2 = x; y2 = y;
X get_wall_for_db(&x2,&y2);
X lev2 = &levl[x2][y2];
X lev2->typ = DOOR;
X lev2->doormask = D_NODOOR;
X if (u.ux == x && u.uy == y) {
X if (cansee(x2,y2))
X newsym(x2,y2);
X You("are hit by the descending drawbridge!");
X killer = "descending drawbridge";
X done("died");
X }
X redosym(x,y);
X redosym(x2,y2);
X}
X
X/*
X * Let's destroy the drawbridge located at x,y
X */
X
Xvoid
Xdestroy_drawbridge(x,y)
Xint x,y;
X{
X register struct rm *lev1, *lev2;
X int x2, y2;
X
X lev1 = &levl[x][y];
X if (!IS_DRAWBRIDGE(lev1->typ))
X return;
X x2 = x; y2 = y;
X get_wall_for_db(&x2,&y2);
X lev2 = &levl[x2][y2];
X if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT) {
X if (lev1->typ == DRAWBRIDGE_UP) {
X if (cansee(x2,y2))
X pline("The portcullis of the drawbridge falls into the moat!");
X else if (flags.soundok)
X You("hear a big *SPLASH*!");
X } else {
X if (cansee(x,y))
X pline("The drawbridge collapses into the moat!");
X else if (flags.soundok)
X You("hear a big *SPLASH*!");
X }
X lev1->typ = MOAT;
X if (u.ux == x && u.uy == y && !(Levitation
X# ifdef POLYSELF
X || is_flyer(uasmon)
X# endif
X )) {
X /* is the player *THAT* stupid ? */
X You("fall from the drawbridge.");
X if (!Wwalking) drown();
X }
X } else {
X if (cansee(x,y))
X pline("The drawbridge disintegrates!");
X else
X You("hear a big *CRASH*!");
X lev1->typ = ROOM;
X }
X lev2->typ = DOOR;
X lev2->doormask = D_NODOOR;
X if (u.ux == x2 && u.uy == y2) { /* More stupidity ? */
X coord xy;
X
X You("are crushed by a falling portcullis.");
X killer = "collapsing drawbridge";
X done("died");
X /* So, you didn't die */
X pline("A %s force teleports you away...",
X Hallucination ? "normal" : "strange");
X enexto(&xy, x2, y2);
X teleds(xy.x, xy.y);
X }
X redosym(x,y);
X redosym(x2,y2);
X}
X
X#endif /* STRONGHOLD /**/
END_OF_FILE
if test 7852 -ne `wc -c <'src/dbridge.c'`; then
echo shar: \"'src/dbridge.c'\" unpacked with wrong size!
fi
# end of 'src/dbridge.c'
fi
if test -f 'src/mhitu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/mhitu.c'\"
else
echo shar: Extracting \"'src/mhitu.c'\" \(42552 characters\)
sed "s/^X//" >'src/mhitu.c' <<'END_OF_FILE'
X/* SCCS Id: \@(#)mhitu.c 3.0 88/10/28
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 struct obj *otmp;
X#ifdef POLYSELF
Xstatic void urustm P((struct monst *, struct obj *));
Xstatic int passiveum P((struct permonst *, struct monst *));
X#endif
X#ifdef SEDUCE
Xstatic void mayberem P((struct obj *, char *));
X#endif
Xstatic int hitmu P((struct monst *,struct attack *));
Xstatic int gulpmu P((struct monst *,struct attack *));
Xstatic int explmu P((struct monst *,struct attack *));
Xstatic int gazemu P((struct monst *,struct attack *));
X
X#ifdef POLYSELF
Xboolean
X/* also needed in uhitm.c */
X#else
Xstatic boolean
X#endif
Xincompatible(mon)
Xregister struct monst *mon;
X{
X return(poly_gender() != 1-gender(mon));
X}
X
Xboolean
Xis_nymph(mon)
Xregister struct monst *mon;
X{
X return( mon->data->mlet == S_NYMPH );
X}
X
Xboolean
Xsp_melee(mon)
Xregister struct monst *mon;
X{
X return(
X#ifdef SEDUCE
X (mon->data == &mons[PM_SUCCUBUS] && !mon->minvis) ||
X (mon->data == &mons[PM_INCUBUS] && !mon->minvis) ||
X#endif
X is_nymph(mon));
X}
X
Xstatic void
Xhitmsg(mtmp, attyp)
Xregister struct monst *mtmp;
Xregister uchar attyp;
X{
X /* Note: if opposite gender, "seductively" */
X /* If same gender, "engagingly" for nymph, normal msg for others */
X if(sp_melee(mtmp) && !mtmp->mcan) {
X if(!is_nymph(mtmp) && incompatible(mtmp)) goto strike;
X kludge("%s %s you %s.", Monnam(mtmp),
X Blind ? "talks to" : "smiles at",
X incompatible(mtmp) ? "engagingly" : "seductively");
X } else
Xstrike:
X switch (attyp) {
X case AT_BITE:
X kludge("%s bites!", Monnam(mtmp));
X break;
X case AT_KICK:
X#ifdef POLYSELF
X kludge("%s kicks%c", Monnam(mtmp), thick_skinned(uasmon) ? '.' : '!');
X#else
X kludge("%s kicks!", Monnam(mtmp));
X#endif
X break;
X case AT_STNG:
X kludge("%s stings!", Monnam(mtmp));
X break;
X case AT_BUTT:
X kludge("%s butts!", Monnam(mtmp));
X break;
X case AT_TUCH:
X kludge("%s touches you!", Monnam(mtmp));
X break;
X default:
X kludge("%s hits!", Monnam(mtmp));
X }
X}
X
Xstatic void
Xmissmu(mtmp, nearmiss) /* monster missed you */
Xregister struct monst *mtmp;
Xregister boolean nearmiss;
X{
X if(sp_melee(mtmp) && !mtmp->mcan) {
X if(!is_nymph(mtmp) && incompatible(mtmp)) goto strike;
X kludge("%s pretends to be friendly.", Monnam(mtmp));
X } else {
Xstrike:
X if (!flags.verbose || !nearmiss)
X kludge("%s misses.", Monnam(mtmp));
X else
X kludge("%s just misses!", Monnam(mtmp));
X }
X}
X
Xstatic void
Xmswings(mtmp, otemp) /* monster swings obj */
Xregister struct monst *mtmp;
Xregister struct obj *otemp;
X{
X if (!flags.verbose || Blind || otemp->olet != WEAPON_SYM) return;
X pline("%s %s %s %s.", Monnam(mtmp),
X (otemp->otyp == SPEAR ||
X otemp->otyp == LANCE ||
X otemp->otyp == GLAIVE ||
X otemp->otyp == TRIDENT) ? "thrusts" : "swings",
X is_female(mtmp) ? "her" :
X is_human(mtmp->data) ? "his" : "its",
X xname(otemp));
X}
X
Xstatic void
Xwildmiss(mtmp) /* monster attacked your displaced image */
X register struct monst *mtmp;
X{
X if (!flags.verbose) return;
X if (!cansee(mtmp->mx, mtmp->my)) return;
X /* maybe it's attacking an image around the corner? */
X if(Invis && !perceives(mtmp->data)) {
X if(sp_melee(mtmp) && !mtmp->mcan) {
X if(!is_nymph(mtmp) && incompatible(mtmp)) goto strike;
X kludge("%s tries to touch you and misses!", Monnam(mtmp));
X } else
Xstrike:
X switch(rn2(3)) {
X case 0: kludge("%s swings wildly and misses!", Monnam(mtmp));
X break;
X case 1: kludge("%s attacks a spot beside you.", Monnam(mtmp));
X break;
X case 2: kludge("%s strikes at thin air!", Monnam(mtmp));
X break;
X default:kludge("%s swings wildly!", Monnam(mtmp));
X break;
X }
X }
X else if(Displaced) {
X if(sp_melee(mtmp) && !mtmp->mcan) {
X if(!is_nymph(mtmp) && incompatible(mtmp)) goto strikem;
X kludge("%s smiles %s at your %sdisplaced image...",
X Monnam(mtmp),
X incompatible(mtmp) ? "engagingly" : "seductively",
X Invis ? "invisible " : "");
X } else
Xstrikem:
X kludge("%s strikes at your %sdisplaced image and misses you!",
X /* Note: if you're both invisible and displaced,
X * only monsters which see invisible will attack your
X * displaced image, since the displaced image is also
X * invisible.
X */
X Monnam(mtmp),
X Invis ? "invisible " : "");
X }
X else impossible("%s attacks you without knowing your location?",
X Monnam(mtmp));
X}
X
Xstatic void
Xregurgitates(mtmp)
Xregister struct monst *mtmp;
X{
X u.ux = mtmp->mx;
X u.uy = mtmp->my;
X u.uswallow = 0;
X u.ustuck = 0;
X mnexto(mtmp);
X setsee();
X docrt();
X spoteffects();
X /* to cover for a case where mtmp is not in a next square */
X if(um_dist(mtmp->mx,mtmp->my,1))
X pline("Brrooaa... You land hard at some distance.");
X}
X
X/*
X * mattacku: monster attacks you
X * returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
X * Note: if you're displaced or invisible the monster might attack the
X * wrong position...
X * Assumption: it's attacking you or an empty square; if there's another
X * monster which it attacks by mistake, the caller had better
X * take care of it...
X */
Xint
Xmattacku(mtmp)
X register struct monst *mtmp;
X{
X struct attack *mattk;
X int i, j, tmp, sum[NATTK];
X struct permonst *mdat = mtmp->data;
X boolean ranged = (dist(mtmp->mx, mtmp->my) > 3);
X /* Is it near you? Affects your actions */
X boolean range2 = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > 3);
X /* Does it think it's near you? Affects its actions */
X boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
X /* Is it attacking you or your image? */
X boolean youseeit = (cansee(mtmp->mx, mtmp->my));
X /* Necessary since if it's attacking your image around a
X * corner, you might not see it
X */
X
X if(!ranged) nomul(0);
X if(mtmp->mhp <= 0) return(0);
X
X /* If swallowed, can only be affected by u.ustuck */
X if(u.uswallow) {
X if(mtmp != u.ustuck)
X return(0);
X u.ustuck->mux = u.ux;
X u.ustuck->muy = u.uy;
X range2 = 0;
X foundyou = 1;
X /* This is not impossible! */
X /* If the swallowing monster changes into a monster
X * that is not capable of swallowing you, you get
X * regurgitated - dgk
X */
X for(i = 0; i < NATTK; i++)
X if(mdat->mattk[i].aatyp == AT_ENGL) goto doattack;
X
X You("get regurgitated!");
X regurgitates(mtmp);
X return(0);
X }
Xdoattack:
X#ifdef POLYSELF
X if (u.uundetected && !range2 && foundyou) {
X u.uundetected = 0;
X if (u.usym == S_PIERCER) {
X coord cc; /* maybe we need a unexto() function? */
X
X unpmon(mtmp);
X levl[mtmp->mx][mtmp->my].mmask = 0;
X mtmp->mx = u.ux; mtmp->my = u.uy;
X levl[mtmp->mx][mtmp->my].mmask = 1;
X pmon(mtmp);
X enexto(&cc, u.ux, u.uy);
X /* Luckily piercers cannot walk through walls, so this
X * will work. If they can (i.e., if someone adds a potion
X * of phasing), we gotta change this...
X */
X teleds(cc.x, cc.y);
X You("fall from the ceiling!");
X if (is_mercenary(mtmp->data) && m_carrying(mtmp,HELMET)) {
X kludge("Your blow glances off %s's helmet.",
X mon_nam(mtmp));
X } else {
X if (3 + mtmp->data->ac <= rnd(20)) {
X kludge("%s is hit by a falling piercer (you)!",
X Monnam(mtmp));
X if ((mtmp->mhp -= d(3,6)) < 1)
X killed(mtmp);
X } else
X kludge("%s is almost hit by a falling piercer (you)!",
X Monnam(mtmp));
X }
X } else {
X if (Blind) pline("It tries to move where you are hiding.");
X else
X pline("Wait, %s! There's a %s named %s hiding under %s!",
X mtmp->mnamelth ? NAME(mtmp) : mtmp->data->mname,
X uasmon->mname, plname,
X levl[u.ux][u.uy].omask ? doname(o_at(u.ux,u.uy)) :
X "some gold");
X prme();
X }
X return(0);
X }
X if (u.usym == S_MIMIC_DEF && !range2 && foundyou) {
X if (Blind) pline("It gets stuck on you.");
X else pline("Wait, %s! That's a %s named %s!",
X mtmp->mnamelth ? NAME(mtmp) : mtmp->data->mname,
X uasmon->mname, plname);
X u.ustuck = mtmp;
X u.usym = S_MIMIC;
X prme();
X return(0);
X }
X#endif
X/* Work out the armor class differential */
X tmp = u.uac + 10; /* tmp ~= 0 - 20 */
X/* give people with Ac < -9 at least some vulnerability */
X/* negative AC gives an actual AC of somewhere from -1 to the AC */
X if (tmp < 10) tmp = 10 - rnd(10-tmp);
X tmp += mtmp->m_lev;
X if(multi < 0) tmp += 4;
X if((Invis && !perceives(mdat)) || !mtmp->mcansee)
X tmp -= 2;
X if(mtmp->mtrapped) tmp -= 2;
X if(tmp <= 0) tmp = 1;
X
X /* make eels visible the moment they hit/miss us */
X if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
X mtmp->minvis = 0;
X pmon(mtmp);
X }
X
X/* Special demon handling code */
X if(!mtmp->cham && is_demon(mdat) && !range2
X#ifdef HARD
X && mtmp->data != &mons[PM_BALROG]
X && mtmp->data != &mons[PM_SUCCUBUS]
X && mtmp->data != &mons[PM_INCUBUS]
X#endif
X )
X if(!mtmp->mcan && !rn2(13)) dsummon(mdat);
X
X/* Special lycanthrope handling code */
X if(!mtmp->cham && is_were(mdat) && !range2) {
X
X if(is_human(mdat)) {
X if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
X } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
X
X if(!rn2(10) && !mtmp->mcan) {
X if(!Blind) {
X pline("%s summons help!",youseeit ?
X Monnam(mtmp) : "It");
X } else
X You("feel hemmed in.");
X /* Technically wrong; we really should check if you can see the
X * help, but close enough...
X */
X if (!were_summon(mdat,FALSE) && !Blind)
X pline("But none comes.");
X }
X }
X
X for(i = 0; i < NATTK; i++) {
X
X mattk = &(mdat->mattk[i]);
X switch(mattk->aatyp) {
X case AT_CLAW: /* "hand to hand" attacks */
X case AT_KICK:
X case AT_BITE:
X case AT_STNG:
X case AT_TUCH:
X case AT_BUTT:
X if(!range2) {
X if (!foundyou) {
X wildmiss(mtmp);
X sum[i] = 0;
X } else if(tmp > (j = rnd(20+i)))
X#ifdef POLYSELF
X if (mattk->aatyp == AT_KICK &&
X thick_skinned(uasmon)) sum[i] = 0;
X else
X#endif
X sum[i] = hitmu(mtmp, mattk);
X else {
X missmu(mtmp, (tmp == j));
X sum[i] = 0;
X }
X } else sum[i] = 0;
X break;
X
X case AT_HUGS: /* automatic if prev two attacks succeed */
X /* Note: if displaced, prev attacks never succeeded */
X if(!range2) {
X if(sum[i-1] && sum[i-2])
X sum[i]= hitmu(mtmp, mattk);
X else sum[i] = 0;
X } else sum[i] = 0;
X break;
X
X case AT_GAZE: /* can affect you either ranged or not */
X if (!youseeit) sum[i] = 0;
X /* Displaced and around a corner so not visible */
X else sum[i] = gazemu(mtmp, mattk);
X break;
X
X case AT_EXPL: /* automatic hit if next to, and aimed at you */
X if(!range2) {
X if (!foundyou) {
X if (!mtmp->mcan) {
X pline("%s explodes at a spot in thin air!",
X youseeit ? Monnam(mtmp) : "It");
X mondead(mtmp);
X sum[i] = 2;
X } else sum[i] = 0;
X } else sum[i] = explmu(mtmp, mattk);
X } else sum[i] = 0;
X break;
X
X case AT_ENGL:
X if (!range2) {
X if(foundyou) {
X if(u.uswallow || tmp > (j = rnd(20+i))) {
X /* Force swallowing monster to be
X * displayed even when player is
X * moving away */
X nscr();
X sum[i] = gulpmu(mtmp, mattk);
X } else {
X missmu(mtmp, (tmp == j));
X sum[i] = 0;
X }
X } else pline("%s gulps some air!", youseeit ?
X Monnam(mtmp) : "It");
X } else sum[i] = 0;
X break;
X case AT_BREA:
X if(range2) sum[i] = breamu(mtmp, mattk);
X /* Note: breamu takes care of displacement */
X else sum[i] = 0;
X break;
X case AT_SPIT:
X if(range2) sum[i] = spitmu(mtmp);
X /* Note: spitmu takes care of displacement */
X else sum[i] = 0;
X break;
X case AT_WEAP:
X if(range2) {
X#ifdef REINCARNATION
X if (dlevel != rogue_level)
X#endif
X sum[i] = thrwmu(mtmp);
X } else {
X if (!foundyou) {
X wildmiss(mtmp);
X sum[i] = 0;
X } else {
X set_uasmon();
X otmp = select_hwep(mtmp);
X if(otmp) {
X tmp += hitval(otmp, uasmon);
X mswings(mtmp, otmp);
X }
X if(tmp > (j = rnd(20+i)))
X sum[i] = hitmu(mtmp, mattk);
X else {
X missmu(mtmp, (tmp == j));
X sum[i] = 0;
X }
X }
X }
X break;
X case AT_MAGC:
X if(!range2) {
X if (!foundyou) {
X pline("%s casts a spell at thin air!",
X youseeit ? Monnam(mtmp) : "It");
X sum[i] = 0;
X /* Not totally right since castmu allows other
X * spells, such as the monster healing itself,
X * that should work even when not next to you--
X * but the previous code was just as wrong.
X * --KAA
X */
X } else sum[i] = castmu(mtmp, mattk);
X } else sum[i] = buzzmu(mtmp, mattk);
X break;
X
X default: /* no attack */
X sum[i] = 0;
X break;
X }
X if(flags.botl) bot();
X if(sum[i] == 2) return(1); /* attacker dead */
X }
X return(0);
X}
X
X/*
X * hitmu: monster hits you
X * returns 2 if monster dies (e.g. "yellow light"), 0 otherwise
X */
Xstatic
Xint
Xhitmu(mtmp, mattk)
X register struct monst *mtmp;
X register struct attack *mattk;
X{
X register struct permonst *mdat = mtmp->data;
X register int dmg, ctmp, ptmp;
X register boolean getbronze;
X char buf[BUFSZ];
X#ifdef POLYSELF
X struct permonst *olduasmon = uasmon;
X int res;
X#endif
X
X/* If the monster is undetected & hits you. You should know where
X * the attack came from.
X */
X if(mtmp->mhide && mtmp->mundetected) {
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("%s was hidden under %s!",
X Xmonnam(mtmp), doname(obj));
X } else if (levl[mtmp->mx][mtmp->my].gmask == 1)
X pline("%s was hidden under some gold!",
X Xmonnam(mtmp));
X }
X }
X
X/* First determine the base damage done */
X dmg = d((int)mattk->damn, (int)mattk->damd);
X if(is_undead(mdat) && midnight())
X dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
X
X/* Next a cancellation factor */
X/* Use ctmp when the cancellation factor takes into account certain
X * armor's special magic protection. Otherwise just use !mtmp->mcan.
X */
X ctmp = !mtmp->mcan &&
X (!uarm || (rn2(3) >= objects[uarm->otyp].a_can) || !rn2(50))
X && (!uarmc || (rn2(3) >= objects[uarmc->otyp].a_can) || !rn2(50));
X
X/* Now, adjust damages via resistances or specific attacks */
X switch(mattk->adtyp) {
X case AD_PHYS:
X if(mattk->aatyp == AT_HUGS
X#ifdef POLYSELF
X && !sticks(uasmon)
X#endif
X ) {
X if(!u.ustuck && rn2(2)) {
X u.ustuck = mtmp;
X kludge("%s grabs you!", Monnam(mtmp));
X } else if(u.ustuck == mtmp)
X You("are being %s.",
X#ifdef GOLEMS
X (mtmp->data == &mons[PM_ROPE_GOLEM])
X ? "choked" :
X#endif /* GOLEMS */
X "crushed");
X
X } else { /* hand to hand weapon */
X hitmsg(mtmp,mattk->aatyp);
X if(mattk->aatyp == AT_WEAP && otmp) {
X dmg += dmgval(otmp, uasmon);
X if (dmg <= 0) dmg = 1;
X#ifdef NAMED_ITEMS
X if (spec_ability(otmp, SPFX_DRLI)
X# ifdef POLYSELF
X && !resists_drli(uasmon)
X# endif
X ) {
X pline("The %s blade drains your life!",
X Hallucination ? hcolor() : black);
X losexp();
X }
X#endif
X#ifdef POLYSELF
X if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
X (u.umonnum==PM_BLACK_PUDDING
X || u.umonnum==PM_BROWN_PUDDING)) {
X /* This redundancy necessary because you have to
X * take the damage _before_ being cloned.
X */
X if (u.uac < 0) dmg += u.uac;
X if (dmg < 1) dmg = 1;
X u.mh -= dmg;
X flags.botl = 1;
X dmg = 0;
X if(cloneu())
X kludge("You divide as %s hits you!",mon_nam(mtmp));
X }
X urustm(mtmp, otmp);
X#endif
X }
X }
X break;
X case AD_DISE:
X hitmsg(mtmp, mattk->aatyp);
X You("feel very sick.");
X make_sick((long)rn1(25-ACURR(A_CON),15),FALSE);
X u.usick_cause = mdat->mname;
X break;
X case AD_FIRE:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp && rn2(2)) {
X pline("You're on fire!");
X if (Fire_resistance) {
X pline("The fire doesn't feel hot!");
X dmg = 0;
X }
X if(mtmp->m_lev > rn2(20))
X destroy_item(SCROLL_SYM, AD_FIRE);
X if(mtmp->m_lev > rn2(20))
X destroy_item(POTION_SYM, AD_FIRE);
X#ifdef SPELLS
X if(mtmp->m_lev > rn2(25))
X destroy_item(SPBOOK_SYM, AD_FIRE);
X#endif
X }
X break;
X case AD_COLD:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp && rn2(2)) {
X pline("You're covered in frost!");
X if (Cold_resistance) {
X pline("The frost doesn't seem cold!");
X dmg = 0;
X }
X if(mtmp->m_lev > rn2(20))
X destroy_item(POTION_SYM, AD_COLD);
X }
X break;
X case AD_ELEC:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp && rn2(2)) {
X You("get zapped!");
X if (Shock_resistance) {
X pline("The zap doesn't shock you!");
X dmg = 0;
X }
X if(mtmp->m_lev > rn2(20))
X destroy_item(WAND_SYM, AD_ELEC);
X if(mtmp->m_lev > rn2(20))
X destroy_item(RING_SYM, AD_ELEC);
X }
X break;
X case AD_SLEE:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp && multi >= 0 && !rn2(5)) {
X if (Sleep_resistance) break;
X nomul(-rnd(10));
X if (Blind) You("are put to sleep!");
X else You("are put to sleep by %s!",mon_nam(mtmp));
X }
X break;
X case AD_DRST:
X ptmp = A_STR;
X goto dopois;
X case AD_DRDX:
X ptmp = A_DEX;
X goto dopois;
X case AD_DRCO:
X ptmp = A_CON;
Xdopois:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp && !rn2(8)) {
X Sprintf(buf, "%s's %s",
X Hallucination ? rndmonnam() : mdat->mname,
X (mattk->aatyp == AT_BITE) ? "bite" : "sting");
X poisoned(buf, ptmp, mdat->mname);
X }
X break;
X case AD_PLYS:
X hitmsg(mtmp, mattk->aatyp);
X if(ctmp && multi >= 0 && !rn2(3)) {
X if (Blind) You("are frozen!");
X else You("are frozen by %s!", mon_nam(mtmp));
X nomul(-rnd(10));
X }
X break;
X case AD_DRLI:
X hitmsg(mtmp, mattk->aatyp);
X if (ctmp && !rn2(3)
X#ifdef POLYSELF
X && !resists_drli(uasmon)
X#endif
X#ifdef NAMED_ITEMS
X && !defends(AD_DRLI, uwep)
X#endif
X ) losexp();
X break;
X case AD_LEGS:
X { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
X if (mtmp->mcan) {
X pline("%s nuzzles against your %s %s!", Monnam(mtmp),
X (side == RIGHT_SIDE) ? "right" : "left",
X body_part(LEG));
X } else {
X if (uarmf) {
X pline("%s scratches your %s boot!", Monnam(mtmp),
X (side == RIGHT_SIDE) ? "right" : "left");
X break;
X }
X pline("%s pricks your %s %s!", Monnam(mtmp),
X (side == RIGHT_SIDE) ? "right" : "left",
X body_part(LEG));
X set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
X }
X break;
X }
X case AD_STON: /* at present only a cockatrice */
X hitmsg(mtmp,mattk->aatyp);
X if(!rn2(3) && !Stoned) {
X if (mtmp->mcan) {
X if (flags.soundok)
X You("hear a cough from %s!", mon_nam(mtmp));
X } else {
X if (flags.soundok)
X You("hear %s's hissing!", mon_nam(mtmp));
X if((!rn2(10) ||
X (flags.moonphase == NEW_MOON &&
X !carrying(DEAD_LIZARD)))
X#ifdef POLYSELF
X && !resists_ston(uasmon)
X#endif
X ) {
X Stoned = 5;
X return(1);
X /* You("turn to stone..."); */
X /* done_in_by(mtmp); */
X }
X }
X }
X break;
X case AD_STCK:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp && !u.ustuck
X#ifdef POLYSELF
X && !sticks(uasmon)
X#endif
X ) u.ustuck = mtmp;
X break;
X case AD_WRAP:
X if(ctmp
X#ifdef POLYSELF
X && !sticks(uasmon)
X#endif
X ) {
X if(!u.ustuck && !rn2(10)) {
X pline("%s swings itself around you!",
X Monnam(mtmp));
X u.ustuck = mtmp;
X } else if(u.ustuck == mtmp) {
X if (is_pool(mtmp->mx,mtmp->my)
X#ifdef POLYSELF
X && !is_swimmer(uasmon)
X#endif
X ) {
X pline("%s drowns you...", Monnam(mtmp));
X done("drowned");
X } else if(mattk->aatyp == AT_HUGS)
X You("are being crushed.");
X } else dmg = 0;
X } else dmg = 0;
X break;
X case AD_WERE:
X hitmsg(mtmp,mattk->aatyp);
X#ifdef POLYSELF
X if (ctmp && !rn2(4) && u.ulycn == -1
X# ifdef NAMED_ITEMS
X && !defends(AD_WERE,uwep)
X# endif
X ) {
X You("feel feverish.");
X u.ulycn = monsndx(mdat);
X }
X#endif
X break;
X case AD_SGLD:
X hitmsg(mtmp,mattk->aatyp);
X#ifdef POLYSELF
X if (u.usym == mdat->mlet) break;
X#endif
X if(!mtmp->mcan) stealgold(mtmp);
X break;
X
X case AD_SITM: /* for now these are the same */
X case AD_SEDU:
X#ifdef POLYSELF
X if (dmgtype(uasmon, AD_SEDU)
X# ifdef SEDUCE
X || dmgtype(uasmon, AD_SSEX)
X# endif
X ) {
X if (mtmp->minvent)
X pline("%s brags about the goods some dungeon explorer provided.",
X Monnam(mtmp));
X else
X pline("%s makes some remarks about how difficult theft is lately.",
X Monnam(mtmp));
X rloc(mtmp);
X } else
X#endif
X if(mtmp->mcan) {
X if (!Blind) {
X pline("%s tries to %s you, but you seem %s.",
X Amonnam(mtmp, "plain"),
X flags.female ? "charm" : "seduce",
X flags.female ? "unaffected" : "uninterested");
X }
X if(rn2(3)) rloc(mtmp);
X } else if(steal(mtmp)) {
X rloc(mtmp);
X mtmp->mflee = 1;
X }
X break;
X#ifdef SEDUCE
X case AD_SSEX:
X if(!mtmp->mcan && !mtmp->minvis) doseduce(mtmp);
X break;
X#endif
X case AD_SAMU:
X hitmsg(mtmp,mattk->aatyp);
X /* when the Wiz hits, 1/20 steals the amulet */
X if (!carrying(AMULET_OF_YENDOR)) break;
X if (!rn2(20)) stealamulet(mtmp);
X break;
X
X case AD_TLPT:
X hitmsg(mtmp,mattk->aatyp);
X if(ctmp) {
X if(flags.verbose)
X Your("position suddenly seems very uncertain!");
X tele();
X }
X break;
X case AD_RUST:
X hitmsg(mtmp,mattk->aatyp);
X if (mtmp->mcan) break;
X#ifdef POLYSELF
X#ifdef GOLEMS
X if (u.umonnum == PM_IRON_GOLEM) {
X You("rust!");
X rehumanize();
X break;
X }
X#endif /* GOLEMS */
X#endif
X /* What the following code does: it keeps looping until it
X * finds a target for the rust monster.
X * Head, feet, etc... not covered by metal, or covered by
X * rusty metal, are not targets. However, your body always
X * is, no matter what covers it.
X */
X getbronze = (mdat == &mons[PM_BLACK_PUDDING] &&
X uarm->otyp == BRONZE_PLATE_MAIL);
X while (1) {
X switch(rn2(5)) {
X case 0:
X if (!rust_dmg(uarmh, "helmet", 1, FALSE)) continue;
X break;
X case 1:
X if (uarmc) break;
X /* Note the difference between break and continue;
X * break means it was hit and didn't rust; continue
X * means it wasn't a target and though it didn't rust
X * something else did.
X */
X if (getbronze)
X (void)rust_dmg(uarm, "bronze armor", 3, TRUE);
X else
X (void)rust_dmg(uarm, "armor", 1, TRUE);
X break;
X case 2:
X if (!rust_dmg(uarms, "shield", 1, FALSE)) continue;
X break;
X case 3:
X if (!rust_dmg(uarmg, "metal gauntlets", 1, FALSE))
X continue;
X break;
X case 4:
X if (!rust_dmg(uarmf, "metal boots", 1, FALSE)) continue;
X break;
X }
X break; /* Out of while loop */
X }
X break;
X case AD_DCAY:
X hitmsg(mtmp,mattk->aatyp);
X if (mtmp->mcan) break;
X#ifdef POLYSELF
X#ifdef GOLEMS
X if (u.umonnum == PM_WOOD_GOLEM ||
X u.umonnum == PM_LEATHER_GOLEM) {
X You("rot!");
X rehumanize();
X break;
X }
X#endif /* GOLEMS */
X#endif
X while (1) {
X switch(rn2(5)) {
X case 0:
X if (!rust_dmg(uarmh, "leather helmet", 2, FALSE))
X continue;
X break;
X case 1:
X if (uarmc) break;
X (void)rust_dmg(uarm, "leather armor", 2, TRUE);
X break;
X case 2:
X if (!rust_dmg(uarms, "wooden shield", 2, FALSE))
X continue;
X break;
X case 3:
X if (!rust_dmg(uarmg, "gloves", 2, FALSE)) continue;
X break;
X case 4:
X if (!rust_dmg(uarmf, "boots", 2, FALSE)) continue;
X break;
X }
X break; /* Out of while loop */
X }
X break;
X case AD_HEAL:
X if(!uwep
X#ifdef SHIRT
X && !uarmu
X#endif
X && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
X kludge("%s hits! (I hope you don't mind.)", Monnam(mtmp));
X#ifdef POLYSELF
X if (u.mtimedone) {
X u.mh += rnd(7);
X if(!rn2(7)) u.mhmax++;
X if(u.mh > u.mhmax) u.mh = u.mhmax;
X if(u.mh == u.mhmax && !rn2(50)) mongone(mtmp);
X } else {
X#endif
X u.uhp += rnd(7);
X if(!rn2(7)) u.uhpmax++;
X if(u.uhp > u.uhpmax) u.uhp = u.uhpmax;
X if(u.uhp == u.uhpmax && !rn2(50)) mongone(mtmp);
X#ifdef POLYSELF
X }
X#endif
X flags.botl = 1;
X if(!rn2(50)) rloc(mtmp);
X dmg = 0;
X } else
X if(pl_character[0] == 'H') {
X if (flags.soundok && !(moves % 5))
X pline("'Doc, I can't help you unless you cooperate.'");
X dmg = 0;
X } else hitmsg(mtmp,mattk->aatyp);
X break;
X case AD_CURS:
X hitmsg(mtmp,mattk->aatyp);
X if(!night() && mdat == &mons[PM_GREMLIN]) break;
X if(!mtmp->mcan && !rn2(10)) {
X if (flags.soundok)
X if (Blind) You("hear laughter.");
X else pline("%s chuckles.", Monnam(mtmp));
X#ifdef POLYSELF
X#ifdef GOLEMS
X if (u.umonnum == PM_CLAY_GOLEM) {
X pline("Some writing vanishes from your head!");
X rehumanize();
X break;
X }
X#endif /* GOLEMS */
X#endif
X attrcurse();
X }
X break;
X case AD_STUN:
X hitmsg(mtmp,mattk->aatyp);
X if(!mtmp->mcan && !rn2(4)) {
X make_stunned(HStun + dmg, TRUE);
X dmg /= 2;
X }
X break;
X case AD_ACID:
X hitmsg(mtmp,mattk->aatyp);
X if(!mtmp->mcan && !rn2(3))
X#ifdef POLYSELF
X if (resists_acid(uasmon)) {
X pline("You're covered in acid, but it seems harmless.");
X dmg = 0;
X } else
X#endif
X pline("You're covered in acid! It burns!");
X else dmg = 0;
X break;
X case AD_SLOW:
X hitmsg(mtmp,mattk->aatyp);
X if(!ctmp && (Fast & (INTRINSIC|TIMEOUT)) && !rn2(4)) {
X Fast &= ~(INTRINSIC|TIMEOUT);
X You("feel yourself slowing down.");
X }
X break;
X case AD_DREN:
X hitmsg(mtmp,mattk->aatyp);
X#ifdef SPELLS
X if(!ctmp && !rn2(4)) drain_en(dmg);
X#endif
X dmg = 0;
X break;
X case AD_CUSS:
X if(flags.soundok && !rn2(3)) cuss(mtmp);
X dmg = 0;
X break;
X#ifdef HARD /* a non-gaze AD_CONF exists only for one of the demons */
X case AD_CONF:
X hitmsg(mtmp,mattk->aatyp);
X if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
X mtmp->mspec_used += (dmg + rn2(6));
X if(Confusion)
X You("are getting even more confused.");
X else You("are getting confused.");
X make_confused(HConfusion + dmg, FALSE);
X }
X#endif
X /* fall through to next case */
X default: dmg = 0;
X break;
X }
X if(u.uhp < 1) done_in_by(mtmp);
X
X/* Negative armor class reduces damage done instead of fully protecting
X * against hits.
X */
X if (dmg && u.uac < 0) {
X dmg -= rnd(-u.uac);
X if (dmg < 1) dmg = 1;
X }
X
X if(dmg) mdamageu(mtmp, dmg);
X
X#ifdef POLYSELF
X res = passiveum(olduasmon, mtmp);
X stop_occupation();
X return res;
X#else
X stop_occupation();
X return 1;
X#endif
X}
X
Xstatic
Xint
Xgulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */
X register struct monst *mtmp;
X register struct attack *mattk;
X{
X int tmp = d((int)mattk->damn, (int)mattk->damd);
X int tim_tmp;
X#ifdef WALKIES
X int i;
X#endif
X
X if(!u.uswallow) { /* swallow him */
X levl[mtmp->mx][mtmp->my].mmask = 0;
X mtmp->mx = u.ux;
X mtmp->my = u.uy;
X levl[mtmp->mx][mtmp->my].mmask = 1;
X u.ustuck = mtmp;
X pmon(mtmp);
X kludge("%s engulfs you!", Monnam(mtmp));
X#ifdef WALKIES
X if((i = number_leashed()) > 0) {
X pline("The leash%s snap%s loose...",
X (i > 1) ? "es" : "",
X (i > 1) ? "" : "s");
X unleash_all();
X }
X#endif
X#ifdef POLYSELF
X if (u.umonnum==PM_COCKATRICE) {
X kludge("%s turns to stone!", Monnam(mtmp));
X stoned = 1;
X xkilled(mtmp, 0);
X return 2;
X }
X#endif
X more();
X seeoff(1);
X u.uswallow = 1;
X /*assume that u.uswldtim always set >=0*/
X u.uswldtim = (tim_tmp =
X (-u.uac + 10 + rnd(25 - (int)mtmp->m_lev)) >> 1) > 0 ?
X tim_tmp : 0;
X swallowed(1);
X } else {
X
X if(mtmp != u.ustuck) return(0);
X switch(mattk->adtyp) {
X
X case AD_DGST:
X if(!u.uswldtim) { /* a3 *//*no cf unsigned <=0*/
X kludge("%s totally digests you!", Monnam(mtmp));
X tmp = u.uhp;
X } else {
X kludge("%s digests you!", Monnam(mtmp));
X }
X break;
X case AD_PHYS:
X You("are pummeled with debris!");
X break;
X case AD_ACID:
X#ifdef POLYSELF
X if (resists_acid(uasmon)) {
X You("are covered with a seemingly harmless goo.");
X tmp = 0;
X } else
X#endif
X if (Hallucination) pline("Ouch! You've been slimed!");
X else You("are covered in slime! It burns!!!");
X break;
X case AD_BLND:
X if(!Blind) {
X You("can't see in here!");
X make_blinded((long)tmp,FALSE);
X } else make_blinded(Blinded+1,FALSE); /* keep him blind until disgorged */
X tmp = 0;
X break;
X case AD_ELEC:
X if(!mtmp->mcan && rn2(2)) {
X pline("The air around you crackles with electricity.");
X if (Shock_resistance) {
X shieldeff(u.ux, u.uy);
X You("seem unhurt.");
X#if defined(POLYSELF) && defined(GOLEMS)
X ugolemeffects(AD_ELEC,tmp);
X#endif
X tmp = 0;
X }
X } else tmp = 0;
X break;
X case AD_COLD:
X if(!mtmp->mcan && rn2(2)) {
X if (Cold_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel mildly chilly.");
X#if defined(POLYSELF) && defined(GOLEMS)
X ugolemeffects(AD_COLD,tmp);
X#endif
X tmp = 0;
X } else You("are freezing to death!");
X } else tmp = 0;
X break;
X case AD_FIRE:
X if(!mtmp->mcan && rn2(2)) {
X if (Fire_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel mildly hot.");
X#if defined(POLYSELF) && defined(GOLEMS)
X ugolemeffects(AD_FIRE,tmp);
X#endif
X tmp = 0;
X } else You("are burning to a crisp!");
X } else tmp = 0;
X break;
X#ifdef HARD
X case AD_DISE:
X if (!Sick) You("feel very sick.");
X make_sick(Sick + (long)rn1(25-ACURR(A_CON),15),FALSE);
X u.usick_cause = mtmp->data->mname;
X break;
X#endif
X default: tmp = 0;
X break;
X }
X }
X
X mdamageu(mtmp, tmp);
X if(u.uswldtim) --u.uswldtim;
X if(!u.uswldtim
X#ifdef POLYSELF
X || u.umonnum==PM_COCKATRICE
X#endif
X ) {
X#ifdef POLYSELF
X if (u.umonnum == PM_COCKATRICE) {
X kludge("%s very hurriedly regurgitates you!",
X Monnam(mtmp));
X u.uswldtim = 0;
X } else {
X#endif
X You("get regurgitated!");
X if(flags.verbose)
X kludge("Obviously %s doesn't like your taste.",
X mon_nam(mtmp));
X#ifdef POLYSELF
X }
X#endif
X regurgitates(mtmp);
X }
X return(1);
X}
X
Xstatic
Xint
Xexplmu(mtmp, mattk) /* monster explodes in your face */
X register struct monst *mtmp;
X register struct attack *mattk;
X{
X register int tmp = d((int)mattk->damn, (int)mattk->damd);
X
X if(mtmp->mcan) return(0);
X if(!Blind) kludge("%s explodes!", Monnam(mtmp));
X else pline("It explodes!");
X
X switch(mattk->adtyp) {
X case AD_COLD:
X if(Cold_resistance) {
X You("seem unaffected by it.");
X#if defined(POLYSELF) && defined(GOLEMS)
X ugolemeffects(AD_COLD,tmp);
X#endif
X tmp = 0;
X } else {
X if(ACURR(A_DEX) > rnd(20)) {
X if (!flags.verbose)
X You("are caught in the blast!");
X } else {
X You("duck the blast...");
X tmp /= 2;
X }
X }
X break;
X case AD_BLND:
X if(!Blind
X#ifdef POLYSELF
X && u.usym != S_YLIGHT
X#endif
X ) {
X You("are blinded by a blast of light!");
X make_blinded((long)tmp,FALSE);
X }
X tmp = 0;
X break;
X default: break;
X }
X mdamageu(mtmp, tmp);
X mondead(mtmp);
X return(2); /* it dies */
X}
X
Xstatic
Xint
Xgazemu(mtmp, mattk) /* monster gazes at you */
X register struct monst *mtmp;
X register struct attack *mattk;
X{
X switch(mattk->adtyp) {
X case AD_STON:
X if (mtmp->mcan) {
X You("notice that %s isn't all that ugly.",mon_nam(mtmp));
X break;
X }
X if (canseemon(mtmp)) {
X You("look upon %s.", mon_nam(mtmp));
X#ifdef POLYSELF
X if (resists_ston(uasmon)) {
X pline("So what?");
X break;
X }
X#endif
X You("turn to stone...");
X killer = mons[PM_MEDUSA].mname;
X done("stoned");
X }
X break;
X case AD_CONF:
X if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
X !mtmp->mspec_used && rn2(5)) {
X int conf = d(3,4);
X
X mtmp->mspec_used += (conf + rn2(6));
X if(!Confusion)
X pline("%s's gaze confuses you!", Monnam(mtmp));
X else
X You("are getting more and more confused.");
X make_confused(HConfusion + conf, FALSE);
X }
X break;
X default: impossible("Gaze attack %d?", mattk->adtyp);
X break;
X }
X return(1);
X}
X
Xvoid
Xmdamageu(mtmp, n) /* mtmp hits you for n points damage */
X register struct monst *mtmp;
X register int n;
X{
X#ifdef POLYSELF
X if (u.mtimedone) {
X u.mh -= n;
X flags.botl = 1;
X if (u.mh < 1) rehumanize();
X return;
X }
X#endif
X u.uhp -= n;
X flags.botl = 1;
X if(u.uhp < 1)
X done_in_by(mtmp);
X}
X
X#ifdef POLYSELF
Xstatic void
Xurustm(mon, obj)
Xregister struct monst *mon;
Xregister struct obj *obj;
X{
X boolean vis = cansee(mon->mx, mon->my);
X
X if (!mon || !obj) return; /* just in case */
X if (u.umonnum == PM_RUST_MONSTER &&
X objects[obj->otyp].oc_material == METAL &&
X obj->spe > -2) {
X if(obj->rustfree) {
X if (vis)
X pline("The rust vanishes from %s's weapon!",
X mon_nam(mon));
X } else if(obj->blessed && rn2(3)) {
X if (vis)
X pline("Somehow, %s's weapon is not affected!",
X mon_nam(mon));
X } else {
X if (vis)
X pline("%s's %s!", Monnam(mon), aobjnam(obj,"corrode"));
X obj->spe--;
X }
X }
X}
X#endif
X
X#ifdef SEDUCE
Xvoid
Xdoseduce(mon)
Xregister struct monst *mon;
X{
X register struct obj *ring;
X boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
X
X if (fem == poly_gender() || poly_gender()==2) return;
X
X if (mon->mcan || mon->mspec_used) {
X pline("%s acts as though %s has got a %sheadache.",
X Blind ? "It" : Monnam(mon), Blind ? "it" :
X fem ? "she" : "he",
X mon->mcan ? "severe " : "");
X return;
X }
X
X if (unconscious()) {
X kludge("%s seems dismayed at your lack of response.",
X Monnam(mon));
X return;
X }
X
X if (Blind) pline("It caresses you...");
X else You("feel very attracted to %s.", mon_nam(mon));
X
X for(ring = invent; ring; ring = ring->nobj) {
X if (ring->otyp != RIN_ADORNMENT) continue;
X if (fem) {
X if (rn2(20) < ACURR(A_CHA)) {
X pline("\"That %s looks pretty. May I have it?\" ",
X xname(ring));
X makeknown(RIN_ADORNMENT);
X if (yn() == 'n') continue;
X } else pline("%s decides she'd like your %s, and takes it.",
X Blind ? "She" : Monnam(mon), xname(ring));
X if (ring->known) makeknown(RIN_ADORNMENT);
X if (ring==uleft || ring==uright) Ring_gone(ring);
X if (ring==uwep) setuwep((struct obj *)0);
X freeinv(ring);
X mpickobj(mon,ring);
X } else {
X char buf[BUFSZ];
X
X if (uleft && uright && uleft->otyp == RIN_ADORNMENT
X && uright->otyp==RIN_ADORNMENT)
X break;
X if (ring==uleft || ring==uright) continue;
X if (rn2(20) < ACURR(A_CHA)) {
X pline("\"That %s looks pretty. Would you wear it for me?\" ",
X xname(ring));
X makeknown(RIN_ADORNMENT);
X if (yn() == 'n') continue;
X } else {
X pline("%s decides you'd look prettier wearing your %s,",
X Blind ? "He" : Monnam(mon), xname(ring));
X pline("and puts it on your finger.");
X }
X makeknown(RIN_ADORNMENT);
X if (!uright) {
X pline("%s puts the %s on your right hand.",
X Blind ? "He" : Monnam(mon), xname(ring));
X setworn(ring, RIGHT_RING);
X } else if (!uleft) {
X pline("%s puts the %s on your left hand.",
X Blind ? "He" : Monnam(mon), xname(ring));
X setworn(ring, LEFT_RING);
X } else if (uright && uright->otyp != RIN_ADORNMENT) {
X Strcpy(buf, xname(uright));
X pline("%s replaces your %s with your %s.",
X Blind ? "He" : Monnam(mon), buf, xname(ring));
X Ring_gone(uright);
X setworn(ring, RIGHT_RING);
X } else if (uleft && uleft->otyp != RIN_ADORNMENT) {
X Strcpy(buf, xname(uleft));
X pline("%s replaces your %s with your %s.",
X Blind ? "He" : Monnam(mon), buf, xname(ring));
X Ring_gone(uleft);
X setworn(ring, LEFT_RING);
X } else impossible("ring replacement");
X Ring_on(ring);
X prinv(ring);
X }
X }
X
X pline("%s murmurs in your ear, while helping you undress.",
X Blind ? (fem ? "She" : "He") : Monnam(mon));
X mayberem(uarmc, "cloak");
X if(!uarmc)
X mayberem(uarm, "suit");
X mayberem(uarmf, "boots");
X mayberem(uarmg, "gloves");
X mayberem(uarms, "shield");
X#ifdef SHIRT
X if(!uarmc && !uarm)
X mayberem(uarmu, "shirt");
X#endif
X
X if (uarm || uarmc) {
X pline("\"You're such a %s; I wish...\"",
X flags.female ? "sweet lady" : "nice guy");
X rloc(mon);
X return;
X }
X#define ALIGNLIM (5L + (moves/200L)) /* from pray.c */
X if (u.ualigntyp == U_CHAOTIC && u.ualign < ALIGNLIM) u.ualign++;
X
X /* by this point you have discovered mon's identity, blind or not... */
X pline("Time stands still while you and %s lie in each other's arms...",
X mon_nam(mon));
X if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
X /* Don't bother with mspec_used here... it didn't get tired! */
X pline("%s seems to have enjoyed it more than you...",
X Monnam(mon));
X#ifdef SPELLS
X switch (rn2(5)) {
X case 0: You("feel drained of energy.");
X u.uen = 0;
X u.uenmax -= rnd(10);
X if (u.uenmax < 0) u.uenmax = 0;
X break;
X#else
X switch (rnd(4)) {
X#endif
X case 1: You("are down in the dumps.");
X adjattrib(A_CON, -1, TRUE);
X flags.botl = 1;
X break;
X case 2: Your("senses are dulled.");
X adjattrib(A_WIS, -1, TRUE);
X flags.botl = 1;
X break;
X case 3:
X#ifdef POLYSELF
X if (resists_drli(uasmon))
X You("have a curious feeling...");
X else {
X#endif
X You("feel out of shape.");
X losexp();
X#ifdef POLYSELF
X }
X#endif
X break;
X case 4: You("feel exhausted.");
X losehp(5+rnd(10), "bout of exhaustion");
X break;
X }
X } else {
X mon->mspec_used = rnd(100); /* monster is worn out */
X You("seem to have enjoyed it more than %s...", mon_nam(mon));
X#ifdef SPELLS
X switch (rn2(5)) {
X case 0: You("feel raised to your full potential.");
X u.uen = (u.uenmax += rnd(5));
X break;
X#else
X switch (rnd(4)) {
X#endif
X case 1: You("feel good enough to do it again.");
X adjattrib(A_CON, 1, TRUE);
X flags.botl = 1;
X break;
X case 2: You("will always remember %s...", mon_nam(mon));
X adjattrib(A_WIS, 1, TRUE);
X flags.botl = 1;
X break;
X case 3: pline("That was a very educational experience.");
X pluslvl();
X break;
X case 4: You("feel restored to health!");
X u.uhp = u.uhpmax;
X#ifdef POLYSELF
X if (u.mtimedone) u.mh = u.mhmax;
X#endif
X flags.botl = 1;
X break;
X }
X }
X
X if (mon->mtame) /* don't charge */ ;
X else if (rn2(20) < ACURR(A_CHA)) {
X pline("%s demands that you pay %s, but you refuse...",
X Monnam(mon), (fem ? "her" : "him"));
X }
X#ifdef POLYSELF
X else if (u.umonnum == PM_LEPRECHAUN)
X pline("%s tries to take your money, but fails...",
X Monnam(mon));
X#endif
X else {
X long cost = (long)rnd(
X (int)(u.ugold > 32767L ? 32767 : u.ugold) +10) + 500;
X
X if (mon->mpeaceful) {
X cost /= 5;
X if (!cost) cost=1;
X }
X if (cost > u.ugold) cost = u.ugold;
X if (!cost) pline("%s says: \"It's on the house!\"", Monnam(mon));
X else {
X pline("%s takes %ld Zorkmid%s for services rendered!",
X Monnam(mon), cost, (cost==1) ? "" : "s");
X u.ugold -= cost;
X mon->mgold += cost;
X flags.botl = 1;
X }
X }
X if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
X rloc(mon);
X}
X
Xstatic void
Xmayberem(obj, str)
Xregister struct obj *obj;
Xchar *str;
X{
X if (!obj || !obj->owornmask) return;
X
X if (rn2(20) < ACURR(A_CHA)) {
X pline("\"Shall I remove your %s, %s?\" ",
X str,
X (!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
X if (yn() == 'n') return;
X } else pline("\"Take off your %s; %s.\"", str,
X (obj == uarm) ? "let's get a little closer" :
X (obj == uarmc) ? "it's in the way" :
X (obj == uarmf) ? "let me rub your feet" :
X (obj == uarmg) ? "they're too clumsy" :
X#ifdef SHIRT
X (obj == uarmu) ? "let me massage you" :
X#endif
X /* obj == uarmh */
X "so I can run my fingers through your hair");
X
X if (obj == uarm) (void) Armor_off();
X else if (obj == uarmc) (void) Cloak_off();
X else if (obj == uarmf) (void) Boots_off();
X else if (obj == uarmg) (void) Gloves_off();
X else if (obj == uarmh) (void) Helmet_off();
X else setworn((struct obj *)0, obj->owornmask & W_ARMOR);
X}
X#endif /* SEDUCE */
X
X#ifdef POLYSELF
Xstatic int
Xpassiveum(olduasmon,mtmp)
Xstruct permonst *olduasmon;
Xregister struct monst *mtmp;
X{
X register struct permonst *mdat = mtmp->data;
X int dam = 0;
X
X if (olduasmon->mattk[0].aatyp != AT_NONE) return 1;
X
X /* These affect the enemy even if you were "killed" (rehumanized) */
X switch(olduasmon->mattk[0].adtyp) {
X case AD_ACID:
X if (!rn2(2)) {
X kludge("%s is splashed by your acid!", Monnam(mtmp));
X if(!resists_acid(mdat))
X dam = d((int)olduasmon->mlevel+1,
X (int)olduasmon->mattk[0].damd);
X else pline("%s is not affected.", Monnam(mtmp));
X }
X break;
X default:
X break;
X }
X if (!u.mtimedone) return 1;
X
X /* These affect the enemy only if you are still a monster */
X if (rn2(3)) switch(uasmon->mattk[0].adtyp) {
X case AD_PLYS: /* Floating eye */
X if (!mtmp->mblinded && rn2(3)) {
X if (Blind)
X pline("As a blind %s, you cannot defend yourself.",
X uasmon->mname);
X else {
X pline("%s is frozen by your gaze!", Monnam(mtmp));
X mtmp->mfroz = 1;
X }
X }
X break;
X case AD_COLD: /* Brown mold or blue jelly */
X dam = d((int)uasmon->mlevel+1, (int)uasmon->mattk[0].damd);
X if(resists_cold(mdat)) {
X shieldeff(mtmp->mx, mtmp->my);
X kludge("%s is mildly chilly.", Monnam(mtmp));
X#ifdef GOLEMS
X golemeffects(mtmp, AD_COLD, dam);
X#endif /* GOLEMS */
X dam = 0;
X break;
X }
X kludge("%s is suddenly very cold!", Monnam(mtmp));
X u.mh += dam / 2;
X if (u.mhmax < u.mh) u.mhmax = u.mh;
X if (u.mhmax > ((uasmon->mlevel+1) * 8)) {
X register struct monst *mon;
X
X if (mon = cloneu()) {
X mon->mhpmax = u.mhmax /= 2;
X if (Blind)
X You("multiply from its heat!");
X else
X You("multiply from %s's heat!", mon_nam(mtmp));
X }
X }
X break;
X case AD_STUN: /* Yellow mold */
X if (!mtmp->mstun) {
X mtmp->mstun = 1;
X kludge("%s staggers...", Monnam(mtmp));
X }
X break;
X case AD_FIRE: /* Red mold */
X dam = d((int)uasmon->mlevel+1, (int)uasmon->mattk[0].damd);
X if(resists_fire(mdat)) {
X shieldeff(mtmp->mx, mtmp->my);
X kludge("%s is mildly warm.", Monnam(mtmp));
X#ifdef GOLEMS
X golemeffects(mtmp, AD_FIRE, dam);
X#endif /* GOLEMS */
X dam = 0;
X break;
X }
X kludge("%s is suddenly very hot!", Monnam(mtmp));
X }
X
X if((mtmp->mhp -= dam) <= 0) {
X kludge("%s dies!", Monnam(mtmp));
X xkilled(mtmp,0);
X return(2);
X }
X return 1;
X}
X
X#include "edog.h"
Xstruct monst *
Xcloneu()
X{
X register struct monst *mon;
X register int nmlth = strlen(plname) + 1;
X
X if (u.mh <= 1) return(struct monst *)0;
X uasmon->pxlth += sizeof(struct edog) + nmlth;
X mon = makemon(uasmon, u.ux, u.uy);
X uasmon->pxlth -= sizeof(struct edog) + nmlth;
X mon->mxlth = sizeof(struct edog);
X Strcpy(NAME(mon), plname);
X mon->mnamelth = nmlth;
X initedog(mon);
X mon->m_lev = uasmon->mlevel;
X mon->mhp = u.mh /= 2;
X mon->mhpmax = u.mhmax;
X return(mon);
X}
X#endif /* POLYSELF */
END_OF_FILE
if test 42552 -ne `wc -c <'src/mhitu.c'`; then
echo shar: \"'src/mhitu.c'\" unpacked with wrong size!
fi
# end of 'src/mhitu.c'
fi
echo shar: End of archive 3 \(of 38\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; 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