From d5d2147ddffde298267f838b55a79411b4fa4552 Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:51 +0000 Subject: [PATCH] *** empty log message *** --- src/mthrowu.c | 746 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 746 insertions(+) create mode 100644 src/mthrowu.c diff --git a/src/mthrowu.c b/src/mthrowu.c new file mode 100644 index 000000000..0ab90c99f --- /dev/null +++ b/src/mthrowu.c @@ -0,0 +1,746 @@ +/* SCCS Id: @(#)mthrowu.c 3.3 2001/12/10 */ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" + +STATIC_DCL int FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int)); + +#define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y)) + +#define POLE_LIM 5 /* How far monsters can use pole-weapons */ + +#ifndef OVLB + +STATIC_DCL const char *breathwep[]; + +#else /* OVLB */ + +/* + * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h. + */ +STATIC_OVL NEARDATA const char *breathwep[] = { + "fragments", + "fire", + "frost", + "sleep gas", + "a disintegration blast", + "lightning", + "poison gas", + "acid", + "strange breath #8", + "strange breath #9" +}; + +/* hero is hit by something other than a monster */ +int +thitu(tlev, dam, obj, name) +int tlev, dam; +struct obj *obj; +const char *name; /* if null, then format `obj' */ +{ + const char *onm, *knm; + boolean is_acid; + char onmbuf[BUFSZ], knmbuf[BUFSZ]; + + if (!name) { + struct obj otmp; + unsigned save_ocknown; + + if (!obj) panic("thitu: name & obj both null?"); + name = strcpy(onmbuf, + (obj->quan > 1L) ? doname(obj) : mshot_xname(obj)); + /* killer name should be more specific; however, exact info + like blessed/cursed and rustproof make things too verbose */ + otmp = *obj; + save_ocknown = objects[otmp.otyp].oc_name_known; + otmp.known = otmp.dknown = 1; + otmp.bknown = otmp.rknown = otmp.greased = 0; + /* "killed by poisoned " would be misleading + since poison is not the cause of death */ + otmp.opoisoned = 0; + objects[otmp.otyp].oc_name_known = 1; + knm = strcpy(knmbuf, + (otmp.quan > 1L) ? doname(&otmp) : xname(&otmp)); + objects[otmp.otyp].oc_name_known = save_ocknown; + } else { + knm = name; + } + onm = (obj && obj_is_pname(obj)) ? the(name) : + (obj && obj->quan > 1L) ? name : an(name); + is_acid = (obj && obj->otyp == ACID_VENOM); + + if(u.uac + tlev <= rnd(20)) { + if(Blind || !flags.verbose) pline("It misses."); + else You("are almost hit by %s.", onm); + return(0); + } else { + if(Blind || !flags.verbose) You("are hit!"); + else You("are hit by %s%s", onm, exclam(dam)); + + if (obj && objects[obj->otyp].oc_material == SILVER + && hates_silver(youmonst.data)) { + dam += rnd(20); + pline_The("silver sears your flesh!"); + exercise(A_CON, FALSE); + } + if (is_acid && Acid_resistance) + pline("It doesn't seem to hurt you."); + else { + if (is_acid) pline("It burns!"); + if (Half_physical_damage) dam = (dam+1) / 2; + losehp(dam, knm, (obj && obj_is_pname(obj)) ? + KILLED_BY : KILLED_BY_AN); + exercise(A_STR, FALSE); + } + return(1); + } +} + +/* Be sure this corresponds with what happens to player-thrown objects in + * dothrow.c (for consistency). --KAA + * Returns 0 if object still exists (not destroyed). + */ + +STATIC_OVL int +drop_throw(obj, ohit, x, y) +register struct obj *obj; +boolean ohit; +int x,y; +{ + int retvalu = 1; + int create; + struct monst *mtmp; + struct trap *t; + + if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS || + (ohit && obj->otyp == EGG)) + create = 0; + else if (ohit && (is_multigen(obj) || obj->otyp == ROCK)) + create = !rn2(3); + else create = 1; + + if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && + (t = t_at(x, y)) && ((t->ttyp == PIT) || + (t->ttyp == SPIKED_PIT)))) { + int objgone = 0; + + if (down_gate(x, y) != -1) + objgone = ship_object(obj, x, y, FALSE); + if (!objgone) { + if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */ + place_object(obj, x, y); + if (!mtmp && x == u.ux && y == u.uy) + mtmp = &youmonst; + if (mtmp && ohit) + passive_obj(mtmp, obj, (struct attack *)0); + stackobj(obj); + retvalu = 0; + } + } + } else obfree(obj, (struct obj*) 0); + return retvalu; +} + +#endif /* OVLB */ +#ifdef OVL1 + +/* an object launched by someone/thing other than player attacks a monster; + return 1 if the object has stopped moving (hit or its range used up) */ +int +ohitmon(mtmp, otmp, range, verbose) +struct monst *mtmp; /* accidental target */ +struct obj *otmp; /* missile; might be destroyed by drop_throw */ +int range; /* how much farther will object travel if it misses */ + /* Use -1 to signify to keep going even after hit, */ + /* unless its gone (used for rolling_boulder_traps) */ +boolean verbose; /* give message(s) even when you can't see what happened */ +{ + int damage, tmp; + boolean vis, ismimic; + int objgone = 1; + + ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER; + vis = cansee(bhitpos.x, bhitpos.y); + + tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); + if (tmp < rnd(20)) { + if (!ismimic) { + if (vis) miss(distant_name(otmp, mshot_xname), mtmp); + else if (verbose) pline("It is missed."); + } + if (!range) { /* Last position; object drops */ + (void) drop_throw(otmp, 0, mtmp->mx, mtmp->my); + return 1; + } + } else if (otmp->oclass == POTION_CLASS) { + if (ismimic) seemimic(mtmp); + mtmp->msleeping = 0; + if (vis) otmp->dknown = 1; + potionhit(mtmp, otmp, FALSE); + return 1; + } else { + damage = dmgval(otmp, mtmp); + if (otmp->otyp == ACID_VENOM && resists_acid(mtmp)) + damage = 0; + if (ismimic) seemimic(mtmp); + mtmp->msleeping = 0; + if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage)); + else if (verbose) pline("It is hit%s", exclam(damage)); + + if (otmp->opoisoned) { + if (resists_poison(mtmp)) { + if (vis) pline_The("poison doesn't seem to affect %s.", + mon_nam(mtmp)); + } else { + if (rn2(30)) { + damage += rnd(6); + } else { + if (vis) pline_The("poison was deadly..."); + damage = mtmp->mhp; + } + } + } + if (objects[otmp->otyp].oc_material == SILVER && + hates_silver(mtmp->data)) { + if (vis) pline_The("silver sears %s flesh!", + s_suffix(mon_nam(mtmp))); + else if (verbose) pline("Its flesh is seared!"); + } + if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) { + if (resists_acid(mtmp)) { + if (vis || verbose) + pline("%s is unaffected.", Monnam(mtmp)); + damage = 0; + } else { + if (vis) pline_The("acid burns %s!", mon_nam(mtmp)); + else if (verbose) pline("It is burned!"); + } + } + mtmp->mhp -= damage; + if (mtmp->mhp < 1) { + if (vis || verbose) + pline("%s is %s!", Monnam(mtmp), + (nonliving(mtmp->data) || !vis) + ? "destroyed" : "killed"); + mondied(mtmp); + } + + if (can_blnd((struct monst*)0, mtmp, + (uchar)(otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP), + otmp)) { + if (vis && mtmp->mcansee) + pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp))); + mtmp->mcansee = 0; + tmp = (int)mtmp->mblinded + rnd(25) + 20; + if (tmp > 127) tmp = 127; + mtmp->mblinded = tmp; + } + + objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y); + if (!objgone && range == -1) { /* special case */ + obj_extract_self(otmp); /* free it for motion again */ + return 0; + } + return 1; + } + return 0; +} + +void +m_throw(mon, x, y, dx, dy, range, obj) + register struct monst *mon; + register int x,y,dx,dy,range; /* direction and range */ + register struct obj *obj; +{ + register struct monst *mtmp; + struct obj *singleobj; + char sym = obj->oclass; + int hitu, blindinc = 0; + + bhitpos.x = x; + bhitpos.y = y; + + if (obj->quan == 1L) { + /* + * Remove object from minvent. This cannot be done later on; + * what if the player dies before then, leaving the monster + * with 0 daggers? (This caused the infamous 2^32-1 orcish + * dagger bug). + * + * VENOM is not in minvent - it should already be OBJ_FREE. + * The extract below does nothing. + */ + + /* not possibly_unwield, which checks the object's */ + /* location, not its existence */ + if (MON_WEP(mon) == obj) { + setmnotwielded(mon,obj); + MON_NOWEP(mon); + } + obj_extract_self(obj); + singleobj = obj; + obj = (struct obj *) 0; + } else { + singleobj = splitobj(obj, obj->quan - 1L); + obj_extract_self(singleobj); + } + + singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */ + + if (singleobj->cursed && (dx || dy) && !rn2(7)) { + if(canseemon(mon) && flags.verbose) { + if(is_ammo(singleobj)) + pline("%s misfires!", Monnam(mon)); + else + pline("%s slips as %s throws it!", + The(xname(singleobj)), mon_nam(mon)); + } + dx = rn2(3)-1; + dy = rn2(3)-1; + /* pre-check validity of new direction */ + if((!dx && !dy) + || !isok(bhitpos.x+dx,bhitpos.y+dy) + /* missile hits the wall */ + || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)) { + (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); + return; + } + } + + /* Note: drop_throw may destroy singleobj. Since obj must be destroyed + * early to avoid the dagger bug, anyone who modifies this code should + * be careful not to use either one after it's been freed. + */ + if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); + while(range-- > 0) { /* Actually the loop is always exited by break */ + bhitpos.x += dx; + bhitpos.y += dy; + if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { + if (ohitmon(mtmp, singleobj, range, TRUE)) + break; + } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { + if (multi) nomul(0); + + if (singleobj->oclass == GEM_CLASS && + singleobj->otyp <= LAST_GEM+9 /* 9 glass colors */ + && is_unicorn(youmonst.data)) { + if (singleobj->otyp > LAST_GEM) { + You("catch the %s.", xname(singleobj)); + You("are not interested in %s junk.", + s_suffix(mon_nam(mon))); + makeknown(singleobj->otyp); + dropy(singleobj); + } else { + You("accept %s gift in the spirit in which it was intended.", + s_suffix(mon_nam(mon))); + (void)hold_another_object(singleobj, + "You catch, but drop, %s.", xname(singleobj), + "You catch:"); + } + break; + } + if (singleobj->oclass == POTION_CLASS) { + if (!Blind) singleobj->dknown = 1; + potionhit(&youmonst, singleobj, FALSE); + break; + } + switch(singleobj->otyp) { + int dam, hitv; + case EGG: + if (!touch_petrifies(&mons[singleobj->corpsenm])) { + impossible("monster throwing egg type %d", + singleobj->corpsenm); + hitu = 0; + break; + } + /* fall through */ + case CREAM_PIE: + case BLINDING_VENOM: + hitu = thitu(8, 0, singleobj, (char *)0); + break; + default: + dam = dmgval(singleobj, &youmonst); + hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my); + if (hitv < -4) hitv = -4; + if (is_elf(mon->data) && + objects[singleobj->otyp].oc_skill == P_BOW) { + hitv++; + if (MON_WEP(mon) && + MON_WEP(mon)->otyp == ELVEN_BOW) + hitv++; + if(singleobj->otyp == ELVEN_ARROW) dam++; + } + if (bigmonst(youmonst.data)) hitv++; + hitv += 8 + singleobj->spe; + if (dam < 1) dam = 1; + hitu = thitu(hitv, dam, singleobj, (char *)0); + } + if (hitu && singleobj->opoisoned) { + char onmbuf[BUFSZ], knmbuf[BUFSZ]; + struct obj otmp; + unsigned save_ocknown; + + /* [see thitu()'s handling of `name'] */ + Strcpy(onmbuf, xname(singleobj)); + otmp = *singleobj; + save_ocknown = objects[otmp.otyp].oc_name_known; + otmp.known = otmp.dknown = 1; + otmp.bknown = otmp.rknown = otmp.greased = 0; + /* "poisoned by poisoned " would be redundant */ + otmp.opoisoned = 0; + objects[otmp.otyp].oc_name_known = 1; + Strcpy(knmbuf, xname(&otmp)); + poisoned(onmbuf, A_STR, knmbuf, 10); + objects[otmp.otyp].oc_name_known = save_ocknown; + } + if(hitu && + can_blnd((struct monst*)0, &youmonst, + (uchar)(singleobj->otyp == BLINDING_VENOM ? + AT_SPIT : AT_WEAP), singleobj)) { + blindinc = rnd(25); + if(singleobj->otyp == CREAM_PIE) { + if(!Blind) pline("Yecch! You've been creamed."); + else pline("There's %s sticky all over your %s.", + something, + body_part(FACE)); + } else if(singleobj->otyp == BLINDING_VENOM) { + int num_eyes = eyecount(youmonst.data); + /* venom in the eyes */ + if(!Blind) pline_The("venom blinds you."); + else Your("%s sting%s.", + (num_eyes == 1) ? body_part(EYE) : + makeplural(body_part(EYE)), + (num_eyes == 1) ? "s" : ""); + } + } + if (hitu && singleobj->otyp == EGG) { + if (!Stone_resistance + && !(poly_when_stoned(youmonst.data) && + polymon(PM_STONE_GOLEM))) { + Stoned = 5; + killer = (char *) 0; + } + } + stop_occupation(); + if (hitu || !range) { + (void) drop_throw(singleobj, hitu, u.ux, u.uy); + break; + } + } else if (!range /* reached end of path */ + /* missile hits edge of screen */ + || !isok(bhitpos.x+dx,bhitpos.y+dy) + /* missile hits the wall */ + || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ) +#ifdef SINKS + /* Thrown objects "sink" */ + || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) +#endif + ) { + (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); + break; + } + tmp_at(bhitpos.x, bhitpos.y); + delay_output(); + } + tmp_at(bhitpos.x, bhitpos.y); + delay_output(); + tmp_at(DISP_END, 0); + + if (blindinc) { + u.ucreamed += blindinc; + make_blinded(Blinded + (long)blindinc, FALSE); + if (!Blind) Your(vision_clears); + } +} + +#endif /* OVL1 */ +#ifdef OVLB + +/* Remove an item from the monster's inventory and destroy it. */ +void +m_useup(mon, obj) +struct monst *mon; +struct obj *obj; +{ + if (obj->quan > 1L) { + obj->quan--; + obj->owt = weight(obj); + } else { + obj_extract_self(obj); + possibly_unwield(mon); + if (obj->owornmask) { + mon->misc_worn_check &= ~obj->owornmask; + update_mon_intrinsics(mon, obj, FALSE); + } + obfree(obj, (struct obj*) 0); + } +} + +#endif /* OVLB */ +#ifdef OVL1 + +/* monster attempts ranged weapon attack against player */ +void +thrwmu(mtmp) +struct monst *mtmp; +{ + struct obj *otmp, *mwep; + xchar x, y; + schar skill; + int multishot; + const char *onm; + + /* Rearranged beginning so monsters can use polearms not in a line */ + if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { + mtmp->weapon_check = NEED_RANGED_WEAPON; + /* mon_wield_item resets weapon_check as appropriate */ + if(mon_wield_item(mtmp) != 0) return; + } + + /* Pick a weapon */ + otmp = select_rwep(mtmp); + if (!otmp) return; + + if (is_pole(otmp)) { + int dam, hitv; + + if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM || + !couldsee(mtmp->mx, mtmp->my)) + return; /* Out of range, or intervening wall */ + + if (canseemon(mtmp)) { + onm = xname(otmp); + pline("%s thrusts %s.", Monnam(mtmp), + obj_is_pname(otmp) ? the(onm) : an(onm)); + } + + dam = dmgval(otmp, &youmonst); + hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my); + if (hitv < -4) hitv = -4; + if (bigmonst(youmonst.data)) hitv++; + hitv += 8 + otmp->spe; + if (dam < 1) dam = 1; + + (void) thitu(hitv, dam, otmp, (char *)0); + stop_occupation(); + return; + } + + x = mtmp->mx; + y = mtmp->my; + /* If you are coming toward the monster, the monster + * should try to soften you up with missiles. If you are + * going away, you are probably hurt or running. Give + * chase, but if you are getting too far away, throw. + */ + if (!lined_up(mtmp) || + (URETREATING(x,y) && + rn2(BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy)))) + return; + + skill = objects[otmp->otyp].oc_skill; + mwep = MON_WEP(mtmp); /* wielded weapon */ + + /* Multishot calculations */ + multishot = 1; + if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER || + skill == -P_DART || skill == -P_SHURIKEN) && !mtmp->mconf) { + /* Assumes lords are skilled, princes are expert */ + if (is_prince(mtmp->data)) multishot += 2; + else if (is_lord(mtmp->data)) multishot++; + + switch (monsndx(mtmp->data)) { + case PM_RANGER: + multishot++; + break; + case PM_ROGUE: + if (skill == P_DAGGER) multishot++; + break; + case PM_SAMURAI: + if (otmp->otyp == YA && mwep && + mwep->otyp == YUMI) multishot++; + break; + default: + break; + } + /* racial bonus */ + if ((is_elf(mtmp->data) && + otmp->otyp == ELVEN_ARROW && + mwep && mwep->otyp == ELVEN_BOW) || + (is_orc(mtmp->data) && + otmp->otyp == ORCISH_ARROW && + mwep && mwep->otyp == ORCISH_BOW)) + multishot++; + + if ((long)multishot > otmp->quan) multishot = (int)otmp->quan; + if (multishot < 1) multishot = 1; + else multishot = rnd(multishot); + } + + if (canseemon(mtmp)) { + char onmbuf[BUFSZ]; + + if (multishot > 1) { + /* "N arrows"; multishot > 1 implies otmp->quan > 1, so + xname()'s result will already be pluralized */ + Sprintf(onmbuf, "%d %s", multishot, xname(otmp)); + onm = onmbuf; + } else { + /* "an arrow" */ + onm = singular(otmp, xname); + onm = obj_is_pname(otmp) ? the(onm) : an(onm); + } + m_shot.s = ammo_and_launcher(otmp,mwep) ? TRUE : FALSE; + pline("%s %s %s!", Monnam(mtmp), + m_shot.s ? "shoots" : "throws", onm); + m_shot.o = otmp->otyp; + } else { + m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */ + } + + m_shot.n = multishot; + for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) + m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), + distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp); + m_shot.n = m_shot.i = 0; + m_shot.o = STRANGE_OBJECT; + m_shot.s = FALSE; + + nomul(0); +} + +#endif /* OVL1 */ +#ifdef OVLB + +int +spitmu(mtmp, mattk) /* monster spits substance at you */ +register struct monst *mtmp; +register struct attack *mattk; +{ + register struct obj *otmp; + + if(mtmp->mcan) { + + if(flags.soundok) + pline("A dry rattle comes from %s throat.", + s_suffix(mon_nam(mtmp))); + return 0; + } + if(lined_up(mtmp)) { + switch (mattk->adtyp) { + case AD_BLND: + case AD_DRST: + otmp = mksobj(BLINDING_VENOM, TRUE, FALSE); + break; + default: + impossible("bad attack type in spitmu"); + /* fall through */ + case AD_ACID: + otmp = mksobj(ACID_VENOM, TRUE, FALSE); + break; + } + if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) { + if (canseemon(mtmp)) + pline("%s spits venom!", Monnam(mtmp)); + m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), + distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp); + nomul(0); + return 0; + } + } + return 0; +} + +#endif /* OVLB */ +#ifdef OVL1 + +int +breamu(mtmp, mattk) /* monster breathes at you (ranged) */ + register struct monst *mtmp; + register struct attack *mattk; +{ + /* if new breath types are added, change AD_ACID to max type */ + int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ; + + if(lined_up(mtmp)) { + + if(mtmp->mcan) { + if(flags.soundok) { + if(canseemon(mtmp)) + pline("%s coughs.", Monnam(mtmp)); + else + You_hear("a cough."); + } + return(0); + } + if(!mtmp->mspec_used && rn2(3)) { + + if((typ >= AD_MAGM) && (typ <= AD_ACID)) { + + if(canseemon(mtmp)) + pline("%s breathes %s!", Monnam(mtmp), + breathwep[typ-1]); + buzz((int) (-20 - (typ-1)), (int)mattk->damn, + mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); + nomul(0); + /* breath runs out sometimes. Also, give monster some + * cunning; don't breath if the player fell asleep. + */ + if(!rn2(3)) + mtmp->mspec_used = 10+rn2(20); + if(typ == AD_SLEE && !Sleep_resistance) + mtmp->mspec_used += rnd(20); + } else impossible("Breath weapon %d used", typ-1); + } + } + return(1); +} + +boolean +linedup(ax, ay, bx, by) +register xchar ax, ay, bx, by; +{ + tbx = ax - bx; /* These two values are set for use */ + tby = ay - by; /* after successful return. */ + + /* sometimes displacement makes a monster think that you're at its + own location; prevent it from throwing and zapping in that case */ + if (!tbx && !tby) return FALSE; + + if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */ + && distmin(tbx, tby, 0, 0) < BOLT_LIM) { + if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by))); + else if(clear_path(ax,ay,bx,by)) return TRUE; + } + return FALSE; +} + +boolean +lined_up(mtmp) /* is mtmp in position to use ranged attack? */ + register struct monst *mtmp; +{ + return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); +} + +#endif /* OVL1 */ +#ifdef OVL0 + +/* Check if a monster is carrying a particular item. + */ +struct obj * +m_carrying(mtmp, type) +struct monst *mtmp; +int type; +{ + register struct obj *otmp; + + for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) + if(otmp->otyp == type) + return(otmp); + return((struct obj *) 0); +} + +#endif /* OVL0 */ + +/*mthrowu.c*/