home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part19
< prev
next >
Wrap
Internet Message Format
|
1993-02-01
|
58KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i019: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part19/108
Message-ID: <4302@master.CNA.TEK.COM>
Date: 28 Jan 93 19:14:34 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2079
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1575
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 19
Archive-name: nethack31/Part19
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /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 19 (of 108)."
# Contents: src/sit.c src/uhitm.c
# Wrapped by billr@saab on Wed Jan 27 16:08:53 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/sit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/sit.c'\"
else
echo shar: Extracting \"'src/sit.c'\" \(8661 characters\)
sed "s/^X//" >'src/sit.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)sit.c 3.1 92/10/24 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#include "artifact.h"
X
Xvoid
Xtake_gold()
X{
X if (u.ugold <= 0) {
X You("feel a strange sensation.");
X } else {
X You("notice you have no gold!");
X u.ugold = 0;
X flags.botl = 1;
X }
X}
X
Xint
Xdosit()
X{
X char pbuf[BUFSZ];
X register struct trap *trap;
X register int typ = levl[u.ux][u.uy].typ;
X
X if(Levitation) {
X pline("There's nothing to sit on up here.");
X return 0;
X }
X
X Strcpy(pbuf, "You sit on the %s.");
X
X if(OBJ_AT(u.ux, u.uy)) {
X register struct obj *obj;
X
X obj = level.objects[u.ux][u.uy];
X You("sit on %s.", the(xname(obj)));
X if(!Is_box(obj)) pline("It is not very comfortable...");
X
X } else if(trap = t_at(u.ux, u.uy)) {
X
X if(u.utrap) {
X if(u.utraptype == TT_BEARTRAP) {
X You("can't sit down!");
X u.utrap++;
X } else if(u.utraptype == TT_PIT) {
X You("sit in the bottom of the pit.");
X if(trap->ttyp == SPIKED_PIT) pline("This hurts!");
X u.utrap += rn2(5);
X } else if(u.utraptype == TT_WEB) {
X pline(pbuf, "giant spider's web");
X You("are further entangled!");
X u.utrap += rn1(10, 5);
X } else if(u.utraptype == TT_LAVA) {
X /* Must have fire resistance or they'd be dead already */
X You("sit in the lava!");
X u.utrap += rnd(4);
X losehp(d(2,10), "sitting in lava", KILLED_BY);
X } else if(u.utraptype == TT_INFLOOR) {
X You("can't maneuver to sit!");
X u.utrap++;
X }
X } else {
X You("sit down.");
X dotrap(trap);
X }
X } else if(Underwater || Is_waterlevel(&u.uz)) {
X if (Is_waterlevel(&u.uz))
X pline("There are no seats floating in the neighborhood.");
X else
X You("sit down in the muddy bottom.");
X } else if(is_pool(u.ux, u.uy)) {
X
X You("sit in the water.");
X if (!rn2(10) && uarm)
X (void) rust_dmg(uarm, "armor", 1, TRUE);
X#ifdef POLYSELF
X /* Note: without POLYSELF, this can't _happen_ without */
X /* water walking boots.... */
X if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS)
X (void) rust_dmg(uarm, "armor", 1, TRUE);
X#endif
X#ifdef SINKS
X } else if(IS_SINK(typ)) {
X
X pline(pbuf, defsyms[S_sink].explanation);
X Your("%s gets wet.", humanoid(uasmon) ? "rump" : "underside");
X#endif
X } else if(IS_ALTAR(typ)) {
X
X pline(pbuf, defsyms[S_altar].explanation);
X altar_wrath(u.ux, u.uy);
X
X } else if(typ == STAIRS) {
X
X pline(pbuf, "stairs");
X
X } else if(typ == LADDER) {
X
X pline(pbuf, "ladder");
X
X } else if (is_lava(u.ux, u.uy)) {
X
X /* must be WWalking */
X pline(pbuf, "lava");
X pline("It burns you!");
X losehp(d((Fire_resistance ? 2 : 10), 10),
X "sitting on lava", KILLED_BY);
X
X } else if (is_ice(u.ux, u.uy)) {
X
X pline(pbuf, defsyms[S_ice].explanation);
X if (!Cold_resistance) pline("It's very cold...");
X
X } else if (typ == DRAWBRIDGE_DOWN) {
X
X pline(pbuf, "drawbridge");
X
X } else if(IS_THRONE(typ)) {
X
X pline(pbuf, defsyms[S_throne].explanation);
X if (rnd(6) > 4) {
X switch (rnd(13)) {
X case 1:
X (void) adjattrib(rn2(A_MAX), -rn1(4,3), FALSE);
X losehp(rnd(10), "cursed throne", KILLED_BY_AN);
X break;
X case 2:
X (void) adjattrib(rn2(A_MAX), 1, FALSE);
X break;
X case 3:
X pline("A%s charge of electricity shoots through your body!",
X (Shock_resistance) ? "" : " massive");
X if(Shock_resistance)
X losehp(rnd(6), "electric chair", KILLED_BY_AN);
X else losehp(rnd(30), "electric chair", KILLED_BY_AN);
X exercise(A_CON, FALSE);
X break;
X case 4:
X You("feel much, much better!");
X if(u.uhp >= (u.uhpmax - 5)) u.uhpmax += 4;
X u.uhp = u.uhpmax;
X make_blinded(0L,TRUE);
X make_sick(0L,FALSE);
X heal_legs();
X flags.botl = 1;
X break;
X case 5:
X take_gold();
X break;
X case 6:
X if(u.uluck + rn2(5) < 0) {
X You("feel your luck is changing.");
X change_luck(1);
X } else makewish();
X break;
X case 7:
X {
X register int cnt = rnd(10);
X
X You("hear a voice echo:");
X verbalize("Thy audience hath been summoned, %s!",
X flags.female ? "Dame" : "Sire");
X while(cnt--)
X (void) makemon(courtmon(), u.ux, u.uy);
X break;
X }
X case 8:
X You("hear a voice echo:");
X verbalize("By thy Imperious order, %s...",
X flags.female ? "Dame" : "Sire");
X do_genocide(1);
X break;
X case 9:
X You("hear a voice echo:");
X verbalize("A curse upon thee for sitting upon this most holy throne!");
X if (Luck > 0) {
X make_blinded(Blinded + rn1(100,250),TRUE);
X } else rndcurse();
X break;
X case 10:
X if (Luck < 0 || (HSee_invisible & INTRINSIC)) {
X if (level.flags.nommap) {
X pline(
X "A terrible drone fills your head!");
X make_confused(HConfusion + rnd(30),
X FALSE);
X } else {
X pline("An image forms in your mind.");
X do_mapping();
X }
X } else {
X Your("vision clarifies.");
X HSee_invisible |= FROMOUTSIDE;
X newsym(u.ux, u.uy);
X }
X break;
X case 11:
X if (Luck < 0) {
X You("feel threatened.");
X aggravate();
X } else {
X
X You("feel a wrenching sensation.");
X tele(); /* teleport him */
X }
X break;
X case 12:
X You("are granted a gift of insight!");
X if (invent) {
X int ret, cval = rn2(5); /* agrees w/seffects() */
X do {
X ret = ggetobj("identify", identify, cval);
X } while (cval && (cval -= ret));
X }
X break;
X case 13:
X Your("mind turns into a pretzel!");
X make_confused(HConfusion + rn1(7,16),FALSE);
X break;
X default: impossible("throne effect");
X break;
X }
X } else You("feel somehow out of place...");
X
X if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) {
X /* may have teleported */
X pline("The throne vanishes in a puff of logic.");
X levl[u.ux][u.uy].typ = ROOM;
X if(Invisible) newsym(u.ux,u.uy);
X }
X
X#ifdef POLYSELF
X } else if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE) {
X struct obj *uegg;
X
X if (!flags.female) {
X pline("Males can't lay eggs!");
X return 0;
X }
X
X if (u.uhunger < (int)objects[EGG].oc_nutrition) {
X You("are too weak to lay an egg.");
X return 0;
X }
X
X uegg = mksobj(EGG, FALSE, FALSE);
X uegg->spe = 1;
X uegg->quan = 1;
X uegg->owt = weight(uegg);
X uegg->corpsenm =
X (u.umonnum==PM_QUEEN_BEE ? PM_KILLER_BEE : monsndx(uasmon));
X uegg->known = uegg->dknown = 1;
X You("lay an egg.");
X dropy(uegg);
X stackobj(uegg);
X morehungry((int)objects[EGG].oc_nutrition);
X#endif
X } else if (u.uswallow)
X pline("There are no seats in here!");
X else
X pline("Having fun sitting on the floor?");
X return(1);
X}
X
Xvoid
Xrndcurse() /* curse a few inventory items at random! */
X{
X int nobj = 0;
X int cnt, onum;
X struct obj *otmp;
X
X if(Antimagic) {
X shieldeff(u.ux, u.uy);
X You("feel a malignant aura surround you.");
X }
X
X for (otmp = invent; otmp; otmp = otmp->nobj) nobj++;
X
X if (nobj)
X for (cnt = rnd(6/((!!Antimagic) + (!!Half_spell_damage) + 1));
X cnt > 0; cnt--) {
X onum = rn2(nobj);
X for(otmp = invent; onum != 0; onum--)
X otmp = otmp->nobj;
X
X if(otmp->oartifact && spec_ability(otmp, SPFX_INTEL) &&
X rn2(10) < 8) {
X pline("%s resists!", The(xname(otmp)));
X continue;
X }
X
X if(otmp->blessed)
X unbless(otmp);
X else
X curse(otmp);
X }
X}
X
Xvoid
Xattrcurse() /* remove a random INTRINSIC ability */
X{
X switch(rnd(10)) {
X case 1 : if (HFire_resistance & INTRINSIC) {
X HFire_resistance &= ~INTRINSIC;
X You("feel warmer.");
X break;
X }
X case 2 : if (HTeleportation & INTRINSIC) {
X HTeleportation &= ~INTRINSIC;
X You("feel less jumpy.");
X break;
X }
X case 3 : if (HPoison_resistance & INTRINSIC) {
X HPoison_resistance &= ~INTRINSIC;
X You("feel a little sick!");
X break;
X }
X case 4 : if (HTelepat & INTRINSIC) {
X HTelepat &= ~INTRINSIC;
X if (Blind && !Telepat)
X see_monsters(); /* Can't sense mons anymore! */
X Your("senses fail!");
X break;
X }
X case 5 : if (HCold_resistance & INTRINSIC) {
X HCold_resistance &= ~INTRINSIC;
X You("feel cooler.");
X break;
X }
X case 6 : if (HInvis & INTRINSIC) {
X HInvis &= ~INTRINSIC;
X You("feel paranoid.");
X break;
X }
X case 7 : if (HSee_invisible & INTRINSIC) {
X HSee_invisible &= ~INTRINSIC;
X You("thought you saw something!");
X break;
X }
X case 8 : if (Fast & INTRINSIC) {
X Fast &= ~INTRINSIC;
X You("feel slower.");
X break;
X }
X case 9 : if (Stealth & INTRINSIC) {
X Stealth &= ~INTRINSIC;
X You("feel clumsy.");
X break;
X }
X case 10: if (Protection & INTRINSIC) {
X Protection &= ~INTRINSIC;
X You("feel vulnerable.");
X break;
X }
X default: break;
X }
X}
X
X/*sit.c*/
END_OF_FILE
if test 8661 -ne `wc -c <'src/sit.c'`; then
echo shar: \"'src/sit.c'\" unpacked with wrong size!
fi
# end of 'src/sit.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'\" \(44975 characters\)
sed "s/^X//" >'src/uhitm.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)uhitm.c 3.1 92/12/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
Xstatic boolean FDECL(known_hitum, (struct monst *,int));
Xstatic boolean FDECL(hitum, (struct monst *,int));
X#ifdef POLYSELF
Xstatic int FDECL(explum, (struct monst *,struct attack *));
Xstatic int FDECL(gulpum, (struct monst *,struct attack *));
Xstatic boolean FDECL(hmonas, (struct monst *,int));
X#endif
Xstatic void FDECL(nohandglow, (struct monst *));
X
Xextern boolean notonhead; /* for long worms */
X/* The below might become a parameter instead if we use it a lot */
Xstatic int dieroll;
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 if (!enexto(&mm, mm.x, mm.y, mon->data)) return (struct monst *)0;
X if (MON_AT(mm.x, mm.y) || mon->mhp <= 1) return (struct monst *)0;
X /* may have been extinguished for population control */
X if(mon->data->geno & G_EXTINCT) 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 (mon->ispriest) m2->ispriest = FALSE;
X m2->mxlth = 0;
X m2->mnamelth = 0;
X place_monster(m2, m2->mx, m2->my);
X newsym(m2->mx,m2->my); /* display the new monster */
X if (mon->mtame) {
X struct monst *m3;
X
X /* because m2 is a copy of mon it is tame but not init'ed.
X * however, tamedog will not re-tame a tame dog, so m2
X * must be made non-tame to get initialized properly.
X */
X m2->mtame = 0;
X if ((m3 = tamedog(m2, (struct obj *)0)) != 0)
X m2 = m3;
X }
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 char qbuf[QBUFSZ];
X
X if(mtmp->m_ap_type && !Protection_from_shape_changers
X && !sensemon(mtmp)) {
X stumble_onto_mimic(mtmp);
X mtmp->data->mflags3 &= ~M3_WAITMASK;
X return(1);
X }
X
X if(mtmp->mundetected && hides_under(mtmp->data) && !canseemon(mtmp)) {
X mtmp->mundetected = 0;
X if (!(Blind ? Telepat : (HTelepat & (W_ARMH|W_AMUL|W_ART)))) {
X register struct obj *obj;
X
X if(Blind)
X pline("Wait! There's a hidden monster there!");
X else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
X pline("Wait! There's %s hiding under %s!",
X an(l_monnam(mtmp)), doname(obj));
X wakeup(mtmp);
X mtmp->data->mflags3 &= ~M3_WAITMASK;
X return(TRUE);
X }
X }
X
X if (flags.confirm && mtmp->mpeaceful
X && !Confusion && !Hallucination && !Stunned) {
X /* Intelligent chaotic weapons (Stormbringer) want blood */
X if (uwep && uwep->oartifact == ART_STORMBRINGER)
X return(FALSE);
X
X if (canspotmon(mtmp)) {
X Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
X if (yn(qbuf) != 'y') {
X flags.move = 0;
X mtmp->data->mflags3 &= ~M3_WAITMASK;
X return(TRUE);
X }
X }
X }
X
X return(FALSE);
X}
X
Xschar
Xfind_roll_to_hit(mtmp)
Xregister struct monst *mtmp;
X{
X schar tmp;
X int tmp2;
X struct permonst *mdat = mtmp->data;
X
X tmp = 1 + Luck + abon() +
X find_mac(mtmp) +
X#ifdef POLYSELF
X ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel);
X#else
X u.ulevel;
X#endif
X
X/* it is unchivalrous to attack the defenseless or from behind */
X if (pl_character[0] == 'K' && u.ualign.type == A_LAWFUL &&
X (!mtmp->mcanmove || mtmp->msleep || mtmp->mflee) &&
X u.ualign.record > -10) adjalign(-1);
X
X/* attacking peaceful creatures is bad for the samurai's giri */
X if (pl_character[0] == 'S' && mtmp->mpeaceful &&
X u.ualign.record > -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->mcanmove) {
X tmp += 4;
X if(!rn2(10)) {
X mtmp->mcanmove = 1;
X mtmp->mfrozen = 0;
X }
X }
X if (is_orc(mtmp->data) && pl_character[0]=='E') tmp++;
X
X/* with a lot of luggage, your agility diminishes */
X if(tmp2 = near_capacity()) tmp -= (tmp2*2) - 1;
X if(u.utrap) tmp -= 3;
X#ifdef POLYSELF
X/* Some monsters have a combination of weapon attacks and non-weapon
X * attacks. It is therefore wrong to add hitval to tmp; we must add it
X * only for the specific attack (in hmonas()).
X */
X if(uwep && u.umonnum == -1) tmp += hitval(uwep, mdat);
X#else
X if(uwep) tmp += hitval(uwep, mdat);
X#endif
X return tmp;
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;
X register struct permonst *mdat = mtmp->data;
X
X /* This section of code provides protection against accidentally
X * hitting peaceful (like '@') and tame (like 'd') monsters.
X * Protection is provided as long as player is not: blind, confused,
X * hallucinating or stunned.
X * changes by wwp 5/16/85
X * More changes 12/90, -dkh-. if its tame and safepet, (and protected
X * 07/92) then we assume that you're not trying to attack. Instead,
X * you'll usually just swap places if this is a movement command
X */
X /* Intelligent chaotic weapons (Stormbringer) want blood */
X if (is_safepet(mtmp) &&
X (!uwep || uwep->oartifact != ART_STORMBRINGER)) {
X /* there are some additional considerations: this won't work
X * if in a shop or Punished or you miss a random roll or
X * if you can walk thru walls and your pet cannot (KAA) or
X * if your pet is a long worm (unless someone does better).
X * there's also a chance of displacing a "frozen" monster.
X * sleeping monsters might magically walk in their sleep.
X */
X unsigned int foo = (Punished ||
X !rn2(7) || is_longworm(mtmp->data));
X
X if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || foo
X#ifdef POLYSELF
X || (IS_ROCK(levl[u.ux][u.uy].typ) &&
X !passes_walls(mtmp->data))
X#endif
X ) {
X mtmp->mflee = 1;
X mtmp->mfleetim = rnd(6);
X You("stop. %s is in your way!",
X (mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp)));
X return(TRUE);
X } else if ((mtmp->mfrozen || (! mtmp->mcanmove)
X || (mtmp->data->mmove == 0)) && rn2(6)) {
X pline("%s doesn't seem to move!", Monnam(mtmp));
X return(TRUE);
X } else return(FALSE);
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 mtmp->data->mflags3 &= ~M3_WAITMASK;
X return(TRUE);
X }
X }
X#endif
X
X if(check_capacity("You cannot fight while so heavily loaded."))
X return (TRUE);
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 exercise(A_STR, TRUE); /* you're exercising muscles */
X /* andrew@orca: prevent unlimited pick-axe attacks */
X u_wipe_engr(3);
X
X if(mdat->mlet == S_LEPRECHAUN && mtmp->mfrozen && !mtmp->msleep &&
X !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
X (m_move(mtmp, 0) == 2 || /* it died */
X mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
X return(FALSE);
X
X tmp = find_roll_to_hit(mtmp);
X#ifdef POLYSELF
X if (u.umonnum >= 0) (void) hmonas(mtmp, tmp);
X else
X#endif
X (void) hitum(mtmp, tmp);
X
X mtmp->data->mflags3 &= ~M3_WAITMASK;
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, special;
X
X /* we need to know whether the special monster was peaceful */
X /* before the attack, to save idle calls to angry_guards() */
X special = (mon->mpeaceful && (mon->data == &mons[PM_WATCHMAN] ||
X mon->data == &mons[PM_WATCH_CAPTAIN] ||
X mon->ispriest || mon->isshk));
X
X if(!mhit) {
X if(flags.verbose) You("miss %s.", mon_nam(mon));
X else You("miss it.");
X if(!mon->msleep && mon->mcanmove)
X wakeup(mon);
X#ifdef MUSE
X else if (uwep && uwep->otyp == TSURUGI &&
X MON_WEP(mon) && !rn2(20)) {
X /* 1/20 chance of shattering defender's weapon */
X struct obj *obj = MON_WEP(mon);
X
X MON_NOWEP(mon);
X m_useup(mon, obj);
X pline("%s weapon shatters!", s_suffix(Monnam(mon)));
X /* perhaps this will freak out the monster */
X if (!rn2(3)) {
X mon->mflee = 1;
X mon->mfleetim += rnd(20);
X }
X }
X#endif
X } else {
X /* we hit the monster; be careful: it might die! */
X notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy);
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 if (mon->wormno) cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep);
X }
X if(mon->ispriest && !rn2(2)) ghod_hitsu(mon);
X if(special) (void) angry_guards(!flags.soundok);
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 NEARDATA malive;
X boolean mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
X
X if(tmp > dieroll) exercise(A_DEX, TRUE);
X malive = known_hitum(mon, mhit);
X (void) passive(mon, mhit, malive, FALSE);
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 int tmp;
X struct permonst *mdat = mon->data;
X /* Why all these booleans? This stuff has to be done in the
X * following order:
X * 1) Know what we're attacking with, and print special hittxt for
X * unusual cases.
X * 2a) Know whether we did damage (depends on 1)
X * 2b) Know if it's poisoned (depends on 1)
X * 2c) Know whether we get a normal damage bonus or not (depends on 1)
X * 3a) Know what the value of the damage bonus is (depends on 2c)
X * 3b) Know how much poison damage was taken (depends on 2b) and if the
X * poison instant-killed it
X * 4) Know if it was killed (requires knowing 3a, 3b) except by instant-
X * kill poison
X * 5) Print hit message (depends on 1 and 4)
X * 6a) Print poison message (must be done after 5)
X#if 0
X * 6b) Rust weapon (must be done after 5)
X#endif
X * 7) Possibly kill monster (must be done after 6a, 6b)
X * 8) Instant-kill from poison (can happen anywhere between 5 and 9)
X * 9) Hands not glowing (must be done after 7 and 8)
X * The major problem is that since we don't want a "hit" message
X * when the monster dies, we have to know how much damage it did
X * _before_ outputting a hit message, but any messages associated with
X * the damage don't come out until _after_ outputting a hit message.
X */
X boolean hittxt = FALSE, destroyed = FALSE;
X boolean get_dmg_bonus = TRUE;
X boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
X boolean silvermsg = FALSE;
X
X wakeup(mon);
X if(!obj) { /* attack with bare hands */
X if (mdat == &mons[PM_SHADE])
X tmp = 0;
X else
X tmp = rnd(2);
X#if 0
X if(mdat == &mons[PM_COCKATRICE] && !uarmg
X#ifdef POLYSELF
X && !resists_ston(uasmon)
X#endif
X ) {
X
X You("hit %s with your bare %s.",
X mon_nam(mon), makeplural(body_part(HAND)));
X# ifdef POLYSELF
X if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
X return TRUE;
X# endif
X You("turn to stone...");
X done_in_by(mon);
X hittxt = TRUE; /* maybe lifesaved */
X }
X#endif
X } else {
X if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
X obj->otyp == UNICORN_HORN || obj->oclass == ROCK_CLASS) {
X
X /* If not a melee weapon, and either not thrown, or thrown */
X /* and a bow (bows are >BOOMERANG), or thrown and a missile */
X /* without a propellor (missiles are <DART), do 1-2 points */
X if((obj->otyp >= BOW || obj->otyp < DART)
X && obj->otyp != PICK_AXE && obj->otyp != UNICORN_HORN
X && (!thrown ||
X (obj->oclass != ROCK_CLASS &&
X (obj->otyp > BOOMERANG ||
X (obj->otyp < DART &&
X (!uwep ||
X objects[obj->otyp].w_propellor !=
X -objects[uwep->otyp].w_propellor)
X ))))) {
X if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
X tmp = 0;
X else
X tmp = rnd(2);
X } else {
X tmp = dmgval(obj, mdat);
X if (obj->oartifact &&
X artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
X if(mon->mhp <= 0) /* artifact killed monster */
X return FALSE;
X hittxt = TRUE;
X }
X if (objects[obj->otyp].oc_material == SILVER
X && hates_silver(mdat))
X silvermsg = TRUE;
X if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
X !rnl(3)) {
X pline("As you hit %s, %s breaks into splinters.",
X mon_nam(mon), the(xname(obj)));
X useup(obj);
X obj = (struct obj *) 0;
X hittxt = TRUE;
X if (mdat != &mons[PM_SHADE])
X tmp++;
X } else if(thrown &&
X (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)) {
X if(uwep && obj->otyp < DART &&
X objects[obj->otyp].w_propellor ==
X -objects[uwep->otyp].w_propellor) {
X /* Elves and Samurai do extra damage using
X * their bows&arrows; they're highly trained.
X */
X if (pl_character[0] == 'S' &&
X obj->otyp == YA && uwep->otyp == YUMI)
X tmp++;
X else if (pl_character[0] == 'E' &&
X obj->otyp == ELVEN_ARROW &&
X uwep->otyp == ELVEN_BOW)
X tmp++;
X }
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->oclass == POTION_CLASS) {
X if (obj->quan > 1L) setuwep(splitobj(obj, 1L));
X else setuwep((struct obj *)0);
X freeinv(obj);
X potionhit(mon,obj);
X hittxt = TRUE;
X if (mdat == &mons[PM_SHADE])
X tmp = 0;
X else
X tmp = 1;
X } else {
X switch(obj->otyp) {
X case HEAVY_IRON_BALL:
X tmp = rnd(25); break;
X case BOULDER:
X tmp = rnd(20); break;
X case MIRROR:
X You("break your mirror. That's bad luck!");
X change_luck(-2);
X useup(obj);
X obj = (struct obj *) 0;
X hittxt = TRUE;
X tmp = 1;
X break;
X#ifdef TOURIST
X case EXPENSIVE_CAMERA:
X You("succeed in destroying your camera. Congratulations!");
X useup(obj);
X return(TRUE);
X#endif
X case CORPSE: /* fixed by polder@cs.vu.nl */
X if(obj->corpsenm == PM_COCKATRICE) {
X You("hit %s with the cockatrice corpse.",
X mon_nam(mon));
X if(resists_ston(mdat)) {
X tmp = 1;
X hittxt = TRUE;
X break;
X }
X if(poly_when_stoned(mdat)) {
X mon_to_stone(mon);
X tmp = 1;
X hittxt = TRUE;
X break;
X }
X pline("%s turns to stone.", Monnam(mon));
X stoned = TRUE;
X xkilled(mon,0);
X return(FALSE);
X }
X tmp = mons[obj->corpsenm].msize + 1;
X break;
X case EGG: /* only possible if hand-to-hand */
X if(obj->corpsenm > -1
X && obj->corpsenm != PM_COCKATRICE
X && mdat == &mons[PM_COCKATRICE]) {
X You("hit %s with the %s egg%s.",
X mon_nam(mon),
X mons[obj->corpsenm].mname,
X plur(obj->quan));
X hittxt = TRUE;
X pline("The egg%sn't live any more...",
X (obj->quan == 1L) ? " is" : "s are");
X obj->otyp = ROCK;
X obj->oclass = GEM_CLASS;
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(mdat)) mon->mflee = 1;
X tmp = 1;
X break;
X case CREAM_PIE:
X#ifdef POLYSELF
X case BLINDING_VENOM:
X if(Blind || !haseyes(mon->data))
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(mdat) &&
X mdat != &mons[PM_FLOATING_EYE])
X ? (*(eos(mon_nam(mon))-1) == 's' ? "' face" :
X "'s face") : "");
X if(mon->msleep) mon->msleep = 0;
X setmangry(mon);
X if(haseyes(mon->data)) {
X mon->mcansee = 0;
X tmp = rn1(25, 21);
X if(((int) mon->mblinded + tmp) > 127)
X mon->mblinded = 127;
X else mon->mblinded += tmp;
X }
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(mdat)) {
X Your("venom hits %s harmlessly.",
X mon_nam(mon));
X tmp = 0;
X } else {
X Your("venom burns %s!", mon_nam(mon));
X tmp = dmgval(obj, mdat);
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/100;
X if(tmp < 1) tmp = 1;
X else tmp = rnd(tmp);
X if(tmp > 6) tmp = 6;
X }
X if (mdat == &mons[PM_SHADE] && obj &&
X objects[obj->otyp].oc_material != SILVER)
X tmp = 0;
X }
X }
X
X /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
X * *OR* if attacking bare-handed!! */
X
X if (get_dmg_bonus && tmp) {
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(!thrown || !obj || !uwep ||
X (obj->oclass != GEM_CLASS && obj->oclass != WEAPON_CLASS) ||
X !objects[obj->otyp].w_propellor ||
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 if(resists_poison(mdat))
X needpoismsg = TRUE;
X else if (rn2(10))
X tmp += rnd(6);
X else poiskilled = TRUE;
X }
X if(tmp < 1)
X if (mdat == &mons[PM_SHADE]) {
X Your("attack passes harmlessly through %s.",
X mon_nam(mon));
X hittxt = TRUE;
X } else
X tmp = 1;
X
X mon->mhp -= tmp;
X if(mon->mhp < 1)
X destroyed = TRUE;
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 if(!mon->mtame) newsym(mon->mx, mon->my);
X mon->mflee = TRUE; /* Rick Richardson */
X mon->mfleetim += 10*rnd(tmp);
X }
X if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
X && obj && obj == uwep
X && objects[obj->otyp].oc_material == IRON
X && mon->mhp > 1 && !thrown && !mon->mcan
X /* && !destroyed -- guaranteed by mhp > 1 */ ) {
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 && !destroyed) {
X if(thrown)
X /* thrown => obj exists */
X hit(xname(obj), mon, exclam(tmp) );
X else if(!flags.verbose) You("hit it.");
X else You("hit %s%s", mon_nam(mon), canseemon(mon)
X ? exclam(tmp) : ".");
X }
X
X if (silvermsg) {
X if (canseemon(mon) || sensemon(mon))
X pline("The silver sears %s%s!",
X mon_nam(mon),
X noncorporeal(mdat) ? "" :
X (*(eos(mon_nam(mon))-1) == 's' ?
X "' flesh" : "'s flesh"));
X else
X pline("It%s is seared!",
X noncorporeal(mdat) ? "" : "s flesh");
X }
X
X if (needpoismsg)
X pline("The poison doesn't seem to affect %s.", mon_nam(mon));
X if (poiskilled) {
X pline("The poison was deadly...");
X xkilled(mon, 0);
X return FALSE;
X } else if (destroyed) {
X killed(mon); /* takes care of most messages */
X } else if(u.umconf && !thrown) {
X nohandglow(mon);
X if(!mon->mconf && !resist(mon, '+', 0, NOTELL)) {
X mon->mconf = 1;
X if(!mon->mstun && mon->mcanmove && !mon->msleep &&
X !Blind)
X pline("%s appears confused.", Monnam(mon));
X }
X }
X
X#if 0
X if(mdat == &mons[PM_RUST_MONSTER] && obj && obj == uwep &&
X is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
X if (obj->greased)
X grease_protect(obj,NULL,FALSE);
X else if (obj->oerodeproof || (obj->blessed && !rnl(4))) {
X if (flags.verbose)
X pline("Somehow, your %s is not affected.",
X is_sword(obj) ? "sword" : "weapon");
X } else {
X Your("%s%s!", aobjnam(obj, "rust"),
X obj->oeroded+1 == MAX_ERODE ? " completely" :
X obj->oeroded ? " further" : "");
X obj->oeroded++;
X }
X }
X#endif
X
X return(destroyed ? FALSE : TRUE);
X}
X
X#ifdef POLYSELF
X
Xint
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 if (is_demon(uasmon) && !rn2(13) && !uwep
X && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
X && u.umonnum != PM_BALROG) {
X struct monst *dtmp;
X pline("Some hell-p has arrived!");
X if((dtmp = makemon(!rn2(6) ? &mons[ndemon()] : uasmon, u.ux, u.uy)))
X (void)tamedog(dtmp, (struct obj *)0);
X exercise(A_WIS, TRUE);
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_HEAL:
X case AD_LEGS:
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 if(!Blind) pline("%s is on fire!", Monnam(mdef));
X tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
X tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
X if(resists_fire(pd)) {
X if (!Blind)
X pline("The fire doesn't heat %s!", mon_nam(mdef));
X golemeffects(mdef, AD_FIRE, tmp);
X shieldeff(mdef->mx, mdef->my);
X tmp = 0;
X }
X /* only potions damage resistant players in destroy_item */
X tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
X break;
X case AD_COLD:
X if(!Blind) pline("%s is covered in frost!", Monnam(mdef));
X if(resists_cold(pd)) {
X shieldeff(mdef->mx, mdef->my);
X if (!Blind)
X pline("The frost doesn't chill %s!", mon_nam(mdef));
X golemeffects(mdef, AD_COLD, tmp);
X tmp = 0;
X }
X tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
X break;
X case AD_ELEC:
X if (!Blind) pline("%s is zapped!", Monnam(mdef));
X tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
X if(resists_elec(pd)) {
X if (!Blind)
X pline("The zap doesn't shock %s!", mon_nam(mdef));
X golemeffects(mdef, AD_ELEC, tmp);
X shieldeff(mdef->mx, mdef->my);
X tmp = 0;
X }
X /* only rings damage resistant players in destroy_item */
X tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
X break;
X case AD_ACID:
X if(resists_acid(pd)) tmp = 0;
X break;
X case AD_STON:
X if(poly_when_stoned(pd))
X mon_to_stone(mdef);
X else 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, *stealoid;
X
X stealoid = (struct obj *)0;
X /* Without MUSE we can only change a monster's AC by stealing
X * armor with the "unarmored soldier" kludge. With it there
X * are many monsters which wear armor, and all can be stripped.
X */
X if(
X#ifndef MUSE
X is_mercenary(pd) &&
X#endif
X could_seduce(&youmonst,mdef,mattk)){
X for(otmp = mdef->minvent; otmp; otmp=otmp->nobj)
X#ifdef MUSE
X if (otmp->owornmask & W_ARM) stealoid = otmp;
X#else
X if (otmp->otyp >= PLATE_MAIL && otmp->otyp
X <= ELVEN_CLOAK) stealoid = otmp;
X#endif
X }
X if (stealoid) {
X boolean stolen = FALSE;
X /* Is "he"/"his" always correct? */
X if (gender(mdef) == u.mfemale &&
X uasmon->mlet == S_NYMPH)
X You("charm %s. She gladly hands over her possessions.", mon_nam(mdef));
X else
X You("seduce %s and %s starts to take off %s clothes.",
X mon_nam(mdef),
X gender(mdef) ? "she" : "he",
X gender(mdef) ? "her" : "his");
X while(mdef->minvent) {
X otmp = mdef->minvent;
X mdef->minvent = otmp->nobj;
X /* set dknown to insure proper merge */
X if (!Blind) otmp->dknown = 1;
X#ifdef MUSE
X otmp->owornmask = 0L;
X#endif
X if (!stolen && otmp==stealoid) {
X otmp = hold_another_object(otmp,
X (const char *)0, (const char *)0,
X (const char *)0);
X stealoid = otmp;
X stolen = TRUE;
X } else {
X otmp = hold_another_object(otmp,
X "You steal %s.", doname(otmp),
X "You steal: ");
X }
X }
X if (!stolen)
X impossible("Player steal fails!");
X else {
X pline("%s finishes taking off %s suit.",
X Monnam(mdef), gender(mdef) ? "her" : "his");
X You("steal %s!", doname(stealoid));
X# if defined(ARMY) && !defined(MUSE)
X mdef->data = &mons[PM_UNARMORED_SOLDIER];
X# endif
X }
X#ifdef MUSE
X possibly_unwield(mdef);
X mdef->misc_worn_check = 0L;
X#endif
X } else {
X otmp = mdef->minvent;
X mdef->minvent = otmp->nobj;
X otmp = hold_another_object(otmp, "You steal %s.",
X doname(otmp), "You steal: ");
X#ifdef MUSE
X possibly_unwield(mdef);
X otmp->owornmask = 0L;
X#endif
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 exercise(A_DEX, TRUE);
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 if (mdef->data == &mons[PM_CLAY_GOLEM]) {
X if (!Blind)
X pline("Some writing vanishes from %s head!",
X s_suffix(mon_nam(mdef)));
X xkilled(mdef, 0);
X return 2;
X }
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 pline("%s suddenly seems weaker!", Monnam(mdef));
X mdef->mhpmax -= xtmp;
X if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev--) {
X pline("%s dies!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
X }
X tmp = 0;
X break;
X case AD_RUST:
X if (pd == &mons[PM_IRON_GOLEM]) {
X pline("%s falls to pieces!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
X tmp = 0;
X break;
X case AD_DCAY:
X if (pd == &mons[PM_WOOD_GOLEM] ||
X pd == &mons[PM_LEATHER_GOLEM]) {
X pline("%s falls to pieces!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
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 pline("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_DRIN:
X if (!has_head(mdef->data)) {
X pline("%s doesn't seem harmed.", Monnam(mdef));
X tmp = 0;
X break;
X }
X#ifdef MUSE
X if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
X pline("%s helmet blocks your attack to %s head.",
X s_suffix(Monnam(mdef)),
X (Blind || !humanoid(mdef->data)) ? "its" :
X (mdef->female ? "her" : "his"));
X break;
X }
X#endif
X You("eat %s brain!", s_suffix(mon_nam(mdef)));
X if (mindless(mdef->data)) {
X pline("%s doesn't notice.", Monnam(mdef));
X break;
X }
X tmp += rnd(10);
X morehungry(-rnd(30)); /* cannot choke */
X if (ABASE(A_INT) < AMAX(A_INT)) {
X ABASE(A_INT) += rnd(4);
X if (ABASE(A_INT) > AMAX(A_INT))
X ABASE(A_INT) = AMAX(A_INT);
X flags.botl = 1;
X }
X exercise(A_WIS, TRUE);
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 case AD_PLYS:
X if (mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
X if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
X mdef->mcanmove = 0;
X mdef->mfrozen = rnd(10);
X }
X break;
X case AD_SLEE:
X if (!resists_sleep(mdef->data) && !mdef->msleep &&
X mdef->mcanmove) {
X if (!Blind)
X pline("%s suddenly falls asleep!", Monnam(mdef));
X mdef->mcanmove = 0;
X mdef->mfrozen = rnd(10);
X }
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 && !cansee(mdef->mx,mdef->my)) {
X You("feel embarrassed for a moment.");
X xkilled(mdef, 0);
X } else if (!flags.verbose) {
X You("destroy it!");
X xkilled(mdef, 0);
X } else
X killed(mdef);
X return(2);
X }
X return(1);
X}
X
Xstatic int
Xexplum(mdef, mattk)
Xregister struct monst *mdef;
Xregister struct attack *mattk;
X{
X register int tmp = d((int)mattk->damn, (int)mattk->damd);
X
X You("explode!");
X switch(mattk->adtyp) {
X case AD_BLND:
X if (haseyes(mdef->data)) {
X pline("%s is blinded by your flash of light!", Monnam(mdef));
X if (mdef->mcansee) {
X mdef->mblinded += tmp;
X mdef->mcansee = 0;
X }
X }
X break;
X case AD_COLD:
X if (!resists_cold(mdef->data)) {
X pline("%s gets blasted!", Monnam(mdef));
X mdef->mhp -= tmp;
X if (mdef->mhp <= 0) {
X killed(mdef);
X return(2);
X }
X } else {
X shieldeff(mdef->mx, mdef->my);
X if (is_golem(mdef->data))
X golemeffects(mdef, AD_COLD, tmp);
X else
X pline("The blast doesn't seem to affect %s.",
X mon_nam(mdef));
X }
X break;
X default:
X 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 if(mdef->data->msize >= MZ_HUGE) return 0;
X
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 You("engulf %s!", mon_nam(mdef));
X switch(mattk->adtyp) {
X case AD_DGST:
X u.uhunger += mdef->data->cnutrit;
X newuhs(FALSE);
X xkilled(mdef,2);
X Sprintf(msgbuf, "You totally digest %s.",
X mon_nam(mdef));
X if ((tmp = 3 + (mdef->data->cwt >> 6)) != 0) {
X You("digest %s.", mon_nam(mdef));
X nomul(-tmp);
X nomovemsg = msgbuf;
X } else pline(msgbuf);
X exercise(A_CON, TRUE);
X return(2);
X case AD_PHYS:
X pline("%s is pummeled with your debris!",Monnam(mdef));
X break;
X case AD_ACID:
X pline("%s is covered with your goo!", Monnam(mdef));
X if (resists_acid(mdef->data)) {
X pline("It seems harmless to %s.", mon_nam(mdef));
X dam = 0;
X }
X break;
X case AD_BLND:
X if(haseyes(mdef->data)) {
X if (mdef->mcansee)
X pline("%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 }
X dam = 0;
X break;
X case AD_ELEC:
X if (rn2(2)) {
X pline("The air around %s crackles with electricity.", mon_nam(mdef));
X if (resists_elec(mdef->data)) {
X pline("%s seems unhurt.", Monnam(mdef));
X dam = 0;
X }
X golemeffects(mdef,(int)mattk->adtyp,dam);
X } else dam = 0;
X break;
X case AD_COLD:
X if (rn2(2)) {
X if (resists_cold(mdef->data)) {
X pline("%s seems mildly chilly.", Monnam(mdef));
X dam = 0;
X } else
X pline("%s is freezing to death!",Monnam(mdef));
X golemeffects(mdef,(int)mattk->adtyp,dam);
X } else dam = 0;
X break;
X case AD_FIRE:
X if (rn2(2)) {
X if (resists_fire(mdef->data)) {
X pline("%s seems mildly hot.", Monnam(mdef));
X dam = 0;
X } else
X pline("%s is burning to a crisp!",Monnam(mdef));
X golemeffects(mdef,(int)mattk->adtyp,dam);
X } else dam = 0;
X break;
X }
X if ((mdef->mhp -= dam) <= 0) {
X killed(mdef);
X return(2);
X }
X You("%s %s!", is_animal(uasmon) ? "regurgitate"
X : "expel", mon_nam(mdef));
X if (is_animal(uasmon)) {
X pline("Obviously, you didn't like %s taste.",
X s_suffix(mon_nam(mdef)));
X }
X } else {
X You("bite into %s", mon_nam(mdef));
X You("turn to stone...");
X killer_format = KILLED_BY;
X killer = "swallowing a cockatrice whole";
X done(STONING);
X }
X }
X return(0);
X}
X
Xvoid
Xmissum(mdef,mattk)
Xregister struct monst *mdef;
Xregister struct attack *mattk;
X{
X if (could_seduce(&youmonst, mdef, mattk))
X You("pretend to be friendly to %s.", mon_nam(mdef));
X else if(!Blind && flags.verbose)
X You("miss %s.", mon_nam(mdef));
X else
X You("miss it.");
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#ifdef GCC_WARN
X dhit = 0;
X#endif
X
X for(i = 0; i < NATTK; i++) {
X
X sum[i] = 0;
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 > (dieroll = rnd(20)) || u.uswallow);
X /* Enemy dead, before any special abilities used */
X if (!known_hitum(mon,dhit)) return 0;
X /* might be a worm that gets cut in half */
X if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return(nsum);
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 break;
X case AT_CLAW:
X if (i==0 && uwep && !cantwield(uasmon)) goto use_weapon;
X# ifdef SEDUCE
X /* succubi/incubi are humanoid, but their _second_
X * attack is AT_CLAW, not their first...
X */
X if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
X u.umonnum == PM_INCUBUS)) goto use_weapon;
X# endif
X case AT_KICK:
X case AT_BITE:
X case AT_STNG:
X case AT_TUCH:
X case AT_BUTT:
X case AT_TENT:
X if (i==0 && uwep && (u.usym==S_LICH)) goto use_weapon;
X if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
X int compat;
X
X if (!u.uswallow &&
X (compat=could_seduce(&youmonst, mon, mattk))) {
X You("%s %s %s.",
X mon->mcansee && haseyes(mon->data)
X ? "smile at" : "talk to",
X mon_nam(mon),
X compat == 2 ? "engagingly":"seductively");
X /* doesn't anger it; no wakeup() */
X sum[i] = damageum(mon, mattk);
X break;
X }
X wakeup(mon);
X if (mon->data == &mons[PM_SHADE]) {
X Your("attack passes harmlessly through %s.",
X mon_nam(mon));
X break;
X }
X if (mattk->aatyp == AT_KICK)
X You("kick %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_BITE)
X You("bite %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_STNG)
X You("sting %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_BUTT)
X You("butt %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_TUCH)
X You("touch %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_TENT)
X Your("tentacles suck %s.", mon_nam(mon));
X else You("hit %s.", mon_nam(mon));
X sum[i] = damageum(mon, mattk);
X } else
X missum(mon, mattk);
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 wakeup(mon);
X if (mon->data == &mons[PM_SHADE])
X Your("hug passes harmlessly through %s.",
X mon_nam(mon));
X else if (!sticks(mon->data))
X if (mon==u.ustuck) {
X pline("%s is being %s.", Monnam(mon),
X u.umonnum==PM_ROPE_GOLEM ? "choked":
X "crushed");
X sum[i] = damageum(mon, mattk);
X } else if(sum[i-1] && sum[i-2]) {
X You("grab %s!", mon_nam(mon));
X u.ustuck = mon;
X sum[i] = damageum(mon, mattk);
X }
X break;
X
X case AT_EXPL: /* automatic hit if next to */
X dhit = -1;
X wakeup(mon);
X sum[i] = explum(mon, mattk);
X break;
X
X case AT_ENGL:
X if((dhit = (tmp > rnd(20+i)))) {
X wakeup(mon);
X if (mon->data == &mons[PM_SHADE])
X Your("attempt to surround %s is harmless.",
X mon_nam(mon));
X else
X sum[i]= gulpum(mon,mattk);
X } else
X missum(mon, mattk);
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 continue;
X /* Not break--avoid passive attacks from enemy */
X
X case AT_BREA:
X case AT_SPIT:
X case AT_GAZE: /* all done using #monster command */
X dhit = 0;
X break;
X
X default: /* Strange... */
X impossible("strange attack of yours (%d)",
X mattk->aatyp);
X }
X if (dhit == -1)
X rehumanize();
X if(sum[i] == 2) return(passive(mon, 1, 0, (mattk->aatyp==AT_KICK)));
X /* defender dead */
X else {
X (void) passive(mon, sum[i], 1, (mattk->aatyp==AT_KICK));
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 /* POLYSELF */
X
X/* Special (passive) attacks on you by monsters done here. */
X
Xint
Xpassive(mon, mhit, malive, kicked)
Xregister struct monst *mon;
Xregister boolean mhit;
Xregister int malive;
Xboolean kicked;
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 /* Note: tmp not always used */
X if (ptr->mattk[i].damn)
X tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
X else if(ptr->mattk[i].damd)
X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
X else
X tmp = 0;
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 acid!",
X s_suffix(mon_nam(mon)));
X
X#ifdef POLYSELF
X if(!resists_acid(uasmon))
X#endif
X mdamageu(mon, tmp);
X if(!rn2(30)) erode_armor(TRUE);
X }
X if(mhit && !rn2(6)) {
X if (kicked) {
X if (uarmf)
X (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE);
X } else erode_weapon(TRUE);
X }
X exercise(A_STR, FALSE);
X break;
X case AD_STON:
X if(mhit)
X if (!kicked)
X if (!uwep && !uarmg
X#ifdef POLYSELF
X && !resists_ston(uasmon)
X && !(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
X#endif
X ) {
X You("turn to stone...");
X done_in_by(mon);
X return 2;
X }
X break;
X case AD_RUST:
X if(mhit && !mon->mcan)
X if (kicked) {
X if (uarmf)
X (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE);
X } else
X erode_weapon(FALSE);
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 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:
X if(ptr == &mons[PM_FLOATING_EYE]) {
X if (!canseemon(mon)) {
X break;
X }
X if(mon->mcansee) {
X if(Reflecting & W_AMUL) {
X makeknown(AMULET_OF_REFLECTION);
X pline("%s gaze is reflected by your medallion.",
X s_suffix(Monnam(mon)));
X } else if(Reflecting & W_ARMS) {
X makeknown(SHIELD_OF_REFLECTION);
X pline("%s gaze is reflected by your shield.",
X s_suffix(Monnam(mon)));
X } else {
X You("are frozen by %s gaze!",
X s_suffix(mon_nam(mon)));
X nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -120);
X }
X } else {
X pline("%s cannot defend itself.",
X Adjmonnam(mon,"blind"));
X if(!rn2(500)) change_luck(-1);
X }
X } else { /* gelatinous cube */
X You("are frozen by %s!", mon_nam(mon));
X nomul(-tmp);
X exercise(A_DEX, FALSE);
X }
X break;
X case AD_COLD: /* brown mold or blue jelly */
X if(monnear(mon, u.ux, u.uy)) {
X if(Cold_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel a mild chill.");
X#ifdef POLYSELF
X ugolemeffects(AD_COLD, tmp);
X#endif
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 > ((int) (mon->m_lev+1) * 8)) {
X register struct monst *mtmp;
X
X if ((mtmp = clone_mon(mon)) != 0) {
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)tmp, TRUE);
X break;
X case AD_FIRE:
X if(monnear(mon, u.ux, u.uy)) {
X if(Fire_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel mildly warm.");
X#ifdef POLYSELF
X ugolemeffects(AD_FIRE, tmp);
X#endif
X break;
X }
X You("are suddenly very hot!");
X mdamageu(mon, tmp);
X }
X break;
X case AD_ELEC:
X if(Shock_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel a mild tingle.");
X#ifdef POLYSELF
X ugolemeffects(AD_ELEC, tmp);
X#endif
X break;
X }
X You("are jolted with electricity!");
X mdamageu(mon, tmp);
X break;
X default:
X break;
X }
X }
X return(malive | mhit);
X}
X
X/* Note: caller must ascertain mtmp is mimicing... */
Xvoid
Xstumble_onto_mimic(mtmp)
Xregister struct monst *mtmp;
X{
X if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
X u.ustuck = mtmp;
X if (Blind) {
X if(!Telepat)
X pline("Wait! That's a monster!");
X } else if (glyph_is_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
X (glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_hcdoor ||
X glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_vcdoor))
X pline("The door actually was %s!", a_monnam(mtmp));
X else if (glyph_is_object(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
X glyph_to_obj(levl[u.ux+u.dx][u.uy+u.dy].glyph) == GOLD_PIECE)
X pline("That gold was %s!", a_monnam(mtmp));
X else {
X pline("Wait! That's %s!", a_monnam(mtmp));
X }
X
X wakeup(mtmp); /* clears mimicing */
X}
X
Xstatic void
Xnohandglow(mon)
Xstruct monst *mon;
X{
X char *hands=makeplural(body_part(HAND));
X
X if (!u.umconf || mon->mconf) return;
X if (u.umconf == 1) {
X if (Blind)
X Your("%s stop tingling.", hands);
X else
X Your("%s stop glowing %s.", hands,
X Hallucination ? hcolor() : red);
X } else {
X if (Blind)
X pline("The tingling in your %s lessens.", hands);
X else
X Your("%s no longer glow so brightly %s.", hands,
X Hallucination ? hcolor() : red);
X }
X u.umconf--;
X}
X
X/*uhitm.c*/
END_OF_FILE
if test 44975 -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 19 \(of 108\).
cp /dev/null ark19isdone
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 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone 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