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