billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 56
Archive-name: nethack3p9/Part11
Supersedes: NetHack3: Volume 7, Issue 56-93
#! /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 11 (of 56)."
# Contents: src/pickup.c src/uhitm.c
# Wrapped by billr@saab on Wed Jul 11 17:11:05 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/pickup.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/pickup.c'\"
else
echo shar: Extracting \"'src/pickup.c'\" \(16041 characters\)
sed "s/^X//" >'src/pickup.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)pickup.c 3.0 88/07/12
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X/*
X * Contains code for picking objects up, and container use.
X */
X
X#include "hack.h"
XSTATIC_PTR int FDECL(in_container,(struct obj *));
XSTATIC_PTR int FDECL(ck_container,(struct obj *));
XSTATIC_PTR int FDECL(ck_bag,(struct obj *));
XSTATIC_PTR int FDECL(out_container,(struct obj *));
Xvoid FDECL(explode_bag,(struct obj *));
X
X#define DELTA_CWT(cont) ((cont)->cursed?(obj->owt*2):(obj->owt/((cont)->blessed?4:2)) + 1)
X
X#ifdef OVL0
X
Xstatic const char nearloadmsg[] = "have a little trouble lifting";
X
Xvoid
Xpickup(all)
Xint all;
X{
X register struct gold *gold = g_at(u.ux, u.uy);
X register struct obj *obj, *obj2;
X register int wt;
X char buf[BUFSZ];
X register char *ip;
X register char sym;
X register int oletct = 0, iletct = 0;
X boolean all_of_a_type = FALSE, selective = FALSE;
X char olets[20], ilets[20];
X struct obj dummygold;
X
X dummygold.ox = u.ux;
X dummygold.oy = u.uy;
X dummygold.olet = GOLD_SYM;
X dummygold.nobj = fobj;
X dummygold.nexthere = level.objects[u.ux][u.uy];
X dummygold.cobj = 0;
X
X if(Levitation) {
X if ((multi && !flags.run) || (all && !flags.pickup))
X read_engr_at(u.ux,u.uy);
X return;
X }
X /* multi && !flags.run means they are in the middle of some other
X * action, or possibly paralyzed, sleeping, etc.... and they just
X * teleported onto the object. They shouldn't pick it up.
X */
X if ((multi && !flags.run) || (all && !flags.pickup)) {
X int ct = 0;
X
X for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
X if(!obj->cobj && obj != uchain)
X ct++;
X
X /* Stop on a zorkmid */
X if (gold) ct++;
X
X /* If there are objects here, take a look.
X */
X if (ct) {
X if (flags.run)
X nomul(0);
X nscr();
X if (ct < 5)
X (void) dolook();
X else {
X read_engr_at(u.ux,u.uy);
X pline("There are several objects here.");
X }
X } else read_engr_at(u.ux,u.uy);
X return;
X }
X
X /* check for more than one object */
X if(!all) {
X register int ct = 0;
X
X if (gold) ct++;
X for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
X if(!obj->cobj) ct++;
X if(ct < 2)
X all++;
X else
X pline("There are several objects here.");
X }
X
X /* added by GAN 10/24/86 to allow selective picking up */
X if(!all) {
X register struct obj *otmp = level.objects[u.ux][u.uy];
X
X ilets[iletct] = 0;
X if(gold) {
X ilets[iletct++] = GOLD_SYM;
X ilets[iletct] = 0;
X }
X while(otmp) {
X if(!index(ilets, otmp->olet) && !otmp->cobj) {
X ilets[iletct++] = otmp->olet;
X ilets[iletct] = 0;
X }
X otmp = otmp->nexthere;
X }
X if(iletct == 1)
X Strcpy(buf,ilets);
X else {
X ilets[iletct++] = ' ';
X ilets[iletct++] = 'a';
X ilets[iletct++] = 'A';
X ilets[iletct] = 0;
X
X pline("What kinds of thing do you want to pick up? [%s] ", ilets);
X getlin(buf);
X if(buf[0] == '\033') {
X clrlin();
X return;
X }
X else if(!buf[0]) selective = TRUE;
X }
X ip = buf;
X olets[0] = 0;
X while(sym = *ip++){
X /* new A function (selective all) added by
X * GAN 01/09/87
X */
X if(sym == ' ') continue;
X if(sym == 'A') selective = TRUE;
X else if(sym == 'a') all_of_a_type = TRUE;
X else if(index(ilets, sym)){
X if(!index(olets, sym)){
X olets[oletct++] = sym;
X olets[oletct] = 0;
X }
X }
X else pline("There are no %c's here.", sym);
X }
X }
X if(all_of_a_type && !olets[0]) all = TRUE;
X
X for(obj = (gold ? &dummygold : level.objects[u.ux][u.uy]); obj;
X obj = obj2) {
X obj2 = obj->nexthere; /* perhaps obj will be picked up */
X if(!obj->cobj) {
X if(flags.run) nomul(0);
X
X if(!all) {
X char c;
X
X if(!selective && !index(olets,obj->olet)) continue;
X
X if (!all_of_a_type) {
X if (obj == &dummygold)
X pline("Pick up %ld gold piece%s? ",
X gold->amount, plur(gold->amount));
X else pline("Pick up %s? ", doname(obj));
X if((c = ynaq()) == 'q') return;
X if(c == 'n') continue;
X if(c == 'a') {
X all_of_a_type = TRUE;
X if (selective) {
X selective = FALSE;
X olets[0] = obj->olet;
X olets[1] = 0;
X /* oletct = 1; */
X }
X }
X }
X }
X
X if(obj == &dummygold) {
X int iw = inv_weight();
X long gold_capacity;
X
X#ifndef lint /* long/int conversion */
X iw -= (int)((u.ugold + 500)/1000);
X#endif
X gold_capacity = ((-iw) * 1000L) - 500 + 999 - u.ugold;
X if (gold_capacity <= 0L) {
X pline("There %s %ld gold piece%s here, but you cannot carry any more.",
X (gold->amount == 1) ? "is" : "are",
X gold->amount, plur(gold->amount));
X continue;
X }
X if (gold_capacity >= gold->amount) {
X u.ugold += gold->amount;
X if (inv_weight() > -5)
X You(nearloadmsg);
X pline("%ld gold piece%s.",
X gold->amount, plur(gold->amount));
X freegold(gold);
X if(Invisible) newsym(u.ux,u.uy);
X } else {
X You("can only carry %s of the %ld gold pieces lying here.",
X gold_capacity == 1L ? "one" : "some", gold->amount);
X You(nearloadmsg);
X pline("%ld gold piece%s.",
X gold_capacity, plur(gold_capacity));
X u.ugold += gold_capacity;
X gold->amount -= gold_capacity;
X }
X flags.botl = 1;
X if(flags.run) nomul(0);
X continue;
X }
X
X if((obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE) &&
X !uarmg
X#ifdef POLYSELF
X && !resists_ston(uasmon)
X#endif
X ) {
X pline("Touching the dead cockatrice is a fatal mistake.");
X You("turn to stone.");
X You("die...");
X killer_format = KILLED_BY_AN;
X killer = "cockatrice corpse";
X done(STONING);
X }
X
X if(obj->otyp == SCR_SCARE_MONSTER){
X if(obj->blessed) obj->blessed = 0;
X else if(!obj->spe && !obj->cursed) obj->spe = 1;
X else {
X pline("The scroll%s turn%s to dust as you pick %s up.",
X plur((long)obj->quan), (obj->quan==1) ? "s":"",
X (obj->quan==1) ? "it" : "them");
X if(!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
X !(objects[SCR_SCARE_MONSTER].oc_uname))
X docall(obj);
X useupf(obj);
X continue;
X }
X }
X
X /* do not pick up uchain */
X if(obj == uchain)
X continue;
X
X wt = inv_weight() + (int)obj->owt;
X if (obj->otyp == LOADSTONE)
X goto lift_some; /* pick it up even if too heavy */
X#ifdef POLYSELF
X if (obj->otyp == BOULDER && throws_rocks(uasmon)) {
X wt = inv_weight();
X goto lift_some;
X }
X#endif
X if(wt > 0) {
X if(obj->quan > 1) {
X /* see how many we can lift */
X unsigned savequan = obj->quan;
X int iw = inv_weight();
X unsigned qq;
X for(qq = 1; qq < savequan; qq++){
X obj->quan = qq;
X if(iw + weight(obj) > 0)
X break;
X }
X obj->quan = savequan;
X qq--;
X /* we can carry qq of them */
X if(qq) {
X register struct obj *obj3;
X
X You("can only carry %s of the %s lying here.",
X (qq == 1) ? "one" : "some",
X doname(obj));
X obj3 = splitobj(obj, (int)qq);
X if(obj3->otyp == SCR_SCARE_MONSTER)
X if(obj3->spe) obj->spe = 0;
X goto lift_some;
X }
X }
X pline("There %s %s here, but %s.",
X (obj->quan == 1) ? "is" : "are",
X doname(obj),
X !invent ? "it is too heavy for you to lift"
X : "you cannot carry any more");
X if(obj->otyp == SCR_SCARE_MONSTER)
X if(obj->spe) obj->spe = 0;
X break;
X }
X lift_some:
X if(inv_cnt() >= 52) {
X Your("knapsack cannot accommodate any more items.");
X if(obj->otyp == SCR_SCARE_MONSTER)
X if(obj->spe) obj->spe = 0;
X break;
X }
X { unsigned pickquan = obj->quan;
X unsigned mergquan;
X
X obj = pick_obj(obj);
X if(wt > -5) You(nearloadmsg);
X if(!Blind) obj->dknown = 1;
X mergquan = obj->quan;
X obj->quan = pickquan; /* to fool prinv() */
X if(uwep && uwep == obj) mrg_to_wielded = TRUE;
X prinv(obj);
X mrg_to_wielded = FALSE;
X obj->quan = mergquan;
X }
X }
X }
X}
X
Xstruct obj *
Xpick_obj(otmp)
Xregister struct obj *otmp;
X{
X if (otmp != uball) /* don't charge for this - kd, 1/17/90 */
X addtobill(otmp, TRUE); /* sets obj->unpaid if necessary */
X freeobj(otmp);
X if(Invisible) newsym(u.ux,u.uy);
X return(addinv(otmp)); /* might merge it with other objects */
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xint
Xdoloot() { /* loot a container on the floor. */
X
X register struct obj *cobj, *nobj;
X register int c;
X
X if (Levitation) {
X You("cannot reach the floor.");
X return(0);
X }
X for(cobj = level.objects[u.ux][u.uy]; cobj; cobj = nobj) {
X nobj = cobj->nexthere;
X
X if(Is_container(cobj)) {
X
X pline("There is %s here, loot it? ", doname(cobj));
X c = ynq();
X if(c == 'q') return 0;
X if(c == 'n') continue;
X
X if(cobj->olocked) {
X
X pline("Hmmm, it seems to be locked.");
X continue;
X }
X if(cobj->otyp == BAG_OF_TRICKS) {
X
X You("carefully open the bag...");
X pline("It develops a huge set of teeth and bites you!");
X losehp(rnd(10), "carnivorous bag", KILLED_BY_AN);
X makeknown(BAG_OF_TRICKS);
X continue;
X }
X
X You("carefully open the %s...", xname(cobj));
X if(cobj->otrapped && chest_trap(cobj, FINGER)) /* don't use obj if obj dies */
X continue;
X if(multi < 0) return 0; /* a paralysis trap */
X
X use_container(cobj, 0);
X }
X }
X return 0;
X}
X
Xstatic
Xstruct obj NEARDATA *current_container; /* a local variable of use_container, to be
X used by its local procedures in/ck_container */
X#define Icebox (current_container->otyp == ICE_BOX)
Xint baggone; /* used in askchain so bag isn't used after explosion */
X
X#endif /* OVLB */
X#ifdef OVL1
X
Xvoid
Xinc_cwt(cobj, obj)
Xregister struct obj *cobj, *obj;
X{
X if (cobj->otyp == BAG_OF_HOLDING)
X cobj->owt += DELTA_CWT(cobj);
X else cobj->owt += obj->owt;
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
XSTATIC_PTR int
Xin_container(obj)
Xregister struct obj *obj;
X{
X char buf[BUFSZ];
X
X if(obj == uball || obj == uchain) {
X You("must be kidding.");
X return(0);
X }
X if(obj == current_container) {
X pline("That would be an interesting topological exercise.");
X return(0);
X }
X if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
X You("cannot %s something you are wearing.",
X Icebox ? "refrigerate" : "stash");
X return(0);
X }
X if((obj->otyp == LOADSTONE) && obj->cursed) {
X obj->bknown = 1;
X pline("The stone%s won't leave your person.",
X plur((long)obj->quan));
X return(0);
X }
X /* Prohibit Amulets in containers; if you allow it, monsters can't
X * steal them. It also becomes a pain to check to see if someone
X * has the Amulet.
X */
X if(obj->otyp == AMULET_OF_YENDOR && !obj->spe) {
X pline("The Amulet of Yendor cannot be confined in such trappings.");
X return(0);
X }
X /* no nested containers - they do not save/restore properly. */
X /* magic bag -> magic bag will self destruct later on. */
X if(Is_container(obj) && Is_container(current_container) &&
X (!Is_mbag(obj) || !Is_mbag(current_container))) {
X pline("The %s won't go in.", xname(obj));
X return(1); /* be careful! */
X }
X if(obj == uwep) {
X if(welded(obj)) {
X weldmsg(obj, FALSE);
X return(0);
X }
X setuwep((struct obj *) 0);
X if (uwep) return(0); /* unwielded, died, rewielded */
X }
X#ifdef WALKIES
X if(obj->otyp == LEASH && obj->leashmon != 0) {
X pline("The %s is attached to your pet.", xname(obj));
X return(0);
X }
X#endif
X inc_cwt(current_container, obj);
X freeinv(obj);
X
X obj->cobj = current_container;
X obj->nobj = fcobj;
X fcobj = obj;
X Strcpy(buf, xname(obj->cobj));
X You("put %s into the %s.", doname(obj), buf);
X
X if(Icebox) obj->age = monstermoves - obj->age; /* actual age */
X
X else if(Is_mbag(obj->cobj) &&
X (Is_mbag(obj) ||
X (obj->otyp == WAN_CANCELLATION && (obj->spe > 0)) )) {
X explode_bag(obj);
X You("are blasted by a magical explosion!");
X losehp(d(6,6),"magical explosion", KILLED_BY_AN);
X baggone = 1;
X }
X return(1);
X}
X
XSTATIC_PTR int
Xck_container(obj)
Xregister struct obj *obj;
X{
X return(obj->cobj == current_container);
X}
X
X/* ck_bag() needs a formal argument to make the overlay/prototype mechanism
X * work right */
X/*ARGSUSED*/
XSTATIC_PTR int
Xck_bag(obj)
Xstruct obj *obj;
X{
X return(!baggone);
X}
X
XSTATIC_PTR int
Xout_container(obj)
Xregister struct obj *obj;
X{
X register struct obj *otmp, *ootmp;
X register boolean near_capacity = (inv_weight() > -5);
X
X if(inv_cnt() >= 52) {
X pline("You have no room to hold anything else.");
X return(0);
X }
X if(obj->otyp != LOADSTONE && inv_weight() + (int)obj->owt -
X (carried(current_container) ?
X (current_container->otyp == BAG_OF_HOLDING ?
X (int)DELTA_CWT(current_container) : (int)obj->owt) : 0) > 0) {
X char buf[BUFSZ];
X
X Strcpy(buf, doname(obj));
X pline("There %s %s in the %s, but %s.",
X obj->quan==1 ? "is" : "are",
X buf, xname(current_container),
X invent ? "you cannot carry any more"
X : "it is too heavy for you to carry");
X /* "too heavy for you to lift" is not right if you're carrying
X the container... */
X return(0);
X }
X if(obj == fcobj) fcobj = fcobj->nobj;
X else {
X for(otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj)
X if(!otmp->nobj) panic("out_container");
X otmp->nobj = obj->nobj;
X }
X dec_cwt(current_container, obj);
X obj->cobj = (struct obj *) 0;
X
X if (Icebox) obj->age = monstermoves - obj->age;
X /* simulated point of time */
X
X ootmp = addinv(obj);
X if (near_capacity) You("have a little trouble removing");
X prinv(ootmp);
X return 0;
X}
X
X/* for getobj: 0: allow cnt; #: allow all types; %: expect food */
Xstatic const char NEARDATA frozen_food[] = { '0', '#', FOOD_SYM, 0 };
X
Xvoid
Xuse_container(obj, held)
Xregister struct obj *obj;
Xregister int held;
X{
X register int cnt = 0;
X register struct obj *otmp;
X register struct obj *backobj;
X
X current_container = obj; /* for use by in/out_container */
X if(current_container->olocked) {
X pline("The %s seems to be locked.", xname(current_container));
X return;
X }
X for(otmp = fcobj, backobj = (struct obj *) 0; otmp;
X backobj = otmp, otmp = otmp->nobj)
X if(otmp->cobj == obj)
X if(Is_mbag(obj) && obj->cursed && !rn2(13)) {
X if (otmp->known)
X pline("The %s to have vanished!",
X aobjnam(otmp,"seem"));
X else You("%s %s disappear.",
X Blind ? "notice" : "see",
X doname(otmp));
X if(!backobj) {
X fcobj = otmp->nobj;
X dec_cwt(current_container, otmp);
X obfree(otmp, (struct obj *) 0);
X otmp = fcobj;
X } else {
X backobj->nobj = otmp->nobj;
X dec_cwt(current_container, otmp);
X obfree(otmp, (struct obj *) 0);
X otmp = backobj->nobj;
X }
X if (!otmp) break;
X if(otmp->cobj == obj) cnt++;
X } else cnt++;
X if(!cnt)
X pline("%s %s is empty.", (held) ? "Your" : "The", xname(obj));
X else if (inv_cnt() < 52) {
X pline("Do you want to take something out of the %s? ",
X xname(obj));
X if(yn() != 'n')
X if(askchain(fcobj, FALSE, NULL, 0, out_container, ck_container, 0, "nodot"))
X return;
X }
X if(!invent) return;
X pline("Do you wish to put something in? ");
X if(yn() != 'y') return;
X if (Icebox && current_container->dknown) {
X otmp = getobj(frozen_food, "put in");
X if(!otmp || !in_container(otmp))
X flags.move = multi = 0;
X } else {
X baggone = 0; /* might be set by in_container */
X if(askchain(invent, TRUE, NULL, 0, in_container, ck_bag, 0, "nodot"))
X return;
X }
X return;
X}
X
Xvoid
Xdelete_contents(obj)
Xregister struct obj *obj;
X{
X register struct obj *otmp, *notmp;
X
X while (fcobj && fcobj->cobj == obj) {
X otmp = fcobj;
X fcobj = fcobj->nobj;
X obfree(otmp,(struct obj *)0);
X }
X if (fcobj) {
X otmp = fcobj;
X while(otmp->nobj)
X if (otmp->nobj->cobj == obj) {
X notmp = otmp->nobj;
X otmp->nobj = notmp->nobj;
X obfree(notmp,(struct obj *)0);
X } else
X otmp = otmp->nobj;
X }
X}
X
Xvoid
Xexplode_bag(obj)
Xstruct obj *obj;
X{
X struct obj *otmp, *cobj;
X
X cobj = obj->cobj;
X delete_contents(cobj);
X
X for (otmp = invent; otmp; otmp = otmp->nobj)
X if (otmp == cobj) break;
X
X if (otmp) {
X You("see your %s blow apart!", xname(otmp));
X useup(otmp);
X /*return(0);*/
X } else panic("explode_bag: bag not in invent.");
X}
X
Xvoid
Xdec_cwt(cobj, obj)
Xregister struct obj *cobj, *obj;
X{
X if (cobj->otyp == BAG_OF_HOLDING)
X cobj->owt -= DELTA_CWT(cobj);
X else cobj->owt -= obj->owt;
X
X if(cobj->owt < objects[cobj->otyp].oc_weight)
X cobj->owt = objects[cobj->otyp].oc_weight;
X}
X
X#endif /* OVLB */
END_OF_FILE
if test 16041 -ne `wc -c <'src/pickup.c'`; then
echo shar: \"'src/pickup.c'\" unpacked with wrong size!
fi
# end of 'src/pickup.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'\" \(39521 characters\)
sed "s/^X//" >'src/uhitm.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)uhitm.c 3.0 89/11/27
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#ifdef NAMED_ITEMS
X# include "artifact.h"
X#endif
X
Xstatic boolean 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
X#ifdef WORM
Xextern boolean notonhead;
X#endif
X
Xstruct monst *
Xclone_mon(mon)
Xstruct monst *mon;
X{
X coord mm;
X struct monst *m2;
X
X mm.x = mon->mx;
X mm.y = mon->my;
X 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 m2 = newmonst(0);
X *m2 = *mon; /* copy condition of old monster */
X m2->nmon = fmon;
X fmon = m2;
X m2->m_id = flags.ident++;
X m2->mx = mm.x;
X m2->my = mm.y;
X
X m2->minvent = (struct obj *) 0; /* objects don't clone */
X m2->mleashed = FALSE;
X m2->mgold = 0L;
X /* Max HP the same, but current HP halved for both. The caller
X * might want to override this by halving the max HP also.
X */
X m2->mhpmax = mon->mhpmax;
X m2->mhp = mon->mhp /= 2;
X
X /* since shopkeepers and guards will only be cloned if they've been
X * polymorphed away from their original forms, the clone doesn't have
X * room for the extra information. we also don't want two shopkeepers
X * around for the same shop.
X * similarly, clones of named monsters don't have room for the name,
X * so we just make the clone unnamed instead of bothering to create
X * a clone with room and copying over the name from the right place
X * (which changes if the original was a shopkeeper or guard).
X */
X if (mon->isshk) m2->isshk = FALSE;
X if (mon->isgd) m2->isgd = FALSE;
X#if defined(ALTARS) && defined(THEOLOGY)
X if (mon->ispriest) m2->ispriest = FALSE;
X#endif
X m2->mxlth = 0;
X m2->mnamelth = 0;
X m2->mdispl = 0;
X pmon(m2); /* display the new monster */
X place_monster(m2, m2->mx, m2->my);
X if (mon->mtame) {
X struct monst *m3;
X
X if (m3 = tamedog(m2, (struct obj *)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 if (flags.confirm && (mtmp->mpeaceful || mtmp->mtame) && !Confusion
X && !Hallucination && (!mtmp->mhide || !mtmp->mundetected)
X && (!mtmp->mimic || Protection_from_shape_changers)) {
X if (Blind ? Telepat : (!mtmp->minvis || See_invisible)) {
X#ifdef MACOS
X char mac_tbuf[80];
X if(!flags.silent) SysBeep(1);
X Sprintf(mac_tbuf, "Really attack %s?", mon_nam(mtmp));
X if(UseMacAlertText(128, mac_tbuf) != 1) {
X#else
X pline("Really attack %s? ", mon_nam(mtmp));
X (void) fflush(stdout);
X if (yn() != 'y') {
X#endif
X flags.move = 0;
X return(TRUE);
X }
X }
X }
X
X if(mtmp->mimic && !Protection_from_shape_changers) {
X stumble_onto_mimic(mtmp);
X return(TRUE);
X }
X
X if(mtmp->mhide && mtmp->mundetected && !canseemon(mtmp)) {
X mtmp->mundetected = 0;
X if (!(Blind ? Telepat : (HTelepat & WORN_HELMET))) {
X register struct obj *obj;
X
X if(Blind) pline("Wait! There's a hidden monster there!");
X else if(OBJ_AT(mtmp->mx, mtmp->my)) {
X if(obj = level.objects[mtmp->mx][mtmp->my])
X pline("Wait! There's %s hiding under %s!",
X defmonnam(mtmp), doname(obj));
X } else if (levl[mtmp->mx][mtmp->my].gmask == 1)
X pline("Wait! There's %s hiding under some gold!",
X defmonnam(mtmp));
X wakeup(mtmp);
X return(TRUE);
X }
X }
X return(FALSE);
X}
X
Xschar
Xfind_roll_to_hit(mtmp)
Xregister struct monst *mtmp;
X{
X schar tmp;
X struct permonst *mdat = mtmp->data;
X
X#ifdef POLYSELF
X tmp = Luck + mdat->ac + abon() +
X ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel);
X#else
X tmp = Luck + u.ulevel + mdat->ac + abon();
X#endif
X/* it is unchivalrous to attack the defenseless or from behind */
X if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL &&
X (!mtmp->mcanmove || mtmp->msleep || mtmp->mflee) &&
X u.ualign > -10) adjalign(-1);
X
X/* Adjust vs. (and possibly modify) monster state. */
X
X if(mtmp->mstun) tmp += 2;
X if(mtmp->mflee) tmp += 2;
X
X if(mtmp->msleep) {
X mtmp->msleep = 0;
X tmp += 2;
X }
X if(!mtmp->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 tmp -= (inv_weight() + 40)/20;
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 = 0;
X register struct permonst *mdat = mtmp->data;
X
X if(unweapon) {
X unweapon=FALSE;
X if(flags.verbose)
X if(uwep)
X You("begin bashing monsters with your %s.",
X aobjnam(uwep, NULL));
X else
X#ifdef POLYSELF
X if (!cantwield(uasmon))
X#endif
X You("begin bashing monsters with your %s hands.",
X uarmg ? "gloved" : "bare"); /* Del Lamb */
X }
X /* andrew@orca: prevent unlimited pick-axe attacks */
X u_wipe_engr(3);
X
X if(mdat->mlet == S_LEPRECHAUN && mtmp->mfrozen && !mtmp->msleep &&
X !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
X (m_move(mtmp, 0) == 2 || /* he died */
X mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* he moved */
X return(FALSE);
X
X /* This section of code provides protection against accidentally
X * hitting peaceful (like '@') and tame (like 'd') monsters.
X * There is protection only if you're not blind, confused, or hallu-
X * cinating.
X */
X /* changes by wwp 5/16/85 */
X if (!Confusion && !Hallucination && flags.safe_dog &&
X (Blind ? Telepat : (!mtmp->minvis || See_invisible)) &&
X mtmp->mtame) {
X mtmp->mflee = 1;
X mtmp->mfleetim = rnd(6);
X if (mtmp->mnamelth)
X You("stop to avoid hitting %s.", NAME(mtmp));
X else
X You("stop to avoid hitting your %s.",
X mdat->mname);
X return(TRUE);
X }
X
X /* moved code to a separate function to share with dokick */
X if(special_case(mtmp)) return(TRUE);
X
X#ifdef POLYSELF
X if(u.umonnum >= 0) { /* certain "pacifist" monsters don't attack */
X set_uasmon();
X if(noattacks(uasmon)) {
X You("have no way to attack monsters physically.");
X return(TRUE);
X }
X }
X#endif
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 return(TRUE);
X}
X
Xstatic boolean
Xknown_hitum(mon, mhit) /* returns TRUE if monster still lives */
X/* Made into a separate function because in some cases we want to know
X * in the calling function whether we hit.
X */
Xregister struct monst *mon;
Xregister int mhit;
X{
X register boolean malive = TRUE;
X
X stoned = FALSE; /* this refers to the thing hit, not you */
X
X if(!mhit) {
X if(!Blind && flags.verbose) You("miss %s.", mon_nam(mon));
X else You("miss it.");
X if(!mon->msleep && mon->mcanmove)
X wakeup(mon);
X } else {
X /* we hit the monster; be careful: it might die! */
X
X#ifdef WORM
X if (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy)
X notonhead = TRUE;
X#endif
X if((malive = hmon(mon, uwep, 0)) == TRUE) {
X /* monster still alive */
X if(!rn2(25) && mon->mhp < mon->mhpmax/2) {
X mon->mflee = 1;
X if(!rn2(3)) mon->mfleetim = rnd(100);
X if(u.ustuck == mon && !u.uswallow
X#ifdef POLYSELF
X && !sticks(uasmon)
X#endif
X )
X u.ustuck = 0;
X }
X#ifdef WORM
X if(mon->wormno)
X cutworm(mon, u.ux+u.dx, u.uy+u.dy,
X uwep ? uwep->otyp : 0);
X#endif
X }
X#if defined(ALTARS) && defined(THEOLOGY)
X if(mon->ispriest && !rn2(2)) ghod_hitsu();
X#endif
X }
X return(malive);
X}
X
Xstatic boolean
Xhitum(mon, tmp) /* returns TRUE if monster still lives */
Xstruct monst *mon;
Xint tmp;
X{
X static int NEARDATA malive;
X boolean mhit = (tmp > rnd(20) || u.uswallow);
X
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 register 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) {
X tmp = rnd(2); /* attack with bare hands */
X#if 0
X if(mdat == &mons[PM_COCKATRICE] && !uarmg
X#ifdef POLYSELF
X && !resists_ston(uasmon)
X#endif
X ) {
X
X kludge("You hit %s with your bare %s.",
X mon_nam(mon), makeplural(body_part(HAND)));
X You("turn to stone...");
X done_in_by(mon);
X hittxt = TRUE; /* maybe lifesaved */
X }
X#endif
X } else {
X if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE ||
X obj->otyp == UNICORN_HORN || obj->olet == ROCK_SYM) {
X
X if(obj == uwep && (obj->otyp >= BOW || obj->otyp < BOOMERANG)
X && obj->otyp != PICK_AXE && obj->otyp != UNICORN_HORN)
X tmp = rnd(2);
X else {
X tmp = dmgval(obj, mdat);
X#ifdef NAMED_ITEMS
X if(spec_ability(obj, SPFX_DRLI) && !resists_drli(mdat)) {
X if (!Blind) {
X pline("The %s blade draws the life from %s!",
X Hallucination ? hcolor() : black,
X mon_nam(mon));
X hittxt = TRUE;
X }
X if (mon->m_lev == 0) tmp = mon->mhp;
X else {
X int drain = rnd(8);
X tmp += drain;
X mon->mhpmax -= drain;
X mon->m_lev--;
X }
X }
X#endif
X if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
X !rnl(3)) {
X kludge("As you hit %s, the boomerang breaks into splinters.",
X mon_nam(mon));
X useup(obj);
X hittxt = TRUE;
X tmp++;
X }
X if(thrown && (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)){
X if(((uwep && objects[obj->otyp].w_propellor ==
X -objects[uwep->otyp].w_propellor)
X || obj->otyp==DART || obj->otyp==SHURIKEN) &&
X obj->opoisoned)
X ispoisoned = TRUE;
X }
X if(thrown && obj->otyp == SILVER_ARROW) {
X if (is_were(mdat) || mdat->mlet==S_VAMPIRE
X || (mdat->mlet==S_IMP && mdat != &mons[PM_TENGU])
X || is_demon(mdat)) {
X silvermsg = TRUE;
X tmp += rnd(20);
X }
X }
X }
X } else if(obj->olet == POTION_SYM) {
X if (obj->quan > 1) setuwep(splitobj(obj, 1));
X else setuwep((struct obj *)0);
X freeinv(obj);
X potionhit(mon,obj);
X hittxt = TRUE;
X tmp = 1;
X } else switch(obj->otyp) {
X case HEAVY_IRON_BALL:
X tmp = rnd(25); break;
X case BOULDER:
X tmp = rnd(20); break;
X#ifdef MEDUSA
X case MIRROR:
X You("break your mirror. That's bad luck!");
X change_luck(-2);
X useup(obj);
X hittxt = TRUE;
X tmp = 1;
X break;
X#endif
X case EXPENSIVE_CAMERA:
X You("succeed in destroying your camera. Congratulations!");
X useup(obj);
X return(TRUE);
X case CORPSE: /* fixed by polder@cs.vu.nl */
X if(obj->corpsenm == PM_COCKATRICE) {
X kludge("You hit %s with the cockatrice corpse.",
X mon_nam(mon));
X if(resists_ston(mdat)) {
X tmp = 1;
X hittxt = TRUE;
X break;
X }
X kludge("%s turns to stone.", Monnam(mon));
X stoned = TRUE;
X xkilled(mon,0);
X nohandglow(mon);
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 kludge("You hit %s with the %s egg%s.",
X mon_nam(mon),
X mons[obj->corpsenm].mname,
X plur((long)obj->quan));
X hittxt = TRUE;
X pline("The egg%sn't live any more...",
X (obj->quan==1) ? " is" : "s are");
X obj->otyp = ROCK;
X obj->olet = GEM_SYM;
X obj->known = obj->dknown = 0;
X obj->owt = weight(obj);
X }
X tmp = 1;
X break;
X case CLOVE_OF_GARLIC: /* no effect against demons */
X if(is_undead(mdat)) mon->mflee = 1;
X tmp = 1;
X break;
X case CREAM_PIE:
X#ifdef POLYSELF
X case BLINDING_VENOM:
X if(Blind)
X pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
X else if (obj->otyp == BLINDING_VENOM)
X pline("The venom blinds %s%s!", mon_nam(mon),
X mon->mcansee ? "" : " further");
X#else
X if(Blind) pline("Splat!");
X#endif
X else
X pline("The cream pie splashes over %s%s!",
X mon_nam(mon),
X (haseyes(mdat) &&
X mdat != &mons[PM_FLOATING_EYE])
X ? "'s face" : "");
X if(mon->msleep) mon->msleep = 0;
X setmangry(mon);
X mon->mcansee = 0;
X tmp = rnd(25) + 20;
X if((mon->mblinded + tmp) > 127) mon->mblinded = 127;
X else mon->mblinded += tmp;
X hittxt = TRUE;
X get_dmg_bonus = FALSE;
X tmp = 0;
X break;
X#ifdef POLYSELF
X case ACID_VENOM: /* only possible if thrown */
X if(resists_acid(mdat)) {
X kludge("Your venom hits %s harmlessly.",
X mon_nam(mon));
X tmp = 0;
X } else {
X kludge("Your venom burns %s!", mon_nam(mon));
X tmp = dmgval(obj, 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/10;
X if(tmp < 1) tmp = 1;
X else tmp = rnd(tmp);
X if(tmp > 6) tmp = 6;
X }
X }
X
X /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
X * *OR* if attacking bare-handed!! */
X
X if (get_dmg_bonus) {
X tmp += u.udaminc;
X /* If you throw using a propellor, you don't get a strength
X * bonus but you do get an increase-damage bonus.
X */
X if(!thrown || !obj || !uwep ||
X (obj->olet != GEM_SYM && obj->olet != WEAPON_SYM) ||
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) 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 mon->mflee = 1; /* 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 == METAL
X && mon->mhp > 1 && !thrown && !mon->mcan
X /* && !destroyed -- guaranteed by mhp > 1 */ ) {
X
X if (clone_mon(mon)) {
X kludge("%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(Blind || !flags.verbose) You("hit it.");
X else You("hit %s%s", mon_nam(mon), exclam(tmp));
X }
X
X if (silvermsg) {
X if (cansee(mon->mx, mon->my))
X pline("The silver arrow sears %s's flesh!",
X mon_nam(mon));
X else
X pline("Its flesh is seared!");
X }
X
X if (needpoismsg)
X kludge("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 nohandglow(mon);
X return FALSE;
X } else if (destroyed) {
X killed(mon); /* takes care of most messages */
X nohandglow(mon);
X } else if(u.umconf && !thrown) {
X nohandglow(mon);
X if(!resist(mon, '+', 0, NOTELL)) mon->mconf = 1;
X if(!mon->mstun && mon->mcanmove && !mon->msleep &&
X !Blind && mon->mconf)
X pline("%s appears confused.", Monnam(mon));
X }
X
X#if 0
X if(mdat == &mons[PM_RUST_MONSTER] && obj && obj == uwep &&
X objects[obj->otyp].oc_material == METAL &&
X obj->olet == WEAPON_SYM && obj->spe > -2) {
X if(obj->rustfree) {
X pline("The rust on your %s vanishes instantly!",
X is_sword(obj) ? "sword" : "weapon");
X } else if(obj->blessed && !rnl(4))
X pline("Somehow your %s is not affected!",
X is_sword(obj) ? "sword" : "weapon");
X else {
X Your("%s!", aobjnam(obj, "corrode"));
X obj->spe--;
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 stoned = FALSE;
X if (is_demon(uasmon) && !rn2(13) && !uwep
X# ifdef INFERNO
X && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
X && u.umonnum != PM_BALROG
X# endif
X ) {
X struct monst *dtmp;
X pline("Some hell-p has arrived!");
X if((dtmp = makemon(!rn2(6) ? &mons[ndemon()] : uasmon, u.ux, u.uy)))
X (void)tamedog(dtmp, (struct obj *)0);
X return(0);
X }
X
X switch(mattk->adtyp) {
X case AD_STUN:
X if(!Blind)
X pline("%s staggers for a moment.", Monnam(mdef));
X mdef->mstun = 1;
X /* fall through to next case */
X case AD_WERE: /* no effect on monsters */
X case AD_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_SYM, AD_FIRE);
X# ifdef SPELLS
X tmp += destroy_mitem(mdef, SPBOOK_SYM, AD_FIRE);
X# endif
X if(resists_fire(pd)) {
X if (!Blind)
X pline("The fire doesn't heat %s!", mon_nam(mdef));
X# ifdef GOLEMS
X golemeffects(mdef, AD_FIRE, tmp);
X# endif /* GOLEMS */
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_SYM, 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# ifdef GOLEMS
X golemeffects(mdef, AD_COLD, tmp);
X# endif /* GOLEMS */
X tmp = 0;
X }
X tmp += destroy_mitem(mdef, POTION_SYM, AD_COLD);
X break;
X case AD_ELEC:
X if (!Blind) pline("%s is zapped!", Monnam(mdef));
X tmp += destroy_mitem(mdef, WAND_SYM, AD_ELEC);
X if(resists_elec(pd)) {
X if (!Blind)
X pline("The zap doesn't shock %s!", mon_nam(mdef));
X# ifdef GOLEMS
X golemeffects(mdef, AD_ELEC, tmp);
X# endif /* GOLEMS */
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_SYM, AD_ELEC);
X break;
X case AD_ACID:
X if(resists_acid(pd)) tmp = 0;
X break;
X case AD_STON:
X if(!resists_ston(pd)) {
X stoned = TRUE;
X if(!Blind) pline("%s turns to stone.", Monnam(mdef));
X xkilled(mdef, 0);
X return(2);
X }
X tmp = 0; /* no damage if this fails */
X break;
X# ifdef SEDUCE
X case AD_SSEX:
X# endif
X case AD_SEDU:
X case AD_SITM:
X if(mdef->minvent) {
X struct obj *otmp, *addinv(), *stealoid;
X
X stealoid = (struct obj *)0;
X if(is_mercenary(pd) && could_seduce(&youmonst,mdef,mattk)){
X for(otmp = mdef->minvent; otmp; otmp=otmp->nobj)
X if (otmp->otyp >= PLATE_MAIL && otmp->otyp
X <= ELVEN_CLOAK) stealoid = otmp;
X }
X if (stealoid) {
X boolean stolen = FALSE;
X /* Is "he"/"his" always correct? */
X kludge("You seduce %s and he starts to take off his clothes.",
X mon_nam(mdef));
X while(mdef->minvent) {
X otmp = mdef->minvent;
X mdef->minvent = otmp->nobj;
X /* set dknown to insure proper merge */
X if (!Blind) otmp->dknown = 1;
X if (!stolen && otmp==stealoid) {
X otmp = addinv(otmp);
X if(inv_cnt() > 52)
X dropx(otmp);
X stealoid = otmp;
X stolen = TRUE;
X } else {
X otmp = addinv(otmp);
X if(inv_cnt() > 52) {
X dropx(otmp);
X You("steal %s.", doname(otmp));
X } else {
X You("steal: ");
X prinv(otmp);
X }
X }
X }
X if (!stolen)
X impossible("Player steal fails!");
X else {
X kludge("%s finishes taking off his suit.",
X Monnam(mdef));
X You("steal %s!", doname(stealoid));
X# ifdef ARMY
X mdef->data = &mons[PM_UNARMORED_SOLDIER];
X# endif
X }
X } else {
X otmp = mdef->minvent;
X mdef->minvent = otmp->nobj;
X if (!Blind) otmp->dknown = 1;
X otmp = addinv(otmp);
X if(inv_cnt() > 52) {
X dropx(otmp);
X You("steal %s.", doname(otmp));
X } else {
X You("steal: ");
X prinv(otmp);
X }
X }
X }
X tmp = 0;
X break;
X case AD_SGLD:
X if (mdef->mgold) {
X u.ugold += mdef->mgold;
X mdef->mgold = 0;
X Your("purse feels heavier.");
X }
X tmp = 0;
X break;
X case AD_TLPT:
X if(tmp <= 0) tmp = 1;
X if(tmp < mdef->mhp) {
X rloc(mdef);
X if(!Blind) pline("%s suddenly disappears!", Monnam(mdef));
X }
X break;
X case AD_BLND:
X if(haseyes(pd)) {
X
X if(!Blind) pline("%s is blinded.", Monnam(mdef));
X mdef->mcansee = 0;
X mdef->mblinded += tmp;
X }
X tmp = 0;
X break;
X case AD_CURS:
X if (night() && !rn2(10) && !mdef->mcan) {
X# ifdef GOLEMS
X if (mdef->data == &mons[PM_CLAY_GOLEM]) {
X if (!Blind)
X pline("Some writing vanishes from %s's head!",
X mon_nam(mdef));
X xkilled(mdef, 0);
X return 2;
X }
X# endif /* GOLEMS */
X mdef->mcan = 1;
X You("chuckle.");
X }
X tmp = 0;
X break;
X case AD_DRLI:
X if(rn2(2) && !resists_drli(pd)) {
X int xtmp = d(2,6);
X kludge("%s suddenly seems weaker!", Monnam(mdef));
X mdef->mhpmax -= xtmp;
X if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev--) {
X kludge("%s dies!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
X }
X tmp = 0;
X break;
X case AD_RUST:
X# ifdef GOLEMS
X if (pd == &mons[PM_IRON_GOLEM]) {
X kludge("%s falls to pieces!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
X# endif /* GOLEMS */
X tmp = 0;
X break;
X case AD_DCAY:
X# ifdef GOLEMS
X if (pd == &mons[PM_WOOD_GOLEM] ||
X pd == &mons[PM_LEATHER_GOLEM]) {
X kludge("%s falls to pieces!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
X# endif /* GOLEMS */
X case AD_DRST:
X case AD_DRDX:
X case AD_DRCO:
X if (!rn2(8)) {
X Your("%s was poisoned!", mattk->aatyp==AT_BITE ?
X "bite" : "sting");
X if (resists_poison(mdef->data))
X kludge("The poison doesn't seem to affect %s.",
X mon_nam(mdef));
X else {
X if (!rn2(10)) {
X Your("poison was deadly...");
X tmp = mdef->mhp;
X } else tmp += rn1(10,6);
X }
X }
X break;
X case AD_WRAP:
X case AD_STCK:
X if (!sticks(mdef->data))
X u.ustuck = mdef; /* it's now stuck to you */
X break;
X 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) {
X if(!Blind) You("killed your %s!", lmonnam(mdef) + 4);
X else You("feel embarrassed for a moment.");
X } else {
X if(!Blind && flags.verbose) pline("%s is killed!", Monnam(mdef));
X else You("kill it!");
X }
X xkilled(mdef, 0);
X return(2);
X }
X return(1);
X}
X
Xstatic int
Xexplum(mdef, mattk)
Xregister struct monst *mdef;
Xregister struct attack *mattk;
X{
X switch(mattk->adtyp) {
X case AD_BLND:
X if(mdef->data->mlet != S_YLIGHT) {
X kludge("%s is blinded by your flash of light!", Monnam(mdef));
X if (mdef->mcansee) {
X mdef->mblinded += rn2(25);
X mdef->mcansee = 0;
X }
X }
X break;
X case AD_COLD:
X You("explode!");
X if (!resists_cold(mdef->data)) {
X kludge("%s gets blasted!", Monnam(mdef));
X mdef->mhp -= d(6,6);
X if (mdef->mhp <= 0) {
X killed(mdef);
X return(2);
X }
X# ifdef GOLEMS
X } else if (is_golem(mdef->data)) {
X golemeffects(mdef, AD_COLD, d(6,6));
X shieldeff(mdef->mx, mdef->my);
X# endif /* GOLEMS */
X } else {
X shieldeff(mdef->mx, mdef->my);
X kludge("The blast doesn't seem to affect %s.",
X mon_nam(mdef));
X }
X break;
X default: break;
X }
X return(1);
X}
X
Xstatic int
Xgulpum(mdef,mattk)
Xregister struct monst *mdef;
Xregister struct attack *mattk;
X{
X register int tmp;
X register int dam = d((int)mattk->damn, (int)mattk->damd);
X /* Not totally the same as for real monsters. Specifically, these
X * don't take multiple moves. (It's just too hard, for too little
X * result, to program monsters which attack from inside you, which
X * would be necessary if done accurately.) Instead, we arbitrarily
X * kill the monster immediately for AD_DGST and we regurgitate them
X * after exactly 1 round of attack otherwise. -KAA
X */
X
X 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 kludge("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 Blind ? "it" : mon_nam(mdef));
X if (tmp = 3 + (mdef->data->cwt >> 2)) {
X kludge("You digest %s.", mon_nam(mdef));
X nomul(-tmp);
X nomovemsg = msgbuf;
X } else pline(msgbuf);
X return(2);
X case AD_PHYS:
X kludge("%s is pummeled with your debris!",Monnam(mdef));
X break;
X case AD_ACID:
X kludge("%s is covered with your goo!", Monnam(mdef));
X if (resists_acid(mdef->data)) {
X kludge("It seems harmless to %s.", mon_nam(mdef));
X dam = 0;
X }
X break;
X case AD_BLND:
X if (mdef->mcansee)
X kludge("%s can't see in there!", Monnam(mdef));
X mdef->mcansee = 0;
X dam += mdef->mblinded;
X if (dam > 127) dam = 127;
X mdef->mblinded = dam;
X dam = 0;
X break;
X case AD_ELEC:
X if (rn2(2)) {
X kludge("The air around %s crackles with electricity.", mon_nam(mdef));
X if (resists_elec(mdef->data)) {
X kludge("%s seems unhurt.", Monnam(mdef));
X dam = 0;
X }
X# ifdef GOLEMS
X golemeffects(mdef,(int)mattk->adtyp,dam);
X# endif
X } else dam = 0;
X break;
X case AD_COLD:
X if (rn2(2)) {
X if (resists_cold(mdef->data)) {
X kludge("%s seems mildly chilly.", Monnam(mdef));
X dam = 0;
X } else
X kludge("%s is freezing to death!",Monnam(mdef));
X# ifdef GOLEMS
X golemeffects(mdef,(int)mattk->adtyp,dam);
X# endif
X } else dam = 0;
X break;
X case AD_FIRE:
X if (rn2(2)) {
X if (resists_fire(mdef->data)) {
X kludge("%s seems mildly hot.", Monnam(mdef));
X dam = 0;
X } else
X kludge("%s is burning to a crisp!",Monnam(mdef));
X# ifdef GOLEMS
X golemeffects(mdef,(int)mattk->adtyp,dam);
X# endif
X } else dam = 0;
X break;
X }
X if ((mdef->mhp -= dam) <= 0) {
X kludge("%s is killed!", Monnam(mdef));
X xkilled(mdef,0);
X return(2);
X }
X kludge("You %s %s!", is_animal(uasmon) ? "regurgitate"
X : "expel", mon_nam(mdef));
X if (is_animal(uasmon)) {
X if (Blind)
X pline("Obviously, you didn't like its taste.");
X else
X pline("Obviously, you didn't like %s's taste.",
X mon_nam(mdef));
X }
X } else {
X kludge("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 kludge("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 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 > rnd(20) || u.uswallow);
X /* Enemy dead, before any special abilities used */
X if (!known_hitum(mon,dhit)) return 0;
X /* Do not print "You hit" message, since known_hitum
X * already did it.
X */
X if (dhit && mattk->adtyp != AD_SPEL
X && mattk->adtyp != AD_PHYS)
X sum[i] = damageum(mon,mattk);
X 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 if (i==0 && uwep && (u.usym==S_LICH)) goto use_weapon;
X if(dhit = (tmp > rnd(20) || u.uswallow)) {
X int compat;
X
X if (!u.uswallow &&
X (compat = could_seduce(&youmonst,
X mon, mattk)))
X You("%s %s %s.",
X mon->mcansee ? "smile at" : "talk to",
X Blind ? "it" : mon_nam(mon),
X compat == 2 ? "engagingly" : "seductively");
X else if (mattk->aatyp == AT_KICK)
X kludge("You kick %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_BITE)
X kludge("You bite %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_STNG)
X kludge("You sting %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_BUTT)
X kludge("You butt %s.", mon_nam(mon));
X else if (mattk->aatyp == AT_TUCH)
X kludge("You touch %s.", mon_nam(mon));
X else kludge("You hit %s.", mon_nam(mon));
X sum[i] = damageum(mon, mattk);
X } else
X missum(mon, 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 if (!sticks(mon->data))
X if (mon==u.ustuck) {
X kludge("%s is being %s.", Monnam(mon),
X# ifdef GOLEMS
X u.umonnum==PM_ROPE_GOLEM ? "choked":
X# endif
X "crushed");
X sum[i] = damageum(mon, mattk);
X } else if(sum[i-1] && sum[i-2]) {
X kludge("You grab %s!", mon_nam(mon));
X u.ustuck = mon;
X sum[i] = damageum(mon, mattk);
X }
X break;
X
X case AT_EXPL: /* automatic hit if next to */
X dhit = -1;
X sum[i] = explum(mon, mattk);
X break;
X
X case AT_ENGL:
X if((dhit = (tmp > rnd(20+i))))
X sum[i]= gulpum(mon,mattk);
X else
X missum(mon, 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 default: /* Strange... */
X impossible("strange attack of yours (%d)",
X mattk->aatyp);
X case AT_BREA:
X case AT_SPIT:
X case AT_GAZE: /* all done using #monster command */
X dhit = 0;
X break;
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
X/* These affect you even if they just died */
X
X switch(ptr->mattk[i].adtyp) {
X
X case AD_ACID:
X if(mhit && rn2(2)) {
X if (Blind || !flags.verbose) You("are splashed!");
X else You("are splashed by %s's acid!", mon_nam(mon));
X
X tmp = d((int)mon->m_lev, (int)ptr->mattk[i].damd);
X#ifdef POLYSELF
X if(!resists_acid(uasmon))
X#endif
X mdamageu(mon, tmp);
X if(!rn2(30)) corrode_armor();
X }
X if(mhit && !rn2(6)) {
X if (kicked) {
X if (uarmf)
X (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE);
X } else corrode_weapon();
X }
X break;
X case AD_STON:
X if(mhit)
X if (!kicked)
X if (!uwep && !uarmg
X#ifdef POLYSELF
X && !resists_ston(uasmon)
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)
X if (kicked) {
X if (uarmf)
X (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE);
X } else
X corrode_weapon();
X break;
X case AD_MAGM:
X /* wrath of gods for attacking Oracle */
X if(Antimagic) {
X shieldeff(u.ux, u.uy);
X pline("A hail of magic missiles narrowly misses you!");
X } else {
X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
X You("are hit by magic missiles appearing from thin air!");
X mdamageu(mon, tmp);
X }
X break;
X default:
X break;
X }
X
X/* These only affect you if they still live */
X
X if(malive && !mon->mcan && rn2(3)) {
X
X switch(ptr->mattk[i].adtyp) {
X
X case AD_PLYS:
X tmp = -d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
X if(ptr == &mons[PM_FLOATING_EYE]) {
X if (!canseemon(mon)) {
X tmp = 0;
X break;
X }
X if(mon->mcansee) {
X if(Reflecting & W_AMUL) {
X makeknown(AMULET_OF_REFLECTION);
X pline("%s's gaze is reflected by your medallion.",
X Monnam(mon));
X } else if(Reflecting & W_ARMS) {
X makeknown(SHIELD_OF_REFLECTION);
X pline("%s's gaze is reflected by your shield.",
X Monnam(mon));
X } else {
X You("are frozen by %s's gaze!", mon_nam(mon));
X nomul((ACURR(A_WIS) > 12 || rn2(4)) ? tmp : -120);
X }
X } else {
X pline("%s cannot defend itself.", Amonnam(mon,"blind"));
X if(!rn2(500)) change_luck(-1);
X }
X } else { /* gelatinous cube */
X You("are frozen by %s!", mon_nam(mon));
X nomul(tmp);
X tmp = 0;
X }
X break;
X case AD_COLD: /* brown mold or blue jelly */
X if(monnear(mon, u.ux, u.uy)) {
X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
X if(Cold_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel a mild chill.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_COLD, tmp);
X#endif /* GOLEMS */
X#endif
X tmp = 0;
X break;
X }
X You("are suddenly very cold!");
X mdamageu(mon, tmp);
X /* monster gets stronger with your heat! */
X mon->mhp += tmp / 2;
X if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
X /* at a certain point, the monster will reproduce! */
X if(mon->mhpmax > ((mon->m_lev+1) * 8)) {
X register struct monst *mtmp;
X
X if(mtmp = clone_mon(mon)) {
X mtmp->mhpmax = mon->mhpmax /= 2;
X if(!Blind)
X pline("%s multiplies from your heat!",
X Monnam(mon));
X }
X }
X }
X break;
X case AD_STUN: /* specifically yellow mold */
X if(!Stunned)
X make_stunned((long)d((int)mon->m_lev+1, (int)ptr->mattk[i].damd), TRUE);
X break;
X case AD_FIRE:
X if(monnear(mon, u.ux, u.uy)) {
X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
X if(Fire_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel mildly warm.");
X#if defined(POLYSELF) && defined(GOLEMS)
X ugolemeffects(AD_FIRE, tmp);
X#endif
X tmp = 0;
X break;
X }
X You("are suddenly very hot!");
X mdamageu(mon, tmp);
X }
X break;
X case AD_ELEC:
X tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
X if(Shock_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel a mild tingle.");
X#if defined(POLYSELF) && defined(GOLEMS)
X ugolemeffects(AD_ELEC, tmp);
X#endif
X tmp = 0;
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->mimic... */
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) goto generic;
X else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == CLOSED_DOOR_SYM)
X#ifdef SPELLS
X {
X if (IS_ROCK(levl[u.ux+u.dx][u.uy+u.dy].typ) ||
X IS_DOOR(levl[u.ux+u.dx][u.uy+u.dy].typ))
X#endif
X pline("The door actually was %s.", defmonnam(mtmp));
X#ifdef SPELLS
X else
X pline("That spellbook was %s.", defmonnam(mtmp));
X }
X#endif
X else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == GOLD_SYM)
X pline("That gold was %s!", defmonnam(mtmp));
X else {
Xgeneric:
X pline("Wait! That's %s!", defmonnam(mtmp));
X }
X wakeup(mtmp); /* clears mtmp->mimic */
X}
X
Xstatic void
Xnohandglow(mon)
Xstruct monst *mon;
X{
X if (!u.umconf || mon->mconf) return;
X if (u.umconf == 1) {
X if (Blind)
X Your("%s stop tingling.", makeplural(body_part(HAND)));
X else
X Your("%s stop glowing %s.",
X makeplural(body_part(HAND)),
X Hallucination ? hcolor() : red);
X } else {
X if (Blind)
X pline("The tingling in your %s lessens.",
X makeplural(body_part(HAND)));
X else
X Your("%s no longer glow so brightly %s.",
X makeplural(body_part(HAND)),
X Hallucination ? hcolor() : red);
X }
X u.umconf--;
X}
END_OF_FILE
if test 39521 -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 11 \(of 56\).
cp /dev/null ark11isdone
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 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 56 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