1 /* SCCS Id: @(#)dothrow.c 3.4 2003/12/04 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* Contains code for 't' (throw) */
10 STATIC_DCL int FDECL(throw_obj, (struct obj *,int));
11 STATIC_DCL void NDECL(autoquiver);
12 STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *));
13 STATIC_DCL void FDECL(tmiss, (struct obj *, struct monst *));
14 STATIC_DCL int FDECL(throw_gold, (struct obj *));
15 STATIC_DCL void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
16 STATIC_DCL void FDECL(breakobj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P,BOOLEAN_P));
17 STATIC_DCL void FDECL(breakmsg, (struct obj *,BOOLEAN_P));
18 STATIC_DCL boolean FDECL(toss_up,(struct obj *, BOOLEAN_P));
19 STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
20 STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj *obj));
21 STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t,int,int));
24 static NEARDATA const char toss_objs[] =
25 { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
26 /* different default choices when wielding a sling (gold must be included) */
27 static NEARDATA const char bullets[] =
28 { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, GEM_CLASS, 0 };
30 struct obj *thrownobj = 0; /* tracks an object until it lands */
32 extern boolean notonhead; /* for long worms */
35 /* Throw the selected object, asking for direction */
37 throw_obj(obj, shotlimit)
47 /* ask "in what direction?" */
49 if (!getdir((char *)0)) {
50 if (obj->oclass == COIN_CLASS) {
58 if(obj->oclass == COIN_CLASS) return(throw_gold(obj));
60 if (!getdir((char *)0)) {
61 /* obj might need to be merged back into the singular gold object */
68 Throwing money is usually for getting rid of it when
69 a leprechaun approaches, or for bribing an oncoming
70 angry monster. So throw the whole object.
72 If the money is in quiver, throw one coin at a time,
73 possibly using a sling.
75 if(obj->oclass == COIN_CLASS && obj != uquiver) return(throw_gold(obj));
78 if(!canletgo(obj,"throw"))
80 if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
81 pline("%s must be wielded before it can be thrown.",
85 if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) < STR19(25))
86 || (obj->otyp == BOULDER && !throws_rocks(youmonst.data))) {
87 pline("It's too heavy.");
90 if(!u.dx && !u.dy && !u.dz) {
91 You("cannot throw an object at yourself.");
95 if (!uarmg && !Stone_resistance && (obj->otyp == CORPSE &&
96 touch_petrifies(&mons[obj->corpsenm]))) {
97 You("throw the %s corpse with your bare %s.",
98 mons[obj->corpsenm].mname, body_part(HAND));
99 Sprintf(killer_buf, "%s corpse", an(mons[obj->corpsenm].mname));
100 instapetrify(killer_buf);
107 /* Multishot calculations
109 skill = objects[obj->otyp].oc_skill;
110 if ((ammo_and_launcher(obj, uwep) || skill == P_DAGGER ||
111 skill == -P_DART || skill == -P_SHURIKEN) &&
112 !(Confusion || Stunned)) {
113 /* Bonus if the player is proficient in this weapon... */
114 switch (P_SKILL(weapon_type(obj))) {
115 default: break; /* No bonus */
116 case P_SKILLED: multishot++; break;
117 case P_EXPERT: multishot += 2; break;
119 /* ...or is using a special weapon for their role... */
120 switch (Role_switch) {
125 if (skill == P_DAGGER) multishot++;
128 if (obj->otyp == YA && uwep && uwep->otyp == YUMI) multishot++;
131 break; /* No bonus */
133 /* ...or using their race's special bow */
134 switch (Race_switch) {
136 if (obj->otyp == ELVEN_ARROW && uwep &&
137 uwep->otyp == ELVEN_BOW) multishot++;
140 if (obj->otyp == ORCISH_ARROW && uwep &&
141 uwep->otyp == ORCISH_BOW) multishot++;
144 break; /* No bonus */
148 if ((long)multishot > obj->quan) multishot = (int)obj->quan;
149 multishot = rnd(multishot);
150 if (shotlimit > 0 && multishot > shotlimit) multishot = shotlimit;
152 m_shot.s = ammo_and_launcher(obj,uwep) ? TRUE : FALSE;
153 /* give a message if shooting more than one, or if player
154 attempted to specify a count */
155 if (multishot > 1 || shotlimit > 0) {
156 /* "You shoot N arrows." or "You throw N daggers." */
158 m_shot.s ? "shoot" : "throw",
159 multishot, /* (might be 1 if player gave shotlimit) */
160 (multishot == 1) ? singular(obj, xname) : xname(obj));
163 wep_mask = obj->owornmask;
164 m_shot.o = obj->otyp;
165 m_shot.n = multishot;
166 for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
168 /* split this object off from its slot if necessary */
169 if (obj->quan > 1L) {
170 otmp = splitobj(obj, 1L);
174 remove_worn_item(otmp, FALSE);
177 throwit(otmp, wep_mask, twoweap);
179 m_shot.n = m_shot.i = 0;
180 m_shot.o = STRANGE_OBJECT;
190 register struct obj *obj;
194 * Since some characters shoot multiple missiles at one time,
195 * allow user to specify a count prefix for 'f' or 't' to limit
196 * number of items thrown (to avoid possibly hitting something
197 * behind target after killing it, or perhaps to conserve ammo).
199 * Prior to 3.3.0, command ``3t'' meant ``t(shoot) t(shoot) t(shoot)''
200 * and took 3 turns. Now it means ``t(shoot at most 3 missiles)''.
202 /* kludge to work around parse()'s pre-decrement of `multi' */
203 shotlimit = (multi || save_cm) ? multi + 1 : 0;
204 multi = 0; /* reset; it's been used up */
206 if (notake(youmonst.data)) {
207 You("are physically incapable of throwing anything.");
211 if(check_capacity((char *)0)) return(0);
212 obj = getobj(uslinging() ? bullets : toss_objs, "throw");
213 /* it is also possible to throw food */
214 /* (or jewels, or iron balls... ) */
217 return throw_obj(obj, shotlimit);
221 /* KMH -- Automatically fill quiver */
222 /* Suggested by Jeffrey Bay <jbay@convex.hp.com> */
226 struct obj *otmp, *oammo = 0, *omissile = 0, *omisc = 0, *altammo = 0;
231 /* Scan through the inventory */
232 for (otmp = invent; otmp; otmp = otmp->nobj) {
233 if (otmp->owornmask || otmp->oartifact || !otmp->dknown) {
235 } else if (otmp->otyp == ROCK ||
236 /* seen rocks or known flint or known glass */
237 (objects[otmp->otyp].oc_name_known &&
238 otmp->otyp == FLINT) ||
239 (objects[otmp->otyp].oc_name_known &&
240 otmp->oclass == GEM_CLASS &&
241 objects[otmp->otyp].oc_material == GLASS)) {
244 else if (ammo_and_launcher(otmp, uswapwep))
248 } else if (otmp->oclass == GEM_CLASS) {
249 ; /* skip non-rock gems--they're ammo but
250 player has to select them explicitly */
251 } else if (is_ammo(otmp)) {
252 if (ammo_and_launcher(otmp, uwep))
253 /* Ammo matched with launcher (bow and arrow, crossbow and bolt) */
255 else if (ammo_and_launcher(otmp, uswapwep))
258 /* Mismatched ammo (no better than an ordinary weapon) */
260 } else if (is_missile(otmp)) {
261 /* Missile (dart, shuriken, etc.) */
263 } else if (otmp->oclass == WEAPON_CLASS && throwing_weapon(otmp)) {
264 /* Ordinary weapon */
265 if (objects[otmp->otyp].oc_skill == P_DAGGER
273 /* Pick the best choice */
287 /* Throw from the quiver */
293 if (notake(youmonst.data)) {
294 You("are physically incapable of doing that.");
298 if(check_capacity((char *)0)) return(0);
300 if (!flags.autoquiver) {
301 /* Don't automatically fill the quiver */
302 You("have no ammunition readied!");
307 You("have nothing appropriate for your quiver!");
310 You("fill your quiver:");
311 prinv((char *)0, uquiver, 0L);
316 * Since some characters shoot multiple missiles at one time,
317 * allow user to specify a count prefix for 'f' or 't' to limit
318 * number of items thrown (to avoid possibly hitting something
319 * behind target after killing it, or perhaps to conserve ammo).
321 * The number specified can never increase the number of missiles.
322 * Using ``5f'' when the shooting skill (plus RNG) dictates launch
323 * of 3 projectiles will result in 3 being shot, not 5.
325 /* kludge to work around parse()'s pre-decrement of `multi' */
326 shotlimit = (multi || save_cm) ? multi + 1 : 0;
327 multi = 0; /* reset; it's been used up */
329 return throw_obj(uquiver, shotlimit);
334 * Object hits floor at hero's feet. Called from drop() and throwit().
338 register struct obj *obj;
340 if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
344 if (IS_ALTAR(levl[u.ux][u.uy].typ))
347 pline("%s hit%s the %s.", Doname2(obj),
348 (obj->quan == 1L) ? "s" : "", surface(u.ux,u.uy));
350 if (hero_breaks(obj, u.ux, u.uy, TRUE)) return;
351 if (ship_object(obj, u.ux, u.uy, FALSE)) return;
353 if (!u.uswallow) container_impact_dmg(obj);
357 * Walk a path from src_cc to dest_cc, calling a proc for each location
358 * except the starting one. If the proc returns FALSE, stop walking
359 * and return FALSE. If stopped early, dest_cc will be the location
360 * before the failed callback.
363 walk_path(src_cc, dest_cc, check_proc, arg)
366 boolean FDECL((*check_proc), (genericptr_t, int, int));
369 int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
370 boolean keep_going = TRUE;
372 /* Use Bresenham's Line Algorithm to walk from src to dest */
373 dx = dest_cc->x - src_cc->x;
374 dy = dest_cc->y - src_cc->y;
375 prev_x = x = src_cc->x;
376 prev_y = y = src_cc->y;
400 /* check for early exit condition */
401 if (!(keep_going = (*check_proc)(arg, x, y)))
414 /* check for early exit condition */
415 if (!(keep_going = (*check_proc)(arg, x, y)))
421 return TRUE; /* successful */
429 * Single step for the hero flying through the air from jumping, flying,
430 * etc. Called from hurtle() and jump() via walk_path(). We expect the
431 * argument to be a pointer to an integer -- the range -- which is
432 * used in the calculation of points off if we hit something.
434 * Bumping into monsters won't cause damage but will wake them and make
435 * them angry. Auto-pickup isn't done, since you don't have control over
436 * your movements at the time.
438 * Possible additions/changes:
439 * o really attack monster if we hit one
440 * o set stunned if we hit a wall or door
441 * o reset nomul when we stop
442 * o creepy feeling if pass through monster (if ever implemented...)
444 * o let jumps go over boulders
447 hurtle_step(arg, x, y)
451 int ox, oy, *range = (int *)arg;
454 boolean may_pass = TRUE;
458 You_feel("the spirits holding you back.");
460 } else if (!in_out_region(x, y)) {
462 } else if (*range == 0) {
463 return FALSE; /* previous step wants to stop now */
466 if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
467 if (IS_ROCK(levl[x][y].typ) || closed_door(x,y)) {
471 if (IS_TREE(levl[x][y].typ))
472 s = "bumping into a tree";
473 else if (IS_ROCK(levl[x][y].typ))
474 s = "bumping into a wall";
476 s = "bumping into a door";
477 losehp(rnd(2+*range), s, KILLED_BY);
480 if (levl[x][y].typ == IRONBARS) {
481 You("crash into some iron bars. Ouch!");
482 losehp(rnd(2+*range), "crashing into iron bars", KILLED_BY);
485 if ((obj = sobj_at(BOULDER,x,y)) != 0) {
486 You("bump into a %s. Ouch!", xname(obj));
487 losehp(rnd(2+*range), "bumping into a boulder", KILLED_BY);
491 /* did we hit a no-dig non-wall position? */
492 You("smack into something!");
493 losehp(rnd(2+*range), "touching the edge of the universe", KILLED_BY);
496 if ((u.ux - x) && (u.uy - y) &&
497 bad_rock(youmonst.data,u.ux,y) && bad_rock(youmonst.data,x,u.uy)) {
498 boolean too_much = (invent && (inv_weight() + weight_cap() > 600));
499 /* Move at a diagonal. */
500 if (bigmonst(youmonst.data) || too_much) {
501 You("%sget forcefully wedged into a crevice.",
502 too_much ? "and all your belongings " : "");
503 losehp(rnd(2+*range), "wedging into a narrow crevice", KILLED_BY);
509 if ((mon = m_at(x, y)) != 0) {
510 You("bump into %s.", a_monnam(mon));
514 if ((u.ux - x) && (u.uy - y) &&
515 bad_rock(youmonst.data,u.ux,y) && bad_rock(youmonst.data,x,u.uy)) {
516 /* Move at a diagonal. */
517 if (In_sokoban(&u.uz)) {
518 You("come to an abrupt halt!");
527 newsym(ox, oy); /* update old position */
528 vision_recalc(1); /* update for new position */
531 * Each trap should really trigger on the recoil if
532 * it would trigger during normal movement. However,
533 * not all the possible side-effects of this are
534 * tested [as of 3.4.0] so we trigger those that
535 * we have tested, and offer a message for the
536 * ones that we have not yet tested.
538 if ((ttmp = t_at(x, y)) != 0) {
539 if (ttmp->ttyp == MAGIC_PORTAL) {
542 } else if (ttmp->ttyp == FIRE_TRAP) {
544 } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT ||
545 ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) &&
547 /* Air currents overcome the recoil */
553 You("pass right over %s %s.",
554 (ttmp->ttyp == ARROW_TRAP) ? "an" : "a",
555 defsyms[trap_to_defsym(ttmp->ttyp)].explanation);
558 if (--*range < 0) /* make sure our range never goes negative */
566 mhurtle_step(arg, x, y)
570 struct monst *mon = (struct monst *)arg;
572 /* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
573 * rather than just stopping before.
575 if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
576 remove_monster(mon->mx, mon->my);
577 newsym(mon->mx, mon->my);
578 place_monster(mon, x, y);
579 newsym(mon->mx, mon->my);
588 * The player moves through the air for a few squares as a result of
589 * throwing or kicking something.
591 * dx and dy should be the direction of the hurtle, not of the original
592 * kick or throw and be only.
595 hurtle(dx, dy, range, verbose)
601 /* The chain is stretched vertically, so you shouldn't be able to move
602 * very far diagonally. The premise that you should be able to move one
603 * spot leads to calculations that allow you to only move one spot away
604 * from the ball, if you are levitating over the ball, or one spot
605 * towards the ball, if you are at the end of the chain. Rather than
606 * bother with all of that, assume that there is no slack in the chain
607 * for diagonal movement, give the player a message and return.
609 if(Punished && !carried(uball)) {
610 You_feel("a tug from the iron ball.");
613 } else if (u.utrap) {
614 You("are anchored by the %s.",
615 u.utraptype == TT_WEB ? "web" : u.utraptype == TT_LAVA ? "lava" :
616 u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) : "trap");
621 /* make sure dx and dy are [-1,0,1] */
625 if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
629 You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
630 /* if we're in the midst of shooting multiple projectiles, stop */
631 if (m_shot.i < m_shot.n) {
632 /* last message before hurtling was "you shoot N arrows" */
633 You("stop %sing after the first %s.",
634 m_shot.s ? "shoot" : "throw", m_shot.s ? "shot" : "toss");
635 m_shot.n = m_shot.i; /* make current shot be the last */
637 if (In_sokoban(&u.uz))
638 change_luck(-1); /* Sokoban guilt */
641 /* this setting of cc is only correct if dx and dy are [-1,0,1] only */
642 cc.x = u.ux + (dx * range);
643 cc.y = u.uy + (dy * range);
644 (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range);
647 /* Move a monster through the air for a few squares.
650 mhurtle(mon, dx, dy, range)
656 /* At the very least, debilitate the monster */
660 /* Is the monster stuck or too heavy to push?
661 * (very large monsters have too much inertia, even floaters and flyers)
663 if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped)
666 /* Make sure dx and dy are [-1,0,1] */
669 if(!range || (!dx && !dy)) return; /* paranoia */
671 /* Send the monster along the path */
674 cc.x = mon->mx + (dx * range);
675 cc.y = mon->my + (dy * range);
676 (void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t)mon);
681 check_shop_obj(obj, x, y, broken)
682 register struct obj *obj;
684 register boolean broken;
686 struct monst *shkp = shop_keeper(*u.ushops);
692 (void)stolen_value(obj, u.ux, u.uy,
693 (boolean)shkp->mpeaceful, FALSE);
694 subfrombill(obj, shkp);
700 if (!costly_spot(x, y) || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
701 /* thrown out of a shop or into a different shop */
703 (void)stolen_value(obj, u.ux, u.uy,
704 (boolean)shkp->mpeaceful, FALSE);
705 subfrombill(obj, shkp);
708 if (costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
709 if(obj->unpaid) subfrombill(obj, shkp);
710 else if(!(x == shkp->mx && y == shkp->my))
717 * Hero tosses an object upwards with appropriate consequences.
719 * Returns FALSE if the object is gone.
722 toss_up(obj, hitsroof)
727 /* note: obj->quan == 1 */
730 if (breaktest(obj)) {
731 pline("%s hits the %s.", Doname2(obj), ceiling(u.ux, u.uy));
732 breakmsg(obj, !Blind);
733 breakobj(obj, u.ux, u.uy, TRUE, TRUE);
740 pline("%s%s hits the %s, then falls back on top of your %s.",
741 Doname2(obj), almost, ceiling(u.ux,u.uy), body_part(HEAD));
743 /* object now hits you */
745 if (obj->oclass == POTION_CLASS) {
746 potionhit(&youmonst, obj, TRUE);
747 } else if (breaktest(obj)) {
748 int otyp = obj->otyp, ocorpsenm = obj->corpsenm;
751 /* need to check for blindness result prior to destroying obj */
752 blindinc = (otyp == CREAM_PIE || otyp == BLINDING_VENOM) &&
753 /* AT_WEAP is ok here even if attack type was AT_SPIT */
754 can_blnd(&youmonst, &youmonst, AT_WEAP, obj) ? rnd(25) : 0;
756 breakmsg(obj, !Blind);
757 breakobj(obj, u.ux, u.uy, TRUE, TRUE);
758 obj = 0; /* it's now gone */
761 if (touch_petrifies(&mons[ocorpsenm]) &&
762 !uarmh && !Stone_resistance &&
763 !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)))
767 pline("You've got it all over your %s!", body_part(FACE));
769 if (otyp == BLINDING_VENOM && !Blind)
770 pline("It blinds you!");
771 u.ucreamed += blindinc;
772 make_blinded(Blinded + (long)blindinc, FALSE);
773 if (!Blind) Your(vision_clears);
780 } else { /* neither potion nor other breaking object */
781 boolean less_damage = uarmh && is_metallic(uarmh), artimsg = FALSE;
782 int dmg = dmgval(obj, &youmonst);
785 /* need a fake die roll here; rn1(18,2) avoids 1 and 20 */
786 artimsg = artifact_hit((struct monst *)0, &youmonst,
787 obj, &dmg, rn1(18,2));
789 if (!dmg) { /* probably wasn't a weapon; base damage on weight */
790 dmg = (int) obj->owt / 100;
791 if (dmg < 1) dmg = 1;
792 else if (dmg > 6) dmg = 6;
793 if (youmonst.data == &mons[PM_SHADE] &&
794 objects[obj->otyp].oc_material != SILVER)
797 if (dmg > 1 && less_damage) dmg = 1;
798 if (dmg > 0) dmg += u.udaminc;
799 if (dmg < 0) dmg = 0; /* beware negative rings of increase damage */
800 if (Half_physical_damage) dmg = (dmg + 1) / 2;
803 if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) {
805 pline("Fortunately, you are wearing a hard helmet.");
806 } else if (flags.verbose &&
807 !(obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])))
808 Your("%s does not protect you.", xname(uarmh));
809 } else if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
810 if (!Stone_resistance &&
811 !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
813 killer_format = KILLED_BY;
814 killer = "elementary physics"; /* "what goes up..." */
815 You("turn to stone.");
816 if (obj) dropy(obj); /* bypass most of hitfloor() */
818 return obj ? TRUE : FALSE;
822 losehp(dmg, "falling object", KILLED_BY_AN);
827 /* return true for weapon meant to be thrown; excludes ammo */
832 return (is_missile(obj) || is_spear(obj) ||
833 /* daggers and knife (excludes scalpel) */
834 (is_blade(obj) && !is_sword(obj) &&
835 (objects[obj->otyp].oc_dir & PIERCE)) ||
836 /* special cases [might want to add AXE] */
837 obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
840 /* the currently thrown object is returning to you (not for boomerangs) */
842 sho_obj_return_to_u(obj)
845 /* might already be our location (bounced off a wall) */
846 if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
847 int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
849 tmp_at(DISP_FLASH, obj_to_glyph(obj));
850 while(x != u.ux || y != u.uy) {
853 x -= u.dx; y -= u.dy;
860 throwit(obj, wep_mask, twoweap)
861 register struct obj *obj;
862 long wep_mask; /* used to re-equip returning boomerang */
863 boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
865 register struct monst *mon;
866 register int range, urange;
867 boolean impaired = (Confusion || Stunned || Blind ||
868 Hallucination || Fumbling);
870 if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
871 boolean slipok = TRUE;
872 if (ammo_and_launcher(obj, uwep))
873 pline("%s!", Tobjnam(obj, "misfire"));
875 /* only slip if it's greased or meant to be thrown */
876 if (obj->greased || throwing_weapon(obj))
877 /* BUG: this message is grammatically incorrect if obj has
878 a plural name; greased gloves or boots for instance. */
879 pline("%s as you throw it!", Tobjnam(obj, "slip"));
885 if (!u.dx && !u.dy) u.dz = 1;
890 if ((u.dx || u.dy || (u.dz < 1)) &&
891 calc_capacity((int)obj->owt) > SLT_ENCUMBER &&
892 (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
893 : (u.uhp < 10 && u.uhp != u.uhpmax)) &&
894 obj->owt > (unsigned)((Upolyd ? u.mh : u.uhp) * 2) &&
895 !Is_airlevel(&u.uz)) {
896 You("have so little stamina, %s drops from your grasp.",
898 exercise(A_CON, FALSE);
910 if (u.dz < 0 && Role_if(PM_VALKYRIE) &&
911 obj->oartifact == ART_MJOLLNIR && !impaired) {
912 pline("%s the %s and returns to your hand!",
913 Tobjnam(obj, "hit"), ceiling(u.ux,u.uy));
915 (void) encumber_msg();
918 } else if (u.dz < 0 && !Is_airlevel(&u.uz) &&
919 !Underwater && !Is_waterlevel(&u.uz)) {
920 (void) toss_up(obj, rn2(5));
924 thrownobj = (struct obj*)0;
927 } else if(obj->otyp == BOOMERANG && !Underwater) {
928 if(Is_airlevel(&u.uz) || Levitation)
929 hurtle(-u.dx, -u.dy, 1, TRUE);
930 mon = boomhit(u.dx, u.dy);
931 if(mon == &youmonst) { /* the thing was caught */
932 exercise(A_DEX, TRUE);
934 (void) encumber_msg();
935 if (wep_mask && !(obj->owornmask & wep_mask)) {
936 setworn(obj, wep_mask);
939 thrownobj = (struct obj*)0;
943 urange = (int)(ACURRSTR)/2;
944 /* balls are easy to throw or at least roll */
945 /* also, this insures the maximum range of a ball is greater
946 * than 1, so the effects from throwing attached balls are
949 if (obj->otyp == HEAVY_IRON_BALL)
950 range = urange - (int)(obj->owt/100);
952 range = urange - (int)(obj->owt/40);
954 if (u.ustuck) range = 1;
955 else if (range >= 5) range = 5;
957 if (range < 1) range = 1;
960 if (ammo_and_launcher(obj, uwep))
962 else if (obj->oclass != GEM_CLASS)
966 if (Is_airlevel(&u.uz) || Levitation) {
967 /* action, reaction... */
969 if(urange < 1) urange = 1;
971 if(range < 1) range = 1;
974 if (obj->otyp == BOULDER)
975 range = 20; /* you must be giant */
976 else if (obj->oartifact == ART_MJOLLNIR)
977 range = (range + 1) / 2; /* it's heavy */
978 else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
981 if (Underwater) range = 1;
983 mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
984 (int FDECL((*),(MONST_P,OBJ_P)))0,
985 (int FDECL((*),(OBJ_P,OBJ_P)))0,
988 /* have to do this after bhit() so u.ux & u.uy are correct */
989 if(Is_airlevel(&u.uz) || Levitation)
990 hurtle(-u.dx, -u.dy, urange, TRUE);
997 obj->where == OBJ_MINVENT && obj->ocarry == mon) {
998 thrownobj = (struct obj*)0;
999 return; /* alert shk caught it */
1001 (void) snuff_candle(obj);
1002 notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
1003 obj_gone = thitmonst(mon, obj);
1004 /* Monster may have been tamed; this frees old mon */
1005 mon = m_at(bhitpos.x, bhitpos.y);
1007 /* [perhaps this should be moved into thitmonst or hmon] */
1008 if (mon && mon->isshk &&
1009 (!inside_shop(u.ux, u.uy) ||
1010 !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)))
1013 if (obj_gone) return;
1017 /* ball is not picked up by monster */
1018 if (obj != uball) (void) mpickobj(u.ustuck,obj);
1020 /* the code following might become part of dropy() */
1021 if (obj->oartifact == ART_MJOLLNIR &&
1022 Role_if(PM_VALKYRIE) && rn2(100)) {
1023 /* we must be wearing Gauntlets of Power to get here */
1024 sho_obj_return_to_u(obj); /* display its flight */
1026 if (!impaired && rn2(100)) {
1027 pline("%s to your hand!", Tobjnam(obj, "return"));
1029 (void) encumber_msg();
1031 u.twoweap = twoweap;
1032 if(cansee(bhitpos.x, bhitpos.y))
1033 newsym(bhitpos.x,bhitpos.y);
1037 pline(Blind ? "%s lands %s your %s." :
1038 "%s back to you, landing %s your %s.",
1039 Blind ? Something : Tobjnam(obj, "return"),
1040 Levitation ? "beneath" : "at",
1041 makeplural(body_part(FOOT)));
1044 pline(Blind ? "%s your %s!" :
1045 "%s back toward you, hitting your %s!",
1046 Tobjnam(obj, Blind ? "hit" : "fly"),
1048 (void) artifact_hit((struct monst *)0,
1049 &youmonst, obj, &dmg, 0);
1050 losehp(dmg, xname(obj),
1051 obj_is_pname(obj) ? KILLED_BY : KILLED_BY_AN);
1053 if (ship_object(obj, u.ux, u.uy, FALSE)) {
1054 thrownobj = (struct obj*)0;
1059 thrownobj = (struct obj*)0;
1063 if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
1065 tmp_at(DISP_FLASH, obj_to_glyph(obj));
1066 tmp_at(bhitpos.x, bhitpos.y);
1068 tmp_at(DISP_END, 0);
1069 breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
1070 breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
1073 if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return;
1074 obj_no_longer_held(obj);
1075 if (mon && mon->isshk && is_pick(obj)) {
1076 if (cansee(bhitpos.x, bhitpos.y))
1077 pline("%s snatches up %s.",
1078 Monnam(mon), the(xname(obj)));
1080 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1081 (void) mpickobj(mon, obj); /* may merge and free obj */
1082 thrownobj = (struct obj*)0;
1085 (void) snuff_candle(obj);
1086 if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) {
1087 thrownobj = (struct obj*)0;
1090 thrownobj = (struct obj*)0;
1091 place_object(obj, bhitpos.x, bhitpos.y);
1092 if(*u.ushops && obj != uball)
1093 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1097 drop_ball(bhitpos.x, bhitpos.y);
1098 if (cansee(bhitpos.x, bhitpos.y))
1099 newsym(bhitpos.x,bhitpos.y);
1100 if (obj_sheds_light(obj))
1101 vision_full_recalc = 1;
1102 if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ))
1103 container_impact_dmg(obj);
1107 /* an object may hit a monster; various factors adjust the chance of hitting */
1109 omon_adj(mon, obj, mon_notices)
1112 boolean mon_notices;
1116 /* size of target affects the chance of hitting */
1117 tmp += (mon->data->msize - MZ_MEDIUM); /* -2..+5 */
1118 /* sleeping target is more likely to be hit */
1119 if (mon->msleeping) {
1121 if (mon_notices) mon->msleeping = 0;
1123 /* ditto for immobilized target */
1124 if (!mon->mcanmove || !mon->data->mmove) {
1126 if (mon_notices && mon->data->mmove && !rn2(10)) {
1131 /* some objects are more likely to hit than others */
1132 switch (obj->otyp) {
1133 case HEAVY_IRON_BALL:
1134 if (obj != uball) tmp += 2;
1140 if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
1141 obj->oclass == GEM_CLASS)
1142 tmp += hitval(obj, mon);
1148 /* thrown object misses target monster */
1154 const char *missile = mshot_xname(obj);
1156 /* If the target can't be seen or doesn't look like a valid target,
1157 avoid "the arrow misses it," or worse, "the arrows misses the mimic."
1158 An attentive player will still notice that this is different from
1159 an arrow just landing short of any target (no message in that case),
1160 so will realize that there is a valid target here anyway. */
1161 if (!canseemon(mon) || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER))
1162 pline("%s %s.", The(missile), otense(obj, "miss"));
1165 if (!rn2(3)) wakeup(mon);
1169 #define quest_arti_hits_leader(obj,mon) \
1170 (obj->oartifact && is_quest_artifact(obj) && (mon->data->msound == MS_LEADER))
1173 * Object thrown by player arrives at monster's location.
1174 * Return 1 if obj has disappeared or otherwise been taken care of,
1175 * 0 if caller must take care of it.
1179 register struct monst *mon;
1180 register struct obj *obj;
1182 register int tmp; /* Base chance to hit */
1183 register int disttmp; /* distance modifier */
1184 int otyp = obj->otyp;
1185 boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
1187 /* Differences from melee weapons:
1189 * Dex still gives a bonus, but strength does not.
1190 * Polymorphed players lacking attacks may still throw.
1191 * There's a base -1 to hit.
1192 * No bonuses for fleeing or stunned targets (they don't dodge
1193 * melee blows as readily, but dodging arrows is hard anyway).
1194 * Not affected by traps, etc.
1195 * Certain items which don't in themselves do damage ignore tmp.
1196 * Distance and monster size affect chance to hit.
1198 tmp = -1 + Luck + find_mac(mon) + u.uhitinc +
1199 maybe_polyd(youmonst.data->mlevel, u.ulevel);
1200 if (ACURR(A_DEX) < 4) tmp -= 3;
1201 else if (ACURR(A_DEX) < 6) tmp -= 2;
1202 else if (ACURR(A_DEX) < 8) tmp -= 1;
1203 else if (ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
1205 /* Modify to-hit depending on distance; but keep it sane.
1206 * Polearms get a distance penalty even when wielded; it's
1207 * hard to hit at a distance.
1209 disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
1210 if(disttmp < -4) disttmp = -4;
1213 /* gloves are a hinderance to proper use of bows */
1214 if (uarmg && uwep && objects[uwep->otyp].oc_skill == P_BOW) {
1215 switch (uarmg->otyp) {
1216 case GAUNTLETS_OF_POWER: /* metal */
1219 case GAUNTLETS_OF_FUMBLING:
1222 case LEATHER_GLOVES:
1223 case GAUNTLETS_OF_DEXTERITY:
1226 impossible("Unknown type of gloves (%d)", uarmg->otyp);
1231 tmp += omon_adj(mon, obj, TRUE);
1232 if (is_orc(mon->data) && maybe_polyd(is_elf(youmonst.data),
1235 if (guaranteed_hit) {
1236 tmp += 1000; /* Guaranteed hit */
1239 if (obj->oclass == GEM_CLASS && is_unicorn(mon->data)) {
1241 pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
1244 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1245 return gem_accept(mon, obj);
1249 /* don't make game unwinnable if naive player throws artifact
1251 if (quest_arti_hits_leader(obj, mon)) {
1252 /* not wakeup(), which angers non-tame monsters */
1254 mon->mstrategy &= ~STRAT_WAITMASK;
1256 if (mon->mcanmove) {
1257 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1258 if (mon->mpeaceful) {
1259 boolean next2u = monnear(mon, u.ux, u.uy);
1261 finish_quest(obj); /* acknowledge quest completion */
1262 pline("%s %s %s back to you.", Monnam(mon),
1263 (next2u ? "hands" : "tosses"), the(xname(obj)));
1264 if (!next2u) sho_obj_return_to_u(obj);
1265 obj = addinv(obj); /* back into your inventory */
1266 (void) encumber_msg();
1268 /* angry leader caught it and isn't returning it */
1269 (void) mpickobj(mon, obj);
1271 return 1; /* caller doesn't need to place it */
1276 if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
1277 obj->oclass == GEM_CLASS) {
1279 if (!ammo_and_launcher(obj, uwep)) {
1282 tmp += uwep->spe - greatest_erosion(uwep);
1283 tmp += weapon_hit_bonus(uwep);
1284 if (uwep->oartifact) tmp += spec_abon(uwep, mon);
1286 * Elves and Samurais are highly trained w/bows,
1287 * especially their own special types of bow.
1288 * Polymorphing won't make you a bow expert.
1290 if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI)) &&
1291 (!Upolyd || your_race(youmonst.data)) &&
1292 objects[uwep->otyp].oc_skill == P_BOW) {
1294 if (Race_if(PM_ELF) && uwep->otyp == ELVEN_BOW)
1296 else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI)
1301 if (otyp == BOOMERANG) /* arbitrary */
1303 else if (throwing_weapon(obj)) /* meant to be thrown */
1305 else /* not meant to be thrown */
1307 /* we know we're dealing with a weapon or weptool handled
1308 by WEAPON_SKILLS once ammo objects have been excluded */
1309 tmp += weapon_hit_bonus(obj);
1312 if (tmp >= rnd(20)) {
1313 if (hmon(mon,obj,1)) { /* mon still alive */
1314 cutworm(mon, bhitpos.x, bhitpos.y, obj);
1316 exercise(A_DEX, TRUE);
1317 /* projectiles other than magic stones
1318 sometimes disappear when thrown */
1319 if (objects[otyp].oc_skill < P_NONE &&
1320 objects[otyp].oc_skill > -P_BOOMERANG &&
1321 !objects[otyp].oc_magic) {
1322 /* we were breaking 2/3 of everything unconditionally.
1323 * we still don't want anything to survive unconditionally,
1324 * but we need ammo to stay around longer on average.
1327 chance = 3 + greatest_erosion(obj) - obj->spe;
1329 broken = rn2(chance);
1332 if (obj->blessed && !rnl(4))
1337 check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
1338 obfree(obj, (struct obj *)0);
1342 passive_obj(mon, obj, (struct attack *)0);
1347 } else if (otyp == HEAVY_IRON_BALL) {
1348 exercise(A_STR, TRUE);
1349 if (tmp >= rnd(20)) {
1350 int was_swallowed = guaranteed_hit;
1352 exercise(A_DEX, TRUE);
1353 if (!hmon(mon,obj,1)) { /* mon killed */
1354 if (was_swallowed && !u.uswallow && obj == uball)
1355 return 1; /* already did placebc() */
1361 } else if (otyp == BOULDER) {
1362 exercise(A_STR, TRUE);
1363 if (tmp >= rnd(20)) {
1364 exercise(A_DEX, TRUE);
1365 (void) hmon(mon,obj,1);
1370 } else if ((otyp == EGG || otyp == CREAM_PIE ||
1371 otyp == BLINDING_VENOM || otyp == ACID_VENOM) &&
1372 (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1373 (void) hmon(mon, obj, 1);
1374 return 1; /* hmon used it up */
1376 } else if (obj->oclass == POTION_CLASS &&
1377 (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1378 potionhit(mon, obj, TRUE);
1381 } else if (befriend_with_obj(mon->data, obj) ||
1382 (mon->mtame && dogfood(mon, obj) <= ACCFOOD)) {
1383 if (tamedog(mon, obj))
1384 return 1; /* obj is gone */
1386 /* not tmiss(), which angers non-tame monsters */
1387 miss(xname(obj), mon);
1389 mon->mstrategy &= ~STRAT_WAITMASK;
1391 } else if (guaranteed_hit) {
1392 /* this assumes that guaranteed_hit is due to swallowing */
1394 if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
1395 if (is_animal(u.ustuck->data)) {
1396 minstapetrify(u.ustuck, TRUE);
1397 /* Don't leave a cockatrice corpse available in a statue */
1404 pline("%s into %s %s.",
1405 Tobjnam(obj, "vanish"), s_suffix(mon_nam(mon)),
1406 is_animal(u.ustuck->data) ? "entrails" : "currents");
1415 gem_accept(mon, obj)
1416 register struct monst *mon;
1417 register struct obj *obj;
1420 boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
1421 boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
1423 static NEARDATA const char nogood[] = " is not interested in your junk.";
1424 static NEARDATA const char acceptgift[] = " accepts your gift.";
1425 static NEARDATA const char maybeluck[] = " hesitatingly";
1426 static NEARDATA const char noluck[] = " graciously";
1427 static NEARDATA const char addluck[] = " gratefully";
1429 Strcpy(buf,Monnam(mon));
1433 /* object properly identified */
1434 if(obj->dknown && objects[obj->otyp].oc_name_known) {
1437 Strcat(buf,addluck);
1440 Strcat(buf,maybeluck);
1441 change_luck(rn2(7)-3);
1447 /* making guesses */
1448 } else if(obj->onamelth || objects[obj->otyp].oc_uname) {
1451 Strcat(buf,addluck);
1454 Strcat(buf,maybeluck);
1455 change_luck(rn2(3)-1);
1461 /* value completely unknown to @ */
1465 Strcat(buf,addluck);
1468 Strcat(buf,maybeluck);
1469 change_luck(rn2(3)-1);
1475 Strcat(buf,acceptgift);
1476 if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
1477 (void) mpickobj(mon, obj); /* may merge and free obj */
1481 if(!Blind) pline("%s", buf);
1482 if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
1487 * Comments about the restructuring of the old breaks() routine.
1489 * There are now three distinct phases to object breaking:
1490 * breaktest() - which makes the check/decision about whether the
1491 * object is going to break.
1492 * breakmsg() - which outputs a message about the breakage,
1493 * appropriate for that particular object. Should
1494 * only be called after a positve breaktest().
1495 * on the object and, if it going to be called,
1496 * it must be called before calling breakobj().
1497 * Calling breakmsg() is optional.
1498 * breakobj() - which actually does the breakage and the side-effects
1499 * of breaking that particular object. This should
1500 * only be called after a positive breaktest() on the
1503 * Each of the above routines is currently static to this source module.
1504 * There are two routines callable from outside this source module which
1505 * perform the routines above in the correct sequence.
1507 * hero_breaks() - called when an object is to be broken as a result
1508 * of something that the hero has done. (throwing it,
1510 * breaks() - called when an object is to be broken for some
1511 * reason other than the hero doing something to it.
1515 * The hero causes breakage of an object (throwing, dropping it, etc.)
1516 * Return 0 if the object didn't break, 1 if the object broke.
1519 hero_breaks(obj, x, y, from_invent)
1521 xchar x, y; /* object location (ox, oy may not be right) */
1522 boolean from_invent; /* thrown or dropped by player; maybe on shop bill */
1524 boolean in_view = !Blind;
1525 if (!breaktest(obj)) return 0;
1526 breakmsg(obj, in_view);
1527 breakobj(obj, x, y, TRUE, from_invent);
1532 * The object is going to break for a reason other than the hero doing
1534 * Return 0 if the object doesn't break, 1 if the object broke.
1539 xchar x, y; /* object location (ox, oy may not be right) */
1541 boolean in_view = Blind ? FALSE : cansee(x, y);
1543 if (!breaktest(obj)) return 0;
1544 breakmsg(obj, in_view);
1545 breakobj(obj, x, y, FALSE, FALSE);
1550 * Unconditionally break an object. Assumes all resistance checks
1551 * and break messages have been delivered prior to getting here.
1554 breakobj(obj, x, y, hero_caused, from_invent)
1556 xchar x, y; /* object location (ox, oy may not be right) */
1557 boolean hero_caused; /* is this the hero's fault? */
1558 boolean from_invent;
1560 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1565 case POT_WATER: /* really, all potions */
1566 if (obj->otyp == POT_OIL && obj->lamplit) {
1567 splatter_burning_oil(x,y);
1568 } else if (distu(x,y) <= 2) {
1569 if (!breathless(youmonst.data) || haseyes(youmonst.data)) {
1570 if (obj->otyp != POT_WATER) {
1571 if (!breathless(youmonst.data))
1572 /* [what about "familiar odor" when known?] */
1573 You("smell a peculiar odor...");
1575 int numeyes = eyecount(youmonst.data);
1577 (numeyes == 1) ? body_part(EYE) :
1578 makeplural(body_part(EYE)),
1579 (numeyes == 1) ? "s" : "");
1585 /* monster breathing isn't handled... [yet?] */
1588 /* breaking your own eggs is bad luck */
1589 if (hero_caused && obj->spe && obj->corpsenm >= LOW_PM)
1590 change_luck((schar) -min(obj->quan, 5L));
1596 check_shop_obj(obj, x, y, TRUE);
1597 } else if (!obj->no_charge && costly_spot(x, y)) {
1598 /* it is assumed that the obj is a floor-object */
1599 char *o_shop = in_rooms(x, y, SHOPBASE);
1600 struct monst *shkp = shop_keeper(*o_shop);
1602 if (shkp) { /* (implies *o_shop != '\0') */
1603 static NEARDATA long lastmovetime = 0L;
1604 static NEARDATA boolean peaceful_shk = FALSE;
1605 /* We want to base shk actions on her peacefulness
1606 at start of this turn, so that "simultaneous"
1607 multiple breakage isn't drastically worse than
1608 single breakage. (ought to be done via ESHK) */
1609 if (moves != lastmovetime)
1610 peaceful_shk = shkp->mpeaceful;
1611 if (stolen_value(obj, x, y, peaceful_shk, FALSE) > 0L &&
1612 (*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy)) &&
1613 moves != lastmovetime) make_angry_shk(shkp, x, y);
1614 lastmovetime = moves;
1622 * Check to see if obj is going to break, but don't actually break it.
1623 * Return 0 if the object isn't going to break, 1 if it is.
1629 if (obj_resists(obj, 1, 99)) return 0;
1630 if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact &&
1631 obj->oclass != GEM_CLASS)
1633 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1635 case EXPENSIVE_CAMERA:
1637 case POT_WATER: /* really, all potions */
1642 case BLINDING_VENOM:
1650 breakmsg(obj, in_view)
1654 const char *to_pieces;
1657 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1658 default: /* glass or crystal wand */
1659 if (obj->oclass != WAND_CLASS)
1660 impossible("breaking odd object?");
1661 case CRYSTAL_PLATE_MAIL:
1666 case EXPENSIVE_CAMERA:
1668 to_pieces = " into a thousand pieces";
1670 case POT_WATER: /* really, all potions */
1672 You_hear("%s shatter!", something);
1674 pline("%s shatter%s%s!", Doname2(obj),
1675 (obj->quan==1) ? "s" : "", to_pieces);
1682 if (in_view) pline("What a mess!");
1685 case BLINDING_VENOM:
1695 int range, odx, ody;
1697 long zorks = obj->quan;
1699 register struct monst *mon;
1701 if(!u.dx && !u.dy && !u.dz) {
1703 u.ugold += obj->quan;
1707 You("cannot throw gold at yourself.");
1714 pline(is_animal(u.ustuck->data) ?
1715 "%s in the %s's entrails." : "%s into %s.",
1717 "The gold disappears", mon_nam(u.ustuck));
1718 u.ustuck->mgold += zorks;
1721 "The money disappears", mon_nam(u.ustuck));
1722 add_to_minv(u.ustuck, obj);
1728 if (u.dz < 0 && !Is_airlevel(&u.uz) &&
1729 !Underwater && !Is_waterlevel(&u.uz)) {
1730 pline_The("gold hits the %s, then falls back on top of your %s.",
1731 ceiling(u.ux,u.uy), body_part(HEAD));
1732 /* some self damage? */
1733 if(uarmh) pline("Fortunately, you are wearing a helmet!");
1738 /* consistent with range for normal objects */
1739 range = (int)((ACURRSTR)/2 - obj->owt/40);
1741 /* see if the gold has a place to move into */
1744 if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
1748 mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
1749 (int FDECL((*),(MONST_P,OBJ_P)))0,
1750 (int FDECL((*),(OBJ_P,OBJ_P)))0,
1753 if (ghitm(mon, obj)) /* was it caught? */
1756 if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
1762 if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
1764 pline_The("gold hits the %s.", surface(bhitpos.x,bhitpos.y));
1765 place_object(obj,bhitpos.x,bhitpos.y);
1766 if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
1768 newsym(bhitpos.x,bhitpos.y);