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. */
4
5/* Contains code for 't' (throw) */
6
7#include "hack.h"
8#include "edog.h"
9
10STATIC_DCL int FDECL(throw_obj, (struct obj *,int));
11STATIC_DCL void NDECL(autoquiver);
12STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *));
13STATIC_DCL void FDECL(tmiss, (struct obj *, struct monst *));
14STATIC_DCL int FDECL(throw_gold, (struct obj *));
15STATIC_DCL void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
16STATIC_DCL void FDECL(breakobj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P,BOOLEAN_P));
17STATIC_DCL void FDECL(breakmsg, (struct obj *,BOOLEAN_P));
18STATIC_DCL boolean FDECL(toss_up,(struct obj *, BOOLEAN_P));
19STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
20STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj *obj));
21STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t,int,int));
22
23
24static 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) */
27static NEARDATA const char bullets[] =
28	{ ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, GEM_CLASS, 0 };
29
30struct obj *thrownobj = 0;	/* tracks an object until it lands */
31
32extern boolean notonhead;	/* for long worms */
33
34
35/* Throw the selected object, asking for direction */
36STATIC_OVL int
37throw_obj(obj, shotlimit)
38struct obj *obj;
39int shotlimit;
40{
41	struct obj *otmp;
42	int multishot = 1;
43	schar skill;
44	long wep_mask;
45	boolean twoweap;
46
47	/* ask "in what direction?" */
48#ifndef GOLDOBJ
49	if (!getdir((char *)0)) {
50		if (obj->oclass == COIN_CLASS) {
51		    u.ugold += obj->quan;
52		    flags.botl = 1;
53		    dealloc_obj(obj);
54		}
55		return(0);
56	}
57
58	if(obj->oclass == COIN_CLASS) return(throw_gold(obj));
59#else
60	if (!getdir((char *)0)) {
61	    /* obj might need to be merged back into the singular gold object */
62	    freeinv(obj);
63	    addinv(obj);
64	    return(0);
65	}
66
67        /*
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.
71
72          If the money is in quiver, throw one coin at a time,
73          possibly using a sling.
74        */
75	if(obj->oclass == COIN_CLASS && obj != uquiver) return(throw_gold(obj));
76#endif
77
78	if(!canletgo(obj,"throw"))
79		return(0);
80	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
81	    pline("%s must be wielded before it can be thrown.",
82		The(xname(obj)));
83		return(0);
84	}
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.");
88		return(1);
89	}
90	if(!u.dx && !u.dy && !u.dz) {
91		You("cannot throw an object at yourself.");
92		return(0);
93	}
94	u_wipe_engr(2);
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);
101	}
102	if (welded(obj)) {
103		weldmsg(obj);
104		return 1;
105	}
106
107	/* Multishot calculations
108	 */
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;
118	    }
119	    /* ...or is using a special weapon for their role... */
120	    switch (Role_switch) {
121	    case PM_RANGER:
122		multishot++;
123		break;
124	    case PM_ROGUE:
125		if (skill == P_DAGGER) multishot++;
126		break;
127	    case PM_SAMURAI:
128		if (obj->otyp == YA && uwep && uwep->otyp == YUMI) multishot++;
129		break;
130	    default:
131		break;	/* No bonus */
132	    }
133	    /* ...or using their race's special bow */
134	    switch (Race_switch) {
135	    case PM_ELF:
136		if (obj->otyp == ELVEN_ARROW && uwep &&
137				uwep->otyp == ELVEN_BOW) multishot++;
138		break;
139	    case PM_ORC:
140		if (obj->otyp == ORCISH_ARROW && uwep &&
141				uwep->otyp == ORCISH_BOW) multishot++;
142		break;
143	    default:
144		break;	/* No bonus */
145	    }
146	}
147
148	if ((long)multishot > obj->quan) multishot = (int)obj->quan;
149	multishot = rnd(multishot);
150	if (shotlimit > 0 && multishot > shotlimit) multishot = shotlimit;
151
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." */
157	    You("%s %d %s.",
158		m_shot.s ? "shoot" : "throw",
159		multishot,	/* (might be 1 if player gave shotlimit) */
160		(multishot == 1) ? singular(obj, xname) :  xname(obj));
161	}
162
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++) {
167	    twoweap = u.twoweap;
168	    /* split this object off from its slot if necessary */
169	    if (obj->quan > 1L) {
170		otmp = splitobj(obj, 1L);
171	    } else {
172		otmp = obj;
173		if (otmp->owornmask)
174		    remove_worn_item(otmp, FALSE);
175	    }
176	    freeinv(otmp);
177	    throwit(otmp, wep_mask, twoweap);
178	}
179	m_shot.n = m_shot.i = 0;
180	m_shot.o = STRANGE_OBJECT;
181	m_shot.s = FALSE;
182
183	return 1;
184}
185
186
187int
188dothrow()
189{
190	register struct obj *obj;
191	int shotlimit;
192
193	/*
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).
198	 *
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)''.
201	 */
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 */
205
206	if (notake(youmonst.data)) {
207	    You("are physically incapable of throwing anything.");
208	    return 0;
209	}
210
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... ) */
215
216	if (!obj) return(0);
217	return throw_obj(obj, shotlimit);
218}
219
220
221/* KMH -- Automatically fill quiver */
222/* Suggested by Jeffrey Bay <jbay@convex.hp.com> */
223static void
224autoquiver()
225{
226	struct obj *otmp, *oammo = 0, *omissile = 0, *omisc = 0, *altammo = 0;
227
228	if (uquiver)
229	    return;
230
231	/* Scan through the inventory */
232	for (otmp = invent; otmp; otmp = otmp->nobj) {
233	    if (otmp->owornmask || otmp->oartifact || !otmp->dknown) {
234		;	/* Skip it */
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)) {
242		if (uslinging())
243		    oammo = otmp;
244		else if (ammo_and_launcher(otmp, uswapwep))
245		    altammo = otmp;
246		else if (!omisc)
247		    omisc = otmp;
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) */
254		    oammo = otmp;
255		else if (ammo_and_launcher(otmp, uswapwep))
256		    altammo = otmp;
257		else
258		    /* Mismatched ammo (no better than an ordinary weapon) */
259		    omisc = otmp;
260	    } else if (is_missile(otmp)) {
261		/* Missile (dart, shuriken, etc.) */
262		omissile = otmp;
263	    } else if (otmp->oclass == WEAPON_CLASS && throwing_weapon(otmp)) {
264		/* Ordinary weapon */
265		if (objects[otmp->otyp].oc_skill == P_DAGGER
266			&& !omissile)
267		    omissile = otmp;
268		else
269		    omisc = otmp;
270	    }
271	}
272
273	/* Pick the best choice */
274	if (oammo)
275	    setuqwep(oammo);
276	else if (omissile)
277	    setuqwep(omissile);
278	else if (altammo)
279	    setuqwep(altammo);
280	else if (omisc)
281	    setuqwep(omisc);
282
283	return;
284}
285
286
287/* Throw from the quiver */
288int
289dofire()
290{
291	int shotlimit;
292
293	if (notake(youmonst.data)) {
294	    You("are physically incapable of doing that.");
295	    return 0;
296	}
297
298	if(check_capacity((char *)0)) return(0);
299	if (!uquiver) {
300		if (!flags.autoquiver) {
301			/* Don't automatically fill the quiver */
302			You("have no ammunition readied!");
303			return(dothrow());
304		}
305		autoquiver();
306		if (!uquiver) {
307			You("have nothing appropriate for your quiver!");
308			return(dothrow());
309		} else {
310			You("fill your quiver:");
311			prinv((char *)0, uquiver, 0L);
312		}
313	}
314
315	/*
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).
320	 *
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.
324	 */
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 */
328
329	return throw_obj(uquiver, shotlimit);
330}
331
332
333/*
334 * Object hits floor at hero's feet.  Called from drop() and throwit().
335 */
336void
337hitfloor(obj)
338register struct obj *obj;
339{
340	if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
341		dropy(obj);
342		return;
343	}
344	if (IS_ALTAR(levl[u.ux][u.uy].typ))
345		doaltarobj(obj);
346	else
347		pline("%s hit%s the %s.", Doname2(obj),
348		      (obj->quan == 1L) ? "s" : "", surface(u.ux,u.uy));
349
350	if (hero_breaks(obj, u.ux, u.uy, TRUE)) return;
351	if (ship_object(obj, u.ux, u.uy, FALSE)) return;
352	dropy(obj);
353	if (!u.uswallow) container_impact_dmg(obj);
354}
355
356/*
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.
361 */
362boolean
363walk_path(src_cc, dest_cc, check_proc, arg)
364    coord *src_cc;
365    coord *dest_cc;
366    boolean FDECL((*check_proc), (genericptr_t, int, int));
367    genericptr_t arg;
368{
369    int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
370    boolean keep_going = TRUE;
371
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;
377
378    if (dx < 0) {
379	x_change = -1;
380	dx = -dx;
381    } else
382	x_change = 1;
383    if (dy < 0) {
384	y_change = -1;
385	dy = -dy;
386    } else
387	y_change = 1;
388
389    i = err = 0;
390    if (dx < dy) {
391	while (i++ < dy) {
392	    prev_x = x;
393	    prev_y = y;
394	    y += y_change;
395	    err += dx;
396	    if (err >= dy) {
397		x += x_change;
398		err -= dy;
399	    }
400	/* check for early exit condition */
401	if (!(keep_going = (*check_proc)(arg, x, y)))
402	    break;
403	}
404    } else {
405	while (i++ < dx) {
406	    prev_x = x;
407	    prev_y = y;
408	    x += x_change;
409	    err += dy;
410	    if (err >= dx) {
411		y += y_change;
412		err -= dx;
413	    }
414	/* check for early exit condition */
415	if (!(keep_going = (*check_proc)(arg, x, y)))
416	    break;
417	}
418    }
419
420    if (keep_going)
421	return TRUE;	/* successful */
422
423    dest_cc->x = prev_x;
424    dest_cc->y = prev_y;
425    return FALSE;
426}
427
428/*
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.
433 *
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.
437 *
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...)
443 *	o bounce off walls
444 *	o let jumps go over boulders
445 */
446boolean
447hurtle_step(arg, x, y)
448    genericptr_t arg;
449    int x, y;
450{
451    int ox, oy, *range = (int *)arg;
452    struct obj *obj;
453    struct monst *mon;
454    boolean may_pass = TRUE;
455    struct trap *ttmp;
456
457    if (!isok(x,y)) {
458	You_feel("the spirits holding you back.");
459	return FALSE;
460    } else if (!in_out_region(x, y)) {
461	return FALSE;
462    } else if (*range == 0) {
463	return FALSE;			/* previous step wants to stop now */
464    }
465
466    if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
467	if (IS_ROCK(levl[x][y].typ) || closed_door(x,y)) {
468	    const char *s;
469
470	    pline("Ouch!");
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";
475	    else
476		s = "bumping into a door";
477	    losehp(rnd(2+*range), s, KILLED_BY);
478	    return FALSE;
479	}
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);
483	    return FALSE;
484	}
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);
488	    return FALSE;
489	}
490	if (!may_pass) {
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);
494	    return FALSE;
495	}
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);
504		return FALSE;
505	    }
506	}
507    }
508
509    if ((mon = m_at(x, y)) != 0) {
510	You("bump into %s.", a_monnam(mon));
511	wakeup(mon);
512	return FALSE;
513    }
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!");
519	    return FALSE;
520	}
521    }
522
523    ox = u.ux;
524    oy = u.uy;
525    u.ux = x;
526    u.uy = y;
527    newsym(ox, oy);		/* update old position */
528    vision_recalc(1);		/* update for new position */
529    flush_screen(1);
530    /* FIXME:
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.
537     */
538    if ((ttmp = t_at(x, y)) != 0) {
539    	if (ttmp->ttyp == MAGIC_PORTAL) {
540    		dotrap(ttmp,0);
541    		return FALSE;
542	} else if (ttmp->ttyp == FIRE_TRAP) {
543    		dotrap(ttmp,0);
544	} else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT ||
545		    ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) &&
546		   In_sokoban(&u.uz)) {
547		/* Air currents overcome the recoil */
548    		dotrap(ttmp,0);
549		*range = 0;
550		return TRUE;
551    	} else {
552		if (ttmp->tseen)
553		    You("pass right over %s %s.",
554		    	(ttmp->ttyp == ARROW_TRAP) ? "an" : "a",
555		    	defsyms[trap_to_defsym(ttmp->ttyp)].explanation);
556    	}
557    }
558    if (--*range < 0)		/* make sure our range never goes negative */
559	*range = 0;
560    if (*range != 0)
561	delay_output();
562    return TRUE;
563}
564
565STATIC_OVL boolean
566mhurtle_step(arg, x, y)
567    genericptr_t arg;
568    int x, y;
569{
570	struct monst *mon = (struct monst *)arg;
571
572	/* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
573	 * rather than just stopping before.
574	 */
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);
580	    set_apparxy(mon);
581	    (void) mintrap(mon);
582	    return TRUE;
583	}
584	return FALSE;
585}
586
587/*
588 * The player moves through the air for a few squares as a result of
589 * throwing or kicking something.
590 *
591 * dx and dy should be the direction of the hurtle, not of the original
592 * kick or throw and be only.
593 */
594void
595hurtle(dx, dy, range, verbose)
596    int dx, dy, range;
597    boolean verbose;
598{
599    coord uc, cc;
600
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.
608     */
609    if(Punished && !carried(uball)) {
610	You_feel("a tug from the iron ball.");
611	nomul(0);
612	return;
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");
617	nomul(0);
618	return;
619    }
620
621    /* make sure dx and dy are [-1,0,1] */
622    dx = sgn(dx);
623    dy = sgn(dy);
624
625    if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
626
627    nomul(-range);
628    if (verbose)
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 */
636    }
637    if (In_sokoban(&u.uz))
638	change_luck(-1);	/* Sokoban guilt */
639    uc.x = u.ux;
640    uc.y = u.uy;
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);
645}
646
647/* Move a monster through the air for a few squares.
648 */
649void
650mhurtle(mon, dx, dy, range)
651	struct monst *mon;
652	int dx, dy, range;
653{
654    coord mc, cc;
655
656	/* At the very least, debilitate the monster */
657	mon->movement = 0;
658	mon->mstun = 1;
659
660	/* Is the monster stuck or too heavy to push?
661	 * (very large monsters have too much inertia, even floaters and flyers)
662	 */
663	if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped)
664	    return;
665
666    /* Make sure dx and dy are [-1,0,1] */
667    dx = sgn(dx);
668    dy = sgn(dy);
669    if(!range || (!dx && !dy)) return; /* paranoia */
670
671	/* Send the monster along the path */
672	mc.x = mon->mx;
673	mc.y = mon->my;
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);
677	return;
678}
679
680STATIC_OVL void
681check_shop_obj(obj, x, y, broken)
682register struct obj *obj;
683register xchar x, y;
684register boolean broken;
685{
686	struct monst *shkp = shop_keeper(*u.ushops);
687
688	if(!shkp) return;
689
690	if(broken) {
691		if (obj->unpaid) {
692		    (void)stolen_value(obj, u.ux, u.uy,
693				       (boolean)shkp->mpeaceful, FALSE);
694		    subfrombill(obj, shkp);
695		}
696		obj->no_charge = 1;
697		return;
698	}
699
700	if (!costly_spot(x, y) || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
701		/* thrown out of a shop or into a different shop */
702		if (obj->unpaid) {
703		    (void)stolen_value(obj, u.ux, u.uy,
704				       (boolean)shkp->mpeaceful, FALSE);
705		    subfrombill(obj, shkp);
706		}
707	} else {
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))
711			    sellobj(obj, x, y);
712		}
713	}
714}
715
716/*
717 * Hero tosses an object upwards with appropriate consequences.
718 *
719 * Returns FALSE if the object is gone.
720 */
721STATIC_OVL boolean
722toss_up(obj, hitsroof)
723struct obj *obj;
724boolean hitsroof;
725{
726    const char *almost;
727    /* note: obj->quan == 1 */
728
729    if (hitsroof) {
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);
734		return FALSE;
735	}
736	almost = "";
737    } else {
738	almost = " almost";
739    }
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));
742
743    /* object now hits you */
744
745    if (obj->oclass == POTION_CLASS) {
746	potionhit(&youmonst, obj, TRUE);
747    } else if (breaktest(obj)) {
748	int otyp = obj->otyp, ocorpsenm = obj->corpsenm;
749	int blindinc;
750
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;
755
756	breakmsg(obj, !Blind);
757	breakobj(obj, u.ux, u.uy, TRUE, TRUE);
758	obj = 0;	/* it's now gone */
759	switch (otyp) {
760	case EGG:
761		if (touch_petrifies(&mons[ocorpsenm]) &&
762		    !uarmh && !Stone_resistance &&
763		    !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)))
764		goto petrify;
765	case CREAM_PIE:
766	case BLINDING_VENOM:
767		pline("You've got it all over your %s!", body_part(FACE));
768		if (blindinc) {
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);
774		}
775		break;
776	default:
777		break;
778	}
779	return FALSE;
780    } else {		/* neither potion nor other breaking object */
781	boolean less_damage = uarmh && is_metallic(uarmh), artimsg = FALSE;
782	int dmg = dmgval(obj, &youmonst);
783
784	if (obj->oartifact)
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));
788
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)
795		dmg = 0;
796	}
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;
801
802	if (uarmh) {
803	    if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) {
804		if (!artimsg)
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))) {
812 petrify:
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() */
817		done(STONING);
818		return obj ? TRUE : FALSE;
819	    }
820	}
821	hitfloor(obj);
822	losehp(dmg, "falling object", KILLED_BY_AN);
823    }
824    return TRUE;
825}
826
827/* return true for weapon meant to be thrown; excludes ammo */
828STATIC_OVL boolean
829throwing_weapon(obj)
830struct obj *obj;
831{
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);
838}
839
840/* the currently thrown object is returning to you (not for boomerangs) */
841STATIC_OVL void
842sho_obj_return_to_u(obj)
843struct obj *obj;
844{
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;
848
849	tmp_at(DISP_FLASH, obj_to_glyph(obj));
850	while(x != u.ux || y != u.uy) {
851	    tmp_at(x, y);
852	    delay_output();
853	    x -= u.dx; y -= u.dy;
854	}
855	tmp_at(DISP_END, 0);
856    }
857}
858
859void
860throwit(obj, wep_mask, twoweap)
861register struct obj *obj;
862long wep_mask;	/* used to re-equip returning boomerang */
863boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
864{
865	register struct monst *mon;
866	register int range, urange;
867	boolean impaired = (Confusion || Stunned || Blind ||
868			   Hallucination || Fumbling);
869
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"));
874	    else {
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"));
880		else slipok = FALSE;
881	    }
882	    if (slipok) {
883		u.dx = rn2(3)-1;
884		u.dy = rn2(3)-1;
885		if (!u.dx && !u.dy) u.dz = 1;
886		impaired = TRUE;
887	    }
888	}
889
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.",
897		the(xname(obj)));
898	    exercise(A_CON, FALSE);
899	    u.dx = u.dy = 0;
900	    u.dz = 1;
901	}
902
903	thrownobj = obj;
904
905	if(u.uswallow) {
906		mon = u.ustuck;
907		bhitpos.x = mon->mx;
908		bhitpos.y = mon->my;
909	} else if(u.dz) {
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));
914		obj = addinv(obj);
915		(void) encumber_msg();
916		setuwep(obj);
917		u.twoweap = twoweap;
918	    } else if (u.dz < 0 && !Is_airlevel(&u.uz) &&
919		    !Underwater && !Is_waterlevel(&u.uz)) {
920		(void) toss_up(obj, rn2(5));
921	    } else {
922		hitfloor(obj);
923	    }
924	    thrownobj = (struct obj*)0;
925	    return;
926
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);
933			obj = addinv(obj);
934			(void) encumber_msg();
935			if (wep_mask && !(obj->owornmask & wep_mask)) {
936			    setworn(obj, wep_mask);
937			    u.twoweap = twoweap;
938			}
939			thrownobj = (struct obj*)0;
940			return;
941		}
942	} else {
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
947		 * actually possible
948		 */
949		if (obj->otyp == HEAVY_IRON_BALL)
950			range = urange - (int)(obj->owt/100);
951		else
952			range = urange - (int)(obj->owt/40);
953		if (obj == uball) {
954			if (u.ustuck) range = 1;
955			else if (range >= 5) range = 5;
956		}
957		if (range < 1) range = 1;
958
959		if (is_ammo(obj)) {
960		    if (ammo_and_launcher(obj, uwep))
961			range++;
962		    else if (obj->oclass != GEM_CLASS)
963			range /= 2;
964		}
965
966		if (Is_airlevel(&u.uz) || Levitation) {
967		    /* action, reaction... */
968		    urange -= range;
969		    if(urange < 1) urange = 1;
970		    range -= urange;
971		    if(range < 1) range = 1;
972		}
973
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)
979		    range = 1;
980
981		if (Underwater) range = 1;
982
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,
986			   obj);
987
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);
991	}
992
993	if (mon) {
994		boolean obj_gone;
995
996		if (mon->isshk &&
997		    obj->where == OBJ_MINVENT && obj->ocarry == mon) {
998		    thrownobj = (struct obj*)0;
999		    return;		/* alert shk caught it */
1000		}
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);
1006
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)))
1011		    hot_pursuit(mon);
1012
1013		if (obj_gone) return;
1014	}
1015
1016	if (u.uswallow) {
1017		/* ball is not picked up by monster */
1018		if (obj != uball) (void) mpickobj(u.ustuck,obj);
1019	} else {
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 */
1025
1026		    if (!impaired && rn2(100)) {
1027			pline("%s to your hand!", Tobjnam(obj, "return"));
1028			obj = addinv(obj);
1029			(void) encumber_msg();
1030			setuwep(obj);
1031			u.twoweap = twoweap;
1032			if(cansee(bhitpos.x, bhitpos.y))
1033			    newsym(bhitpos.x,bhitpos.y);
1034		    } else {
1035			int dmg = rn2(2);
1036			if (!dmg) {
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)));
1042			} else {
1043			    dmg += rnd(3);
1044			    pline(Blind ? "%s your %s!" :
1045					"%s back toward you, hitting your %s!",
1046				  Tobjnam(obj, Blind ? "hit" : "fly"),
1047				  body_part(ARM));
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);
1052			}
1053			if (ship_object(obj, u.ux, u.uy, FALSE)) {
1054		    	    thrownobj = (struct obj*)0;
1055			    return;
1056			}
1057			dropy(obj);
1058		    }
1059		    thrownobj = (struct obj*)0;
1060		    return;
1061		}
1062
1063		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
1064			breaktest(obj)) {
1065		    tmp_at(DISP_FLASH, obj_to_glyph(obj));
1066		    tmp_at(bhitpos.x, bhitpos.y);
1067		    delay_output();
1068		    tmp_at(DISP_END, 0);
1069		    breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
1070		    breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
1071		    return;
1072		}
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)));
1079		    if(*u.ushops)
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;
1083		    return;
1084		}
1085		(void) snuff_candle(obj);
1086		if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) {
1087		    thrownobj = (struct obj*)0;
1088		    return;
1089		}
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);
1094
1095		stackobj(obj);
1096		if (obj == uball)
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);
1104	}
1105}
1106
1107/* an object may hit a monster; various factors adjust the chance of hitting */
1108int
1109omon_adj(mon, obj, mon_notices)
1110struct monst *mon;
1111struct obj *obj;
1112boolean mon_notices;
1113{
1114	int tmp = 0;
1115
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) {
1120	    tmp += 2;
1121	    if (mon_notices) mon->msleeping = 0;
1122	}
1123	/* ditto for immobilized target */
1124	if (!mon->mcanmove || !mon->data->mmove) {
1125	    tmp += 4;
1126	    if (mon_notices && mon->data->mmove && !rn2(10)) {
1127		mon->mcanmove = 1;
1128		mon->mfrozen = 0;
1129	    }
1130	}
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;
1135	    break;
1136	case BOULDER:
1137	    tmp += 6;
1138	    break;
1139	default:
1140	    if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
1141		    obj->oclass == GEM_CLASS)
1142		tmp += hitval(obj, mon);
1143	    break;
1144	}
1145	return tmp;
1146}
1147
1148/* thrown object misses target monster */
1149STATIC_OVL void
1150tmiss(obj, mon)
1151struct obj *obj;
1152struct monst *mon;
1153{
1154    const char *missile = mshot_xname(obj);
1155
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"));
1163    else
1164	miss(missile, mon);
1165    if (!rn2(3)) wakeup(mon);
1166    return;
1167}
1168
1169#define quest_arti_hits_leader(obj,mon)	\
1170  (obj->oartifact && is_quest_artifact(obj) && (mon->data->msound == MS_LEADER))
1171
1172/*
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.
1176 */
1177int
1178thitmonst(mon, obj)
1179register struct monst *mon;
1180register struct obj   *obj;
1181{
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);
1186
1187	/* Differences from melee weapons:
1188	 *
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.
1197	 */
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);
1204
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.
1208	 */
1209	disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
1210	if(disttmp < -4) disttmp = -4;
1211	tmp += disttmp;
1212
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 */
1217		tmp -= 2;
1218		break;
1219	    case GAUNTLETS_OF_FUMBLING:
1220		tmp -= 3;
1221		break;
1222	    case LEATHER_GLOVES:
1223	    case GAUNTLETS_OF_DEXTERITY:
1224		break;
1225	    default:
1226		impossible("Unknown type of gloves (%d)", uarmg->otyp);
1227		break;
1228	    }
1229	}
1230
1231	tmp += omon_adj(mon, obj, TRUE);
1232	if (is_orc(mon->data) && maybe_polyd(is_elf(youmonst.data),
1233			Race_if(PM_ELF)))
1234	    tmp++;
1235	if (guaranteed_hit) {
1236	    tmp += 1000; /* Guaranteed hit */
1237	}
1238
1239	if (obj->oclass == GEM_CLASS && is_unicorn(mon->data)) {
1240	    if (mon->mtame) {
1241		pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
1242		return 0;
1243	    } else {
1244		pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1245		return gem_accept(mon, obj);
1246	    }
1247	}
1248
1249	/* don't make game unwinnable if naive player throws artifact
1250	   at leader.... */
1251	if (quest_arti_hits_leader(obj, mon)) {
1252	    /* not wakeup(), which angers non-tame monsters */
1253	    mon->msleeping = 0;
1254	    mon->mstrategy &= ~STRAT_WAITMASK;
1255
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);
1260
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();
1267		} else {
1268		    /* angry leader caught it and isn't returning it */
1269		    (void) mpickobj(mon, obj);
1270		}
1271		return 1;		/* caller doesn't need to place it */
1272	    }
1273	    return(0);
1274	}
1275
1276	if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
1277		obj->oclass == GEM_CLASS) {
1278	    if (is_ammo(obj)) {
1279		if (!ammo_and_launcher(obj, uwep)) {
1280		    tmp -= 4;
1281		} else {
1282		    tmp += uwep->spe - greatest_erosion(uwep);
1283		    tmp += weapon_hit_bonus(uwep);
1284		    if (uwep->oartifact) tmp += spec_abon(uwep, mon);
1285		    /*
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.
1289		     */
1290		    if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI)) &&
1291				(!Upolyd || your_race(youmonst.data)) &&
1292				objects[uwep->otyp].oc_skill == P_BOW) {
1293			tmp++;
1294			if (Race_if(PM_ELF) && uwep->otyp == ELVEN_BOW)
1295			    tmp++;
1296			else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI)
1297			    tmp++;
1298		    }
1299		}
1300	    } else {
1301		if (otyp == BOOMERANG)		/* arbitrary */
1302		    tmp += 4;
1303		else if (throwing_weapon(obj))	/* meant to be thrown */
1304		    tmp += 2;
1305		else				/* not meant to be thrown */
1306		    tmp -= 2;
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);
1310	    }
1311
1312	    if (tmp >= rnd(20)) {
1313		if (hmon(mon,obj,1)) {	/* mon still alive */
1314		    cutworm(mon, bhitpos.x, bhitpos.y, obj);
1315		}
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.
1325		     */
1326		    int broken, chance;
1327		    chance = 3 + greatest_erosion(obj) - obj->spe;
1328		    if (chance > 1)
1329			broken = rn2(chance);
1330		    else
1331			broken = !rn2(4);
1332		    if (obj->blessed && !rnl(4))
1333			broken = 0;
1334
1335		    if (broken) {
1336			if (*u.ushops)
1337			    check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
1338			obfree(obj, (struct obj *)0);
1339			return 1;
1340		    }
1341		}
1342		passive_obj(mon, obj, (struct attack *)0);
1343	    } else {
1344		tmiss(obj, mon);
1345	    }
1346
1347	} else if (otyp == HEAVY_IRON_BALL) {
1348	    exercise(A_STR, TRUE);
1349	    if (tmp >= rnd(20)) {
1350		int was_swallowed = guaranteed_hit;
1351
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() */
1356		}
1357	    } else {
1358		tmiss(obj, mon);
1359	    }
1360
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);
1366	    } else {
1367		tmiss(obj, mon);
1368	    }
1369
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 */
1375
1376	} else if (obj->oclass == POTION_CLASS &&
1377		(guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1378	    potionhit(mon, obj, TRUE);
1379	    return 1;
1380
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 */
1385	    else {
1386		/* not tmiss(), which angers non-tame monsters */
1387		miss(xname(obj), mon);
1388		mon->msleeping = 0;
1389		mon->mstrategy &= ~STRAT_WAITMASK;
1390	    }
1391	} else if (guaranteed_hit) {
1392	    /* this assumes that guaranteed_hit is due to swallowing */
1393	    wakeup(mon);
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 */
1398			if (!u.uswallow) {
1399				delobj(obj);
1400				return 1;
1401			}
1402	    	}
1403	    }
1404	    pline("%s into %s %s.",
1405		Tobjnam(obj, "vanish"), s_suffix(mon_nam(mon)),
1406		is_animal(u.ustuck->data) ? "entrails" : "currents");
1407	} else {
1408	    tmiss(obj, mon);
1409	}
1410
1411	return 0;
1412}
1413
1414STATIC_OVL int
1415gem_accept(mon, obj)
1416register struct monst *mon;
1417register struct obj *obj;
1418{
1419	char buf[BUFSZ];
1420	boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
1421	boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
1422	int ret = 0;
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";
1428
1429	Strcpy(buf,Monnam(mon));
1430	mon->mpeaceful = 1;
1431	mon->mavenge = 0;
1432
1433	/* object properly identified */
1434	if(obj->dknown && objects[obj->otyp].oc_name_known) {
1435		if(is_gem) {
1436			if(is_buddy) {
1437				Strcat(buf,addluck);
1438				change_luck(5);
1439			} else {
1440				Strcat(buf,maybeluck);
1441				change_luck(rn2(7)-3);
1442			}
1443		} else {
1444			Strcat(buf,nogood);
1445			goto nopick;
1446		}
1447	/* making guesses */
1448	} else if(obj->onamelth || objects[obj->otyp].oc_uname) {
1449		if(is_gem) {
1450			if(is_buddy) {
1451				Strcat(buf,addluck);
1452				change_luck(2);
1453			} else {
1454				Strcat(buf,maybeluck);
1455				change_luck(rn2(3)-1);
1456			}
1457		} else {
1458			Strcat(buf,nogood);
1459			goto nopick;
1460		}
1461	/* value completely unknown to @ */
1462	} else {
1463		if(is_gem) {
1464			if(is_buddy) {
1465				Strcat(buf,addluck);
1466				change_luck(1);
1467			} else {
1468				Strcat(buf,maybeluck);
1469				change_luck(rn2(3)-1);
1470			}
1471		} else {
1472			Strcat(buf,noluck);
1473		}
1474	}
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 */
1478	ret = 1;
1479
1480nopick:
1481	if(!Blind) pline("%s", buf);
1482	if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
1483	return(ret);
1484}
1485
1486/*
1487 * Comments about the restructuring of the old breaks() routine.
1488 *
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
1501 *                   object.
1502 *
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.
1506 *
1507 *   hero_breaks() - called when an object is to be broken as a result
1508 *                   of something that the hero has done. (throwing it,
1509 *                   kicking it, etc.)
1510 *   breaks()      - called when an object is to be broken for some
1511 *                   reason other than the hero doing something to it.
1512 */
1513
1514/*
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.
1517 */
1518int
1519hero_breaks(obj, x, y, from_invent)
1520struct obj *obj;
1521xchar x, y;		/* object location (ox, oy may not be right) */
1522boolean from_invent;	/* thrown or dropped by player; maybe on shop bill */
1523{
1524	boolean in_view = !Blind;
1525	if (!breaktest(obj)) return 0;
1526	breakmsg(obj, in_view);
1527	breakobj(obj, x, y, TRUE, from_invent);
1528	return 1;
1529}
1530
1531/*
1532 * The object is going to break for a reason other than the hero doing
1533 * something to it.
1534 * Return 0 if the object doesn't break, 1 if the object broke.
1535 */
1536int
1537breaks(obj, x, y)
1538struct obj *obj;
1539xchar x, y;		/* object location (ox, oy may not be right) */
1540{
1541	boolean in_view = Blind ? FALSE : cansee(x, y);
1542
1543	if (!breaktest(obj)) return 0;
1544	breakmsg(obj, in_view);
1545	breakobj(obj, x, y, FALSE, FALSE);
1546	return 1;
1547}
1548
1549/*
1550 * Unconditionally break an object. Assumes all resistance checks
1551 * and break messages have been delivered prior to getting here.
1552 */
1553STATIC_OVL void
1554breakobj(obj, x, y, hero_caused, from_invent)
1555struct obj *obj;
1556xchar x, y;		/* object location (ox, oy may not be right) */
1557boolean hero_caused;	/* is this the hero's fault? */
1558boolean from_invent;
1559{
1560	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1561		case MIRROR:
1562			if (hero_caused)
1563			    change_luck(-2);
1564			break;
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...");
1574					else {
1575					    int numeyes = eyecount(youmonst.data);
1576					    Your("%s water%s.",
1577						 (numeyes == 1) ? body_part(EYE) :
1578							makeplural(body_part(EYE)),
1579						 (numeyes == 1) ? "s" : "");
1580					}
1581				}
1582				potionbreathe(obj);
1583			    }
1584			}
1585			/* monster breathing isn't handled... [yet?] */
1586			break;
1587		case EGG:
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));
1591			break;
1592	}
1593	if (hero_caused) {
1594	    if (from_invent) {
1595		if (*u.ushops)
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);
1601
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;
1615		}
1616	    }
1617	}
1618	delobj(obj);
1619}
1620
1621/*
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.
1624 */
1625boolean
1626breaktest(obj)
1627struct obj *obj;
1628{
1629	if (obj_resists(obj, 1, 99)) return 0;
1630	if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact &&
1631		obj->oclass != GEM_CLASS)
1632	    return 1;
1633	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1634#ifdef TOURIST
1635		case EXPENSIVE_CAMERA:
1636#endif
1637		case POT_WATER:		/* really, all potions */
1638		case EGG:
1639		case CREAM_PIE:
1640		case MELON:
1641		case ACID_VENOM:
1642		case BLINDING_VENOM:
1643			return 1;
1644		default:
1645			return 0;
1646	}
1647}
1648
1649STATIC_OVL void
1650breakmsg(obj, in_view)
1651struct obj *obj;
1652boolean in_view;
1653{
1654	const char *to_pieces;
1655
1656	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:
1662		case LENSES:
1663		case MIRROR:
1664		case CRYSTAL_BALL:
1665#ifdef TOURIST
1666		case EXPENSIVE_CAMERA:
1667#endif
1668			to_pieces = " into a thousand pieces";
1669			/*FALLTHRU*/
1670		case POT_WATER:		/* really, all potions */
1671			if (!in_view)
1672			    You_hear("%s shatter!", something);
1673			else
1674			    pline("%s shatter%s%s!", Doname2(obj),
1675				(obj->quan==1) ? "s" : "", to_pieces);
1676			break;
1677		case EGG:
1678		case MELON:
1679			pline("Splat!");
1680			break;
1681		case CREAM_PIE:
1682			if (in_view) pline("What a mess!");
1683			break;
1684		case ACID_VENOM:
1685		case BLINDING_VENOM:
1686			pline("Splash!");
1687			break;
1688	}
1689}
1690
1691STATIC_OVL int
1692throw_gold(obj)
1693struct obj *obj;
1694{
1695	int range, odx, ody;
1696#ifndef GOLDOBJ
1697	long zorks = obj->quan;
1698#endif
1699	register struct monst *mon;
1700
1701	if(!u.dx && !u.dy && !u.dz) {
1702#ifndef GOLDOBJ
1703		u.ugold += obj->quan;
1704		flags.botl = 1;
1705		dealloc_obj(obj);
1706#endif
1707		You("cannot throw gold at yourself.");
1708		return(0);
1709	}
1710#ifdef GOLDOBJ
1711        freeinv(obj);
1712#endif
1713	if(u.uswallow) {
1714		pline(is_animal(u.ustuck->data) ?
1715			"%s in the %s's entrails." : "%s into %s.",
1716#ifndef GOLDOBJ
1717			"The gold disappears", mon_nam(u.ustuck));
1718		u.ustuck->mgold += zorks;
1719		dealloc_obj(obj);
1720#else
1721			"The money disappears", mon_nam(u.ustuck));
1722		add_to_minv(u.ustuck, obj);
1723#endif
1724		return(1);
1725	}
1726
1727	if(u.dz) {
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!");
1734		}
1735		bhitpos.x = u.ux;
1736		bhitpos.y = u.uy;
1737	} else {
1738		/* consistent with range for normal objects */
1739		range = (int)((ACURRSTR)/2 - obj->owt/40);
1740
1741		/* see if the gold has a place to move into */
1742		odx = u.ux + u.dx;
1743		ody = u.uy + u.dy;
1744		if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
1745			bhitpos.x = u.ux;
1746			bhitpos.y = u.uy;
1747		} else {
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,
1751				   obj);
1752			if(mon) {
1753			    if (ghitm(mon, obj))	/* was it caught? */
1754				return 1;
1755			} else {
1756			    if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
1757				return 1;
1758			}
1759		}
1760	}
1761
1762	if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
1763	if(u.dz > 0)
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);
1767	stackobj(obj);
1768	newsym(bhitpos.x,bhitpos.y);
1769	return(1);
1770}
1771
1772/*dothrow.c*/
1773