Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/dothrow.c

2,032pages on
this wiki
Talk0

Below is the full text to dothrow.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/dothrow.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.    
10.   STATIC_DCL int FDECL(throw_obj, (struct obj *, int, 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));
22.   static void NDECL(autoquiver);	/* KMH -- automatically fill quiver */
23.   
24.   
25.   static NEARDATA const char toss_objs[] =
26.   	{ ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
27.   /* different default choices when wielding a sling (gold must be included) */
28.   static NEARDATA const char bullets[] =
29.   	{ ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, GEM_CLASS, 0 };
30.   
31.   struct obj *thrownobj = 0;	/* tracks an object until it lands */
32.   
33.   extern boolean notonhead;	/* for long worms */
34.   
35.   #define THROW_UWEP 	1
36.   #define THROW_USWAPWEP 	2
37.   
38.   /* Split this object off from its slot */
39.   
40.   struct obj *
41.   splitoneoff(pobj)
42.   struct obj **pobj;
43.   {
44.       struct obj *obj = *pobj;
45.       struct obj *otmp = (struct obj *)0;
46.       if (obj == uquiver) {
47.   	if (obj->quan > 1L)
48.   	    setuqwep(otmp = splitobj(obj, 1L));
49.   	else
50.   	    setuqwep((struct obj *)0);
51.       } else if (obj == uswapwep) {
52.   	if (obj->quan > 1L)
53.   	    setuswapwep(otmp = splitobj(obj, 1L), FALSE);
54.   	else
55.   	    setuswapwep((struct obj *)0, FALSE);
56.       } else if (obj == uwep) {
57.   	if (obj->quan > 1L)
58.   	    setworn(otmp = splitobj(obj, 1L), W_WEP);
59.   	    /* not setuwep; do not change unweapon */
60.   	else {
61.   	    setuwep((struct obj *)0, FALSE);
62.   	    if (uwep) return (struct obj *)0; /* unwielded, died, rewielded */
63.   	}
64.       } else if (obj->quan > 1L)
65.   	otmp = splitobj(obj, 1L);
66.       *pobj = otmp;
67.       return obj;
68.   }
69.   
70.   /* Throw the selected object, asking for direction */
71.   STATIC_OVL int
72.   throw_obj(obj, shotlimit, thrown)
73.   register struct obj *obj;
74.   int shotlimit;
75.   int thrown;
76.   {
77.   	struct obj *otmp;
78.   	struct obj *launcher;
79.   	int multishot = 1;
80.   	schar skill;
81.   	long wep_mask;
82.   	boolean twoweap;
83.   
84.   	multi = 0;		/* reset; it's been used up */
85.   	
86.   	if (thrown == 1 && uwep && ammo_and_launcher(obj, uwep)) 
87.   		launcher = uwep;
88.   	else if (thrown == 2 && uswapwep && ammo_and_launcher(obj, uswapwep))
89.   		launcher = uswapwep;
90.   	else launcher = (struct obj *)0;
91.   
92.   	/* ask "in what direction?" */
93.   #ifndef GOLDOBJ
94.   	if (!getdir((char *)0)) {
95.   		if (obj->oclass == COIN_CLASS) {
96.   		    u.ugold += obj->quan;
97.   		    flags.botl = 1;
98.   		    dealloc_obj(obj);
99.   		}
100.  		return(0);
101.  	}
102.  
103.  	if(obj->oclass == COIN_CLASS) return(throw_gold(obj));
104.  #else
105.  	if (!getdir((char *)0)) {
106.  	    /* obj might need to be merged back into the singular gold object */
107.  	    freeinv(obj);
108.  	    addinv(obj);
109.  	    return(0);
110.  	}
111.  
112.          /*
113.  	  Throwing money is usually for getting rid of it when
114.            a leprechaun approaches, or for bribing an oncoming 
115.            angry monster.  So throw the whole object.
116.  
117.            If the money is in quiver, throw one coin at a time,
118.            possibly using a sling.
119.          */
120.  	if(obj->oclass == COIN_CLASS && obj != uquiver) return(throw_gold(obj));
121.  #endif
122.  
123.  	if(!canletgo(obj,"throw"))
124.  		return(0);
125.  
126.  	if(obj == uwep && welded(obj)) {
127.  		weldmsg(obj);
128.  		return(1);
129.  	}
130.  
131.  	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
132.  	    pline("%s must be wielded before it can be thrown.",
133.  		The(xname(obj)));
134.  		return(0);
135.  	}
136.  	if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) < STR19(25))
137.  	   || (obj->otyp == BOULDER && !throws_rocks(youmonst.data))) {
138.  		pline("It's too heavy.");
139.  		return(1);
140.  	}
141.  	if(!u.dx && !u.dy && !u.dz) {
142.  		You("cannot throw an object at yourself.");
143.  		return(0);
144.  	}
145.  	u_wipe_engr(2);
146.  	if (!uarmg && !Stone_resistance && (obj->otyp == CORPSE &&
147.  		    touch_petrifies(&mons[obj->corpsenm]))) {
148.  		You("throw the %s corpse with your bare %s.",
149.  		    mons[obj->corpsenm].mname, body_part(HAND));
150.  		Sprintf(killer_buf, "%s corpse", an(mons[obj->corpsenm].mname));
151.  		instapetrify(killer_buf);
152.  	}
153.  	if (welded(obj)) {
154.  		weldmsg(obj);
155.  		return 1;
156.  	}
157.  
158.  	/* Multishot calculations
159.  	 */
160.  	skill = objects[obj->otyp].oc_skill;
161.  	if ((ammo_and_launcher(obj, uwep) || skill == P_DAGGER ||
162.  			skill == -P_DART || skill == -P_SHURIKEN) &&
163.  		!(Confusion || Stunned)) {
164.  	    /* Bonus if the player is proficient in this weapon... */
165.  	    switch (P_SKILL(weapon_type(obj))) {
166.  	    default:	break; /* No bonus */
167.  	    case P_SKILLED:	multishot++; break;
168.  	    case P_EXPERT:	multishot += 2; break;
169.  	    }
170.  	    
171.  	    /* ...or is using a good weapon... */
172.  	    /* Elven Craftsmanship makes for light, quick bows */
173.  	    if (obj->otyp == ELVEN_ARROW && !obj->cursed && !rn2(3)) multishot++;
174.  	    if (launcher && launcher->otyp == ELVEN_BOW &&
175.  	      !launcher->cursed && !rn2(3))
176.  		multishot++;
177.  
178.  	    /* 1/3 of object enchantment */
179.  	    if (launcher && launcher->spe > 1)
180.  		multishot += (long) rounddiv(launcher->spe,3);
181.  	    
182.  	    /* ...or is using a special weapon for their role... */
183.  	    switch (Role_switch) {
184.  	    case PM_RANGER:
185.  		multishot++;
186.  		break;
187.  	    case PM_ROGUE:
188.  		if (skill == P_DAGGER) multishot++;
189.  		break;
190.  	    case PM_SAMURAI:
191.  		if (obj->otyp == YA && launcher && launcher->otyp == YUMI) multishot++;
192.  		break;
193.  	    default:
194.  		break;	/* No bonus */
195.  	    }
196.  	    /* ...or using their race's special bow */
197.  	    switch (Race_switch) {
198.  	    case PM_ELF:
199.  		if (obj->otyp == ELVEN_ARROW && launcher &&
200.  				launcher->otyp == ELVEN_BOW) multishot++;
201.  		break;
202.  	    case PM_ORC:
203.  		if (obj->otyp == ORCISH_ARROW && uwep &&
204.  				uwep->otyp == ORCISH_BOW) multishot++;
205.  		break;
206.  	    default:
207.  		break;	/* No bonus */
208.  	    }
209.  
210.  	if ((long)multishot > obj->quan) multishot = (int)obj->quan;
211.  
212.  	    if (multishot > 0) 
213.  	    	multishot = rnd(multishot); /* Some randomness */
214.  	    else multishot = 1;
215.  	       
216.  	    /* Tech: Flurry */
217.  	    if (objects[obj->otyp].oc_skill == -P_BOW && tech_inuse(T_FLURRY)) {
218.  		multishot += 1; /* Let'em rip! */
219.  
220.  		/* more than usual == volley */
221.  		if (((shotlimit <= 0) || (shotlimit >= multishot)) && 
222.  			(obj->quan >= multishot))
223.  		    You("let fly a volley of %s!", xname(obj));
224.  	    }
225.  
226.  	    /* Shotlimit controls your rate of fire */
227.  	    if ((shotlimit > 0) && (multishot > shotlimit)) multishot = shotlimit;
228.  
229.  #ifdef FIREARMS
230.  	    /* Rate of fire is intrinsic to the weapon - cannot be user selected
231.  	     * except via altmode
232.  	     * Only for valid launchers 
233.  	     * (currently oc_rof conflicts with wsdam)
234.  	     */
235.  	    if (launcher && is_launcher(launcher))
236.  	    {
237.  		if (objects[(launcher->otyp)].oc_rof) 
238.  		    multishot += (objects[(launcher->otyp)].oc_rof - 1);
239.  		if (launcher->altmode == WP_MODE_SINGLE)
240.  		  /* weapons switchable b/w full/semi auto */
241.  		    multishot = 1;
242.  		else if (launcher->altmode == WP_MODE_BURST)
243.  		    multishot = ((multishot > 3) ? (multishot / 3) : 1);
244.  		/* else it is auto == no change */
245.  	    }
246.  
247.  	    if ((long)multishot > obj->quan) multishot = (int)obj->quan;
248.  #endif
249.  	}
250.  
251.  	if (multishot < 1) multishot = 1;
252.  
253.  	m_shot.s = ammo_and_launcher(obj,uwep) ? TRUE : FALSE;
254.  	/* give a message if shooting more than one, or if player
255.  	   attempted to specify a count */
256.  	if (multishot > 1 || shotlimit > 0) {
257.  	    /* "You shoot N arrows." or "You throw N daggers." */
258.  	    You("%s %d %s.",
259.  		m_shot.s ? "shoot" : "throw",
260.  		multishot,	/* (might be 1 if player gave shotlimit) */
261.  		(multishot == 1) ? singular(obj, xname) :  xname(obj));
262.  	}
263.  
264.  	wep_mask = obj->owornmask;
265.  	m_shot.o = obj->otyp;
266.  	m_shot.n = multishot;
267.  	for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
268.  	    twoweap = u.twoweap;
269.  	    /* split this object off from its slot if necessary */
270.  	    if (obj->quan > 1L) {
271.  		otmp = splitobj(obj, 1L);
272.  	    } else {
273.  		otmp = obj;
274.  		if (otmp->owornmask)
275.  		    remove_worn_item(otmp, FALSE);
276.  	    }
277.  	    freeinv(otmp);
278.  	    throwit(otmp, wep_mask, twoweap, thrown);
279.  	}
280.  	m_shot.n = m_shot.i = 0;
281.  	m_shot.o = STRANGE_OBJECT;
282.  	m_shot.s = FALSE;
283.  
284.  	return 1;
285.  
286.  }
287.  
288.  
289.  int
290.  dothrow()
291.  {
292.  	register struct obj *obj;
293.  	int oldmulti = multi, result, shotlimit;
294.  	char *oldsave_cm = save_cm;
295.  
296.  	/*
297.  	 * Since some characters shoot multiple missiles at one time,
298.  	 * allow user to specify a count prefix for 'f' or or select 
299.  	 * a number of items in the item selection for 't' to limit
300.  	 * number of items thrown (to avoid possibly hitting something
301.  	 * behind target after killing it, or perhaps to conserve ammo).
302.  	 *
303.  	 * Nethack 3.3.0 uses prefixes for all - should this revert to that?
304.  	 *
305.  	 * Prior to 3.3.0, command ``3t meant ``t(shoot) t(shoot) t(shoot)
306.  	 * and took 3 turns.  Now it means ``t(shoot at most 3 missiles).
307.  	 */
308.  
309.  	if (notake(youmonst.data)) {
310.  	    You("are physically incapable of throwing anything.");
311.  	    return 0;
312.  	}
313.  
314.  	if(check_capacity((char *)0)) return(0);
315.  	obj = getobj(uslinging() ? bullets : toss_objs, "throw");
316.  	/* it is also possible to throw food */
317.  	/* (or jewels, or iron balls... ) */
318.  
319.  	if (!obj) return(0);
320.  
321.  	/* kludge to work around parse()'s pre-decrement of 'multi' */
322.  	shotlimit = (multi || save_cm) ? multi + 1 : 0;
323.  
324.          result = throw_obj(obj, shotlimit, THROW_UWEP);
325.          
326.  	/*
327.  	 * [ALI] Bug fix: Temporary paralysis (eg., from hurtle) cancels
328.  	 * any count for the throw command.
329.  	 */
330.  	if (multi >= 0)
331.  	    multi = oldmulti;
332.          save_cm = oldsave_cm;
333.          return (result);
334.  }
335.  
336.  
337.  /* KMH -- automatically fill quiver */
338.  /* Suggested by Jeffrey Bay <jbay@convex.hp.com> */
339.  static void
340.  autoquiver()
341.  {
342.  	struct obj *otmp, *oammo = 0, *omissile = 0, *omisc = 0, *altammo = 0;
343.  
344.  	if (uquiver)
345.  	    return;
346.  
347.  	/* Scan through the inventory */
348.  	for (otmp = invent; otmp; otmp = otmp->nobj) {
349.  	    if (otmp->owornmask || otmp->oartifact || !otmp->dknown) {
350.  		;	/* Skip it */
351.  	    } else if (otmp->otyp == ROCK ||
352.  			/* seen rocks or known flint or known glass */
353.  			(objects[otmp->otyp].oc_name_known &&
354.  			 otmp->otyp == FLINT) ||
355.  			(objects[otmp->otyp].oc_name_known &&
356.  			 otmp->oclass == GEM_CLASS &&
357.  			 objects[otmp->otyp].oc_material == GLASS)) {
358.  		if (uslinging())
359.  		    oammo = otmp;
360.  		else if (ammo_and_launcher(otmp, uswapwep))
361.  		    altammo = otmp;
362.  		else if (!omisc)
363.  		    omisc = otmp;
364.  	    } else if (otmp->oclass == GEM_CLASS) {
365.  		;	/* skip non-rock gems--they're ammo but
366.  			   player has to select them explicitly */
367.  	    } else if (is_ammo(otmp)) {
368.  		if (ammo_and_launcher(otmp, uwep))
369.  		    /* Ammo matched with launcher (bow and arrow, crossbow and bolt) */
370.  		    oammo = otmp;
371.  		else if (ammo_and_launcher(otmp, uswapwep))
372.  		    altammo = otmp;
373.  		else
374.  		    /* Mismatched ammo (no better than an ordinary weapon) */
375.  		    omisc = otmp;
376.  	    } else if (is_missile(otmp)) {
377.  		/* Missile (dart, shuriken, etc.) */
378.  		omissile = otmp;
379.  	    } else if (otmp->oclass == WEAPON_CLASS && throwing_weapon(otmp)) {
380.  		/* Ordinary weapon */
381.  		if (objects[otmp->otyp].oc_skill == P_DAGGER
382.  			&& !omissile) 
383.  		    omissile = otmp;
384.  		else
385.  		    omisc = otmp;
386.  	    }
387.  	}
388.  
389.  	/* Pick the best choice */
390.  	if (oammo)
391.  	    setuqwep(oammo);
392.  	else if (omissile)
393.  	    setuqwep(omissile);
394.  	else if (altammo)
395.  	    setuqwep(altammo);
396.  	else if (omisc)
397.  	    setuqwep(omisc);
398.  
399.  	return;
400.  }
401.  
402.  int
403.  dofire()
404.  {
405.  	int result, shotlimit;
406.  
407.  	if (notake(youmonst.data)) {
408.  	    You("are physically incapable of doing that.");
409.  	    return 0;
410.  	}
411.  
412.  	if(check_capacity((char *)0)) return(0);
413.  	if (!uquiver) {
414.  		if (!flags.autoquiver) {
415.  			/* Don't automatically fill the quiver */
416.  			You("have no ammunition readied!");
417.  			return(dothrow());
418.  		}
419.  		autoquiver();
420.  		if (!uquiver) {
421.  			You("have nothing appropriate for your quiver!");
422.  			return(dothrow());
423.  		} else {
424.  			You("fill your quiver:");
425.  			prinv((char *)0, uquiver, 0L);
426.  		}
427.  	}
428.  
429.  	/*
430.  	 * Since some characters shoot multiple missiles at one time,
431.  	 * allow user to specify a count prefix for 'f' or 't' to limit
432.  	 * number of items thrown (to avoid possibly hitting something
433.  	 * behind target after killing it, or perhaps to conserve ammo).
434.  	 *
435.  	 * The number specified can never increase the number of missiles.
436.  	 * Using ``5f when the shooting skill (plus RNG) dictates launch
437.  	 * of 3 projectiles will result in 3 being shot, not 5.
438.  	 */
439.  	/* kludge to work around parse()'s pre-decrement of `multi' */
440.  	shotlimit = (multi || save_cm) ? multi + 1 : 0;
441.  	multi = 0;		/* reset; it's been used up */
442.  
443.  	if (u.twoweap) {
444.  		if (!can_twoweapon()) untwoweapon();
445.  		else if (ammo_and_launcher(uquiver,uwep) 
446.  		    && ammo_and_launcher(uquiver, uswapwep)){
447.  			result = throw_obj(uquiver, shotlimit, THROW_UWEP);
448.  			if ((result == 1) && uquiver) 
449.  			    result += throw_obj(uquiver, shotlimit, THROW_USWAPWEP);
450.  			if (result > 1) result--;
451.  			return(result);
452.  		}
453.  	}
454.  	result = (throw_obj(uquiver, shotlimit, THROW_UWEP));
455.  	
456.  	return result;
457.  }
458.  
459.  
460.  /*
461.   * Object hits floor at hero's feet.  Called from drop() and throwit().
462.   */
463.  void
464.  hitfloor(obj)
465.  register struct obj *obj;
466.  {
467.  	if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
468.  		dropy(obj);
469.  		return;
470.  	}
471.  	if (IS_ALTAR(levl[u.ux][u.uy].typ))
472.  		doaltarobj(obj);
473.  	else
474.  		pline("%s hit%s the %s.", Doname2(obj),
475.  		      (obj->quan == 1L) ? "s" : "", surface(u.ux,u.uy));
476.  
477.  	if (hero_breaks(obj, u.ux, u.uy, TRUE)) return;
478.  	if (ship_object(obj, u.ux, u.uy, FALSE)) return;
479.  	dropy(obj);
480.  	if (!u.uswallow) container_impact_dmg(obj);
481.  }
482.  
483.  /*
484.   * Walk a path from src_cc to dest_cc, calling a proc for each location
485.   * except the starting one.  If the proc returns FALSE, stop walking
486.   * and return FALSE.  If stopped early, dest_cc will be the location
487.   * before the failed callback.
488.   */
489.  boolean
490.  walk_path(src_cc, dest_cc, check_proc, arg)
491.      coord *src_cc;
492.      coord *dest_cc;
493.      boolean FDECL((*check_proc), (genericptr_t, int, int));
494.      genericptr_t arg;
495.  {
496.      int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
497.      boolean keep_going = TRUE;
498.  
499.      /* Use Bresenham's Line Algorithm to walk from src to dest */
500.      dx = dest_cc->x - src_cc->x;
501.      dy = dest_cc->y - src_cc->y;
502.      prev_x = x = src_cc->x;
503.      prev_y = y = src_cc->y;
504.  
505.      if (dx < 0) {
506.  	x_change = -1;
507.  	dx = -dx;
508.      } else
509.  	x_change = 1;
510.      if (dy < 0) {
511.  	y_change = -1;
512.  	dy = -dy;
513.      } else
514.  	y_change = 1;
515.  
516.      i = err = 0;
517.      if (dx < dy) {
518.  	while (i++ < dy) {
519.  	    prev_x = x;
520.  	    prev_y = y;
521.  	    y += y_change;
522.  	    err += dx;
523.  	    if (err >= dy) {
524.  		x += x_change;
525.  		err -= dy;
526.  	    }
527.  	/* check for early exit condition */
528.  	if (!(keep_going = (*check_proc)(arg, x, y)))
529.  	    break;
530.  	}
531.      } else {
532.  	while (i++ < dx) {
533.  	    prev_x = x;
534.  	    prev_y = y;
535.  	    x += x_change;
536.  	    err += dy;
537.  	    if (err >= dx) {
538.  		y += y_change;
539.  		err -= dx;
540.  	    }
541.  	/* check for early exit condition */
542.  	if (!(keep_going = (*check_proc)(arg, x, y)))
543.  	    break;
544.  	}
545.      }
546.  
547.      if (keep_going)
548.  	return TRUE;	/* successful */
549.  
550.      dest_cc->x = prev_x;
551.      dest_cc->y = prev_y;
552.      return FALSE;
553.  }
554.  
555.  /*
556.   * Single step for the hero flying through the air from jumping, flying,
557.   * etc.  Called from hurtle() and jump() via walk_path().  We expect the
558.   * argument to be a pointer to an integer -- the range -- which is
559.   * used in the calculation of points off if we hit something.
560.   *
561.   * Bumping into monsters won't cause damage but will wake them and make
562.   * them angry.  Auto-pickup isn't done, since you don't have control over
563.   * your movements at the time.
564.   *
565.   * Possible additions/changes:
566.   *	o really attack monster if we hit one
567.   *	o set stunned if we hit a wall or door
568.   *	o reset nomul when we stop
569.   *	o creepy feeling if pass through monster (if ever implemented...)
570.   *	o bounce off walls
571.   *	o let jumps go over boulders
572.   */
573.  boolean
574.  hurtle_step(arg, x, y)
575.      genericptr_t arg;
576.      int x, y;
577.  {
578.      int ox, oy, *range = (int *)arg;
579.      struct obj *obj;
580.      struct monst *mon;
581.      boolean may_pass = TRUE;
582.      struct trap *ttmp;
583.      
584.      if (!isok(x,y)) {
585.  	You_feel("the spirits holding you back.");
586.  	return FALSE;
587.      } else if (!in_out_region(x, y)) {
588.  	return FALSE;
589.      } else if (*range == 0) {
590.  	return FALSE;			/* previous step wants to stop now */
591.      }
592.  
593.      if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
594.  	if (IS_ROCK(levl[x][y].typ) || closed_door(x,y)) {
595.  	    const char *s;
596.  
597.  	    pline("Ouch!");
598.  	    if (IS_TREE(levl[x][y].typ))
599.  		s = "bumping into a tree";
600.  	    else if (IS_ROCK(levl[x][y].typ))
601.  		s = "bumping into a wall";
602.  	    else
603.  		s = "bumping into a door";
604.  	    losehp(rnd(2+*range), s, KILLED_BY);
605.  	    return FALSE;
606.  	}
607.  	if (levl[x][y].typ == IRONBARS) {
608.  	    You("crash into some iron bars.  Ouch!");
609.  	    losehp(rnd(2+*range), "crashing into iron bars", KILLED_BY);
610.  	    return FALSE;
611.  	}
612.  	if ((obj = sobj_at(BOULDER,x,y)) != 0) {
613.  	    You("bump into a %s.  Ouch!", xname(obj));
614.  	    losehp(rnd(2+*range), "bumping into a boulder", KILLED_BY);
615.  	    return FALSE;
616.  	}
617.  	if (!may_pass) {
618.  	    /* did we hit a no-dig non-wall position? */
619.  	    You("smack into something!");
620.  	    losehp(rnd(2+*range), "touching the edge of the universe", KILLED_BY);
621.  	    return FALSE;
622.  	}
623.  	if ((u.ux - x) && (u.uy - y) &&
624.  		bad_rock(&youmonst,u.ux,y) && bad_rock(&youmonst,x,u.uy)) {
625.  	    boolean too_much = (invent && (inv_weight() + weight_cap() > 600));
626.  	    /* Move at a diagonal. */
627.  	    if (bigmonst(youmonst.data) || too_much) {
628.  		You("%sget forcefully wedged into a crevice.",
629.  			too_much ? "and all your belongings " : "");
630.  		losehp(rnd(2+*range), "wedging into a narrow crevice", KILLED_BY);
631.  		return FALSE;
632.  	    }
633.  	}
634.      }
635.  
636.      if ((mon = m_at(x, y)) != 0) {
637.  	You("bump into %s.", a_monnam(mon));
638.  	wakeup(mon);
639.  	return FALSE;
640.      }
641.      if ((u.ux - x) && (u.uy - y) &&
642.  	bad_rock(&youmonst, u.ux, y) && bad_rock(&youmonst, x, u.uy)) {
643.  	/* Move at a diagonal. */
644.  	if (In_sokoban(&u.uz)) {
645.  	    You("come to an abrupt halt!");
646.  	    return FALSE;
647.  	}
648.      }
649.  
650.      ox = u.ux;
651.      oy = u.uy;
652.      u.ux = x;
653.      u.uy = y;
654.      newsym(ox, oy);		/* update old position */
655.      vision_recalc(1);		/* update for new position */
656.      flush_screen(1);
657.      /* FIXME:
658.       * Each trap should really trigger on the recoil if
659.       * it would trigger during normal movement. However,
660.       * not all the possible side-effects of this are
661.       * tested [as of 3.4.0] so we trigger those that
662.       * we have tested, and offer a message for the
663.       * ones that we have not yet tested.
664.       */
665.      if ((ttmp = t_at(x, y)) != 0) {
666.      	if (ttmp->ttyp == MAGIC_PORTAL) {
667.      		dotrap(ttmp,0);
668.      		return FALSE;
669.  	} else if (ttmp->ttyp == FIRE_TRAP) {
670.      		dotrap(ttmp,0);
671.  	} else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT ||
672.  		    ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) &&
673.  		   In_sokoban(&u.uz)) {
674.  		/* Air currents overcome the recoil */
675.      		dotrap(ttmp,0);
676.  		*range = 0;
677.  		return TRUE;
678.      	} else {
679.  		if (ttmp->tseen)
680.  		    You("pass right over %s %s.",
681.  		    	(ttmp->ttyp == ARROW_TRAP) ? "an" : "a",
682.  		    	defsyms[trap_to_defsym(ttmp->ttyp)].explanation);
683.      	}
684.      }
685.      if (--*range < 0)		/* make sure our range never goes negative */
686.  	*range = 0;
687.      if (*range != 0)
688.  	delay_output();
689.      return TRUE;
690.  }
691.  
692.  STATIC_OVL boolean
693.  mhurtle_step(arg, x, y)
694.      genericptr_t arg;
695.      int x, y;
696.  {
697.  	struct monst *mon = (struct monst *)arg;
698.  
699.  	/* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
700.  	 * rather than just stopping before.
701.  	 */
702.  	if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
703.  	    remove_monster(mon->mx, mon->my);
704.  	    newsym(mon->mx, mon->my);
705.  	    place_monster(mon, x, y);
706.  	    newsym(mon->mx, mon->my);
707.  	    set_apparxy(mon);
708.  	    (void) mintrap(mon);
709.  	    return TRUE;
710.  	}
711.  	return FALSE;
712.  }
713.  
714.  /*
715.   * The player moves through the air for a few squares as a result of
716.   * throwing or kicking something.
717.   *
718.   * dx and dy should be the direction of the hurtle, not of the original
719.   * kick or throw and be only.
720.   */
721.  void
722.  hurtle(dx, dy, range, verbose)
723.      int dx, dy, range;
724.      boolean verbose;
725.  {
726.      coord uc, cc;
727.  
728.      /* The chain is stretched vertically, so you shouldn't be able to move
729.       * very far diagonally.  The premise that you should be able to move one
730.       * spot leads to calculations that allow you to only move one spot away
731.       * from the ball, if you are levitating over the ball, or one spot
732.       * towards the ball, if you are at the end of the chain.  Rather than
733.       * bother with all of that, assume that there is no slack in the chain
734.       * for diagonal movement, give the player a message and return.
735.       */
736.      if(Punished && !carried(uball)) {
737.  	You_feel("a tug from the iron ball.");
738.  	nomul(0);
739.  	return;
740.      } else if (u.utrap) {
741.  	You("are anchored by the %s.",
742.  	    u.utraptype == TT_WEB ? "web" : u.utraptype == TT_LAVA ? "lava" :
743.  		u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) : "trap");
744.  	nomul(0);
745.  	return;
746.      }
747.  
748.      /* make sure dx and dy are [-1,0,1] */
749.      dx = sgn(dx);
750.      dy = sgn(dy);
751.  
752.      if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
753.  
754.      nomul(-range);
755.      nomovemsg = 0;
756.      if (verbose)
757.  	You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
758.      /* if we're in the midst of shooting multiple projectiles, stop */
759.      if (m_shot.i < m_shot.n) {
760.  	/* last message before hurtling was "you shoot N arrows" */
761.  	You("stop %sing after the first %s.",
762.  	    m_shot.s ? "shoot" : "throw", m_shot.s ? "shot" : "toss");
763.  	m_shot.n = m_shot.i;	/* make current shot be the last */
764.      }
765.      if (In_sokoban(&u.uz))
766.  	change_luck(-1);	/* Sokoban guilt */
767.      uc.x = u.ux;
768.      uc.y = u.uy;
769.      /* this setting of cc is only correct if dx and dy are [-1,0,1] only */
770.      cc.x = u.ux + (dx * range);
771.      cc.y = u.uy + (dy * range);
772.      (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range);
773.      teleds(cc.x, cc.y, FALSE);
774.  }
775.  
776.  /* Move a monster through the air for a few squares.
777.   */
778.  void
779.  mhurtle(mon, dx, dy, range)
780.  	struct monst *mon;
781.  	int dx, dy, range;
782.  {
783.      coord mc, cc;
784.  
785.  	/* At the very least, debilitate the monster */
786.  	mon->movement = 0;
787.  	mon->mstun = 1;
788.  
789.  	/* Is the monster stuck or too heavy to push?
790.  	 * (very large monsters have too much inertia, even floaters and flyers)
791.  	 */
792.  	if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped)
793.  	    return;
794.  
795.      /* Make sure dx and dy are [-1,0,1] */
796.      dx = sgn(dx);
797.      dy = sgn(dy);
798.      if(!range || (!dx && !dy)) return; /* paranoia */
799.  
800.  	/* Send the monster along the path */
801.  	mc.x = mon->mx;
802.  	mc.y = mon->my;
803.  	cc.x = mon->mx + (dx * range);
804.  	cc.y = mon->my + (dy * range);
805.  	(void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t)mon);
806.  	return;
807.  }
808.  
809.  STATIC_OVL void
810.  check_shop_obj(obj, x, y, broken)
811.  register struct obj *obj;
812.  register xchar x, y;
813.  register boolean broken;
814.  {
815.  	struct monst *shkp = shop_keeper(*u.ushops);
816.  
817.  	if(!shkp) return;
818.  
819.  	if(broken) {
820.  		if (obj->unpaid) {
821.  		    (void)stolen_value(obj, u.ux, u.uy,
822.  				       (boolean)shkp->mpeaceful, FALSE, TRUE);
823.  		    subfrombill(obj, shkp);
824.  		}
825.  		obj->no_charge = 1;
826.  		return;
827.  	}
828.  
829.  	if (!costly_spot(x, y) || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
830.  		/* thrown out of a shop or into a different shop */
831.  		if (obj->unpaid) {
832.  		    (void)stolen_value(obj, u.ux, u.uy,
833.  				       (boolean)shkp->mpeaceful, FALSE, FALSE);
834.  		    subfrombill(obj, shkp);
835.  		}
836.  	} else {
837.  		if (costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
838.  		    if(obj->unpaid) subfrombill(obj, shkp);
839.  		    else if(!(x == shkp->mx && y == shkp->my))
840.  			    sellobj(obj, x, y);
841.  		}
842.  	}
843.  }
844.  
845.  /*
846.   * Hero tosses an object upwards with appropriate consequences.
847.   *
848.   * Returns FALSE if the object is gone.
849.   */
850.  STATIC_OVL boolean
851.  toss_up(obj, hitsroof)
852.  struct obj *obj;
853.  boolean hitsroof;
854.  {
855.      const char *almost;
856.      /* note: obj->quan == 1 */
857.  
858.      if (hitsroof) {
859.  	if (breaktest(obj)) {
860.  		pline("%s hits the %s.", Doname2(obj), ceiling(u.ux, u.uy));
861.  		breakmsg(obj, !Blind);
862.  		breakobj(obj, u.ux, u.uy, TRUE, TRUE);
863.  		return FALSE;
864.  	}
865.  	almost = "";
866.      } else {
867.  	almost = " almost";
868.      }
869.      pline("%s%s hits the %s, then falls back on top of your %s.",
870.  	  Doname2(obj), almost, ceiling(u.ux,u.uy), body_part(HEAD));
871.  
872.      /* object now hits you */
873.  
874.      if (obj->oclass == POTION_CLASS) {
875.  	potionhit(&youmonst, obj, TRUE);
876.      } else if (breaktest(obj)) {
877.  	int otyp = obj->otyp, ocorpsenm = obj->corpsenm;
878.  	int blindinc;
879.  
880.  	/* need to check for blindness result prior to destroying obj */
881.  	blindinc = (otyp == CREAM_PIE || otyp == BLINDING_VENOM) &&
882.  		   /* AT_WEAP is ok here even if attack type was AT_SPIT */
883.  		   can_blnd(&youmonst, &youmonst, AT_WEAP, obj) ? rnd(25) : 0;
884.  
885.  	breakmsg(obj, !Blind);
886.  	breakobj(obj, u.ux, u.uy, TRUE, TRUE);
887.  	obj = 0;	/* it's now gone */
888.  	switch (otyp) {
889.  	case EGG:
890.  		if (touch_petrifies(&mons[ocorpsenm]) &&
891.  		    !uarmh && !Stone_resistance &&
892.  		    !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)))
893.  		goto petrify;
894.  	case CREAM_PIE:
895.  	case BLINDING_VENOM:
896.  		pline("You've got it all over your %s!", body_part(FACE));
897.  		if (blindinc) {
898.  		    if (otyp == BLINDING_VENOM && !Blind)
899.  			pline("It blinds you!");
900.  		    u.ucreamed += blindinc;
901.  		    make_blinded(Blinded + (long)blindinc, FALSE);
902.  		    if (!Blind) Your(vision_clears);
903.  		}
904.  		break;
905.  	default:
906.  		break;
907.  	}
908.  	return FALSE;
909.      } else {		/* neither potion nor other breaking object */
910.  	boolean less_damage = uarmh && is_metallic(uarmh), artimsg = FALSE;
911.  	int dmg = dmgval(obj, &youmonst);
912.  
913.  	if (obj->oartifact)
914.  	    /* need a fake die roll here; rn1(18,2) avoids 1 and 20 */
915.  	    artimsg = artifact_hit((struct monst *)0, &youmonst,
916.  				   obj, &dmg, rn1(18,2));
917.  
918.  	if (!dmg) {	/* probably wasn't a weapon; base damage on weight */
919.  	    dmg = (int) obj->owt / 100;
920.  	    if (dmg < 1) dmg = 1;
921.  	    else if (dmg > 6) dmg = 6;
922.  	    if (youmonst.data == &mons[PM_SHADE] &&
923.  		    objects[obj->otyp].oc_material != SILVER)
924.  		dmg = 0;
925.  	}
926.  	if (dmg > 1 && less_damage) dmg = 1;
927.  	if (dmg > 0) dmg += u.udaminc;
928.  	if (dmg < 0) dmg = 0;	/* beware negative rings of increase damage */
929.  	if (Half_physical_damage) dmg = (dmg + 1) / 2;
930.  
931.  	if (uarmh) {
932.  	    if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) {
933.  		if (!artimsg)
934.  		    pline("Fortunately, you are wearing a hard helmet.");
935.  	    } else if (flags.verbose &&
936.  		    !(obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])))
937.  		Your("%s does not protect you.", xname(uarmh));
938.  	} else if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
939.  	    if (!Stone_resistance &&
940.  		    !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
941.   petrify:
942.  		killer_format = KILLED_BY;
943.  		killer = "elementary physics";	/* "what goes up..." */
944.  		You("turn to stone.");
945.  		if (obj) dropy(obj);	/* bypass most of hitfloor() */
946.  		done(STONING);
947.  		return obj ? TRUE : FALSE;
948.  	    }
949.  	}
950.  	hitfloor(obj);
951.  	losehp(dmg, "falling object", KILLED_BY_AN);
952.      }
953.      return TRUE;
954.  }
955.  
956.  /* return true for weapon meant to be thrown; excludes ammo */
957.  STATIC_OVL boolean
958.  throwing_weapon(obj)
959.  struct obj *obj;
960.  {
961.  	return (is_missile(obj) || is_spear(obj) ||
962.  		/* daggers and knife (excludes scalpel) */
963.  		(is_blade(obj) && !is_sword(obj) &&
964.  		 (objects[obj->otyp].oc_dir & PIERCE)) ||
965.  		/* special cases [might want to add AXE] */
966.  		obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
967.  }
968.  
969.  /* the currently thrown object is returning to you (not for boomerangs) */
970.  STATIC_OVL void
971.  sho_obj_return_to_u(obj)
972.  struct obj *obj;
973.  {
974.      /* might already be our location (bounced off a wall) */
975.      if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
976.  	int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
977.  
978.  	tmp_at(DISP_FLASH, obj_to_glyph(obj));
979.  	while(x != u.ux || y != u.uy) {
980.  	    tmp_at(x, y);
981.  	    delay_output();
982.  	    x -= u.dx; y -= u.dy;
983.  	}
984.  	tmp_at(DISP_END, 0);
985.      }
986.  }
987.  
988.  void
989.  throwit(obj, wep_mask, twoweap, thrown)
990.  struct obj *obj;
991.  long wep_mask;	/* used to re-equip returning boomerang */
992.  boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
993.  int thrown;
994.  {
995.  	register struct monst *mon;
996.  	register int range, urange;
997.  	struct obj *launcher = (struct obj*) 0;
998.  	boolean impaired = (Confusion || Stunned || Blind ||
999.  			   Hallucination || Fumbling);
1000. 
1001. 	if (thrown == 1) launcher = uwep;
1002. 	else if (thrown == 2) launcher = uswapwep;
1003. 	
1004. 	/* KMH -- Handle Plague here */
1005. 	if (launcher && launcher->oartifact == ART_PLAGUE &&
1006. 			ammo_and_launcher(obj, launcher) && is_poisonable(obj))
1007. 		obj->opoisoned = 1;
1008. 
1009. 	obj->was_thrown = 1;
1010. 	if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
1011. 	    boolean slipok = TRUE;
1012. 	    if (ammo_and_launcher(obj, launcher))
1013. 		pline("%s!", Tobjnam(obj, "misfire"));
1014. 	    else {
1015. 		/* only slip if it's greased or meant to be thrown */
1016. 		if (obj->greased || throwing_weapon(obj))
1017. 		    /* BUG: this message is grammatically incorrect if obj has
1018. 		       a plural name; greased gloves or boots for instance. */
1019. 		    pline("%s as you throw it!", Tobjnam(obj, "slip"));
1020. 		else slipok = FALSE;
1021. 	    }
1022. 	    if (slipok) {
1023. 		u.dx = rn2(3)-1;
1024. 		u.dy = rn2(3)-1;
1025. 		if (!u.dx && !u.dy) u.dz = 1;
1026. 		impaired = TRUE;
1027. 	    }
1028. 	}
1029. 
1030. 	if ((u.dx || u.dy || (u.dz < 1)) &&
1031. 	    calc_capacity((int)obj->owt) > SLT_ENCUMBER &&
1032. 	    (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1033. 	     : (u.uhp < 10 && u.uhp != u.uhpmax)) &&
1034. 	    obj->owt > (unsigned)((Upolyd ? u.mh : u.uhp) * 2) &&
1035. 	    !Is_airlevel(&u.uz)) {
1036. 	    You("have so little stamina, %s drops from your grasp.",
1037. 		the(xname(obj)));
1038. 	    exercise(A_CON, FALSE);
1039. 	    u.dx = u.dy = 0;
1040. 	    u.dz = 1;
1041. 	}
1042. 
1043. 	thrownobj = obj;
1044. 
1045. 	if(u.uswallow) {
1046. 		mon = u.ustuck;
1047. 		bhitpos.x = mon->mx;
1048. 		bhitpos.y = mon->my;
1049. 	} else if(u.dz) {
1050. 	    if (u.dz < 0 && Role_if(PM_VALKYRIE) &&
1051. 		    obj->oartifact == ART_MJOLLNIR && !impaired) {
1052. 		pline("%s the %s and returns to your hand!",
1053. 		      Tobjnam(obj, "hit"), ceiling(u.ux,u.uy));
1054. 		obj = addinv(obj);
1055. 		(void) encumber_msg();
1056. 		setuwep(obj, TRUE);
1057. 		u.twoweap = twoweap;
1058. /*            if (!fire_weapon) setuwep(obj);                
1059.             else setuqwep(obj);*/
1060. 		return;
1061. 	    }
1062. #ifdef FIREARMS
1063. 	    /* [ALI]
1064. 	     * Grenades are armed but are then processed by toss_up/hitfloor
1065. 	     * as normal.
1066. 	     *
1067. 	     * Bullets just disappear with no message.
1068. 	     *
1069. 	     * Rockets hit the ceiling/floor and explode.
1070. 	     */
1071. 	    else if (is_grenade(obj))
1072. 		arm_bomb(obj, TRUE);
1073. 	    else if (is_bullet(obj) && ammo_and_launcher(obj, launcher)) {
1074. 		if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !Underwater
1075. 			&& (objects[obj->otyp].oc_dir & EXPLOSION)) {
1076. 		    pline("%s hit%s the %s and explodes in a ball of fire!",
1077. 			    Doname2(obj), (obj->quan == 1L) ? "s" : "",
1078. 			    u.dz < 0 ? ceiling(u.ux, u.uy) : surface(u.ux, u.uy));
1079. 		    explode(u.ux, u.uy, ZT_SPELL(ZT_FIRE), d(3, 8),
1080. 			    WEAPON_CLASS, EXPL_FIERY);
1081. 		}
1082. 		check_shop_obj(obj, u.ux, u.uy, TRUE);
1083. 		obfree(obj, (struct obj *)0);
1084. 		return;
1085. 	    }
1086. #endif
1087. 	    if (u.dz < 0 && !Is_airlevel(&u.uz) &&
1088. 		    !Underwater && !Is_waterlevel(&u.uz)) {
1089. 		(void) toss_up(obj, rn2(5));
1090. 	    } else {
1091. 		hitfloor(obj);
1092. 	    }
1093. 	    thrownobj = (struct obj*)0;
1094. 	    return;
1095. 
1096. 	} else if(obj->otyp == BOOMERANG && !Underwater) {
1097. 		if(Is_airlevel(&u.uz) || Levitation)
1098. 		    hurtle(-u.dx, -u.dy, 1, TRUE);
1099. 		mon = boomhit(u.dx, u.dy);
1100. 		if(mon == &youmonst) {		/* the thing was caught */
1101. 			exercise(A_DEX, TRUE);
1102. 			obj = addinv(obj);
1103. 			(void) encumber_msg();
1104. 			if (wep_mask && !(obj->owornmask & wep_mask)) {
1105. 			    setworn(obj, wep_mask);
1106. 			    u.twoweap = twoweap;
1107. 			}
1108. 			thrownobj = (struct obj*)0;
1109. 			return;
1110. 		}
1111. 	} else {
1112. 		urange = (int)(ACURRSTR)/2;
1113. 		/* balls are easy to throw or at least roll */
1114. 		/* also, this insures the maximum range of a ball is greater
1115. 		 * than 1, so the effects from throwing attached balls are
1116. 		 * actually possible
1117. 		 */
1118. 		if (obj->otyp == HEAVY_IRON_BALL)
1119. 			range = urange - (int)(obj->owt/100);
1120. 		else
1121. 			range = urange - (int)(obj->owt/40);
1122. 		if (obj == uball) {
1123. 			if (u.ustuck) range = 1;
1124. 			else if (range >= 5) range = 5;
1125. 		}
1126. 		if (range < 1) range = 1;
1127. 
1128. 		/* KMH, balance patch -- new macros */
1129. 		if (is_ammo(obj)) {
1130. 		    if (ammo_and_launcher(obj, launcher)) {
1131. #ifdef FIREARMS
1132. 			if (is_launcher(launcher) && 
1133. 					objects[(launcher->otyp)].oc_range) 
1134. 				range = objects[(launcher->otyp)].oc_range;
1135. 		    else
1136. #endif
1137. 			range++;
1138. 		    } else if (obj->oclass != GEM_CLASS)
1139. 			range /= 2;
1140. 		}
1141. 
1142. 		if (Is_airlevel(&u.uz) || Levitation) {
1143. 		    /* action, reaction... */
1144. 		    urange -= range;
1145. 		    if(urange < 1) urange = 1;
1146. 		    range -= urange;
1147. 		    if(range < 1) range = 1;
1148. 		}
1149. 
1150. 		if (obj->otyp == BOULDER)
1151. 		    range = 20;		/* you must be giant */
1152. 		else if (obj->oartifact == ART_MJOLLNIR)
1153. 		    range = (range + 1) / 2;	/* it's heavy */
1154. 		else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
1155. 		    range = 1;
1156. 
1157. 		if (Underwater) range = 1;
1158. 
1159. 		mon = bhit(u.dx,u.dy,range,THROWN_WEAPON,
1160. 			   (int FDECL((*),(MONST_P,OBJ_P)))0,
1161. 			   (int FDECL((*),(OBJ_P,OBJ_P)))0,
1162. 			   &obj);
1163. 
1164. 		/* have to do this after bhit() so u.ux & u.uy are correct */
1165. 		if(Is_airlevel(&u.uz) || Levitation)
1166. 		    hurtle(-u.dx, -u.dy, urange, TRUE);
1167. 
1168. 		if (!obj) {
1169. 		    thrownobj = (struct obj *)0;
1170. 		    return;
1171. 		}
1172. 	}
1173. 
1174. 	if(mon) {
1175. 		boolean obj_gone;
1176. 
1177. 		if (mon->isshk &&
1178. 		    obj->where == OBJ_MINVENT && obj->ocarry == mon) {
1179. 		    thrownobj = (struct obj*)0;
1180. 		    return;		/* alert shk caught it */
1181. 		}
1182. 		(void) snuff_candle(obj);
1183. 		notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
1184. 		obj_gone = thitmonst(mon, obj, thrown);
1185. 		/* Monster may have been tamed; this frees old mon */
1186. 		mon = m_at(bhitpos.x, bhitpos.y);
1187. 
1188. 		/* [perhaps this should be moved into thitmonst or hmon] */
1189. 		if (mon && mon->isshk &&
1190. 			(!inside_shop(u.ux, u.uy) ||
1191. 			 !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)))
1192. 		    hot_pursuit(mon);
1193. 
1194. 		if (obj_gone) return;
1195. 	}
1196. 
1197. #ifdef FIREARMS
1198. 	/* Handle grenades or rockets */
1199. 	if (is_grenade(obj)) {
1200. 	    arm_bomb(obj, TRUE);
1201. 	} else if (ammo_and_launcher(obj, launcher) &&
1202. 		(objects[obj->otyp].oc_dir & EXPLOSION)) {
1203. 	    if (cansee(bhitpos.x,bhitpos.y)) 
1204. 		pline("%s explodes in a ball of fire!", Doname2(obj));
1205. 	    else You_hear("an explosion");
1206. 	    explode(bhitpos.x, bhitpos.y, ZT_SPELL(ZT_FIRE),
1207. 		    d(3,8), WEAPON_CLASS, EXPL_FIERY);
1208. 	}
1209. 	if (is_bullet(obj) && (ammo_and_launcher(obj, launcher) &&
1210. 		!is_grenade(obj))) {
1211. 	    check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
1212. 	    obfree(obj, (struct obj *)0);
1213. 	    return;
1214. 	}
1215. #endif
1216. 
1217. 	if (u.uswallow) {
1218. 		/* ball is not picked up by monster */
1219. 		if (obj != uball) (void) mpickobj(u.ustuck,obj);
1220. 	} else {
1221. 		/* the code following might become part of dropy() */
1222. 		if (obj->oartifact == ART_MJOLLNIR &&
1223. 			Role_if(PM_VALKYRIE) && rn2(100)) {
1224. 		    /* we must be wearing Gauntlets of Power to get here */
1225. 		    sho_obj_return_to_u(obj);	    /* display its flight */
1226. 
1227. 		    if (!impaired && rn2(100)) {
1228. 			pline("%s to your hand!", Tobjnam(obj, "return"));
1229. 			obj = addinv(obj);
1230. 			(void) encumber_msg();
1231. 			setuwep(obj, TRUE);
1232. 			u.twoweap = twoweap;
1233. 			if(cansee(bhitpos.x, bhitpos.y))
1234. 			    newsym(bhitpos.x,bhitpos.y);
1235. 		    } else {
1236. 			int dmg = rn2(2);
1237. 			if (!dmg) {
1238. 			    pline(Blind ? "%s lands %s your %s." :
1239. 					"%s back to you, landing %s your %s.",
1240. 				  Blind ? Something : Tobjnam(obj, "return"),
1241. 				  Levitation ? "beneath" : "at",
1242. 				  makeplural(body_part(FOOT)));
1243. 			} else {
1244. 			    dmg += rnd(3);
1245. 			    pline(Blind ? "%s your %s!" :
1246. 					"%s back toward you, hitting your %s!",
1247. 				  Tobjnam(obj, Blind ? "hit" : "fly"),
1248. 				  body_part(ARM));
1249. 			    (void) artifact_hit((struct monst *)0,
1250. 						&youmonst, obj, &dmg, 0);
1251. 			    losehp(dmg, xname(obj),
1252. 				obj_is_pname(obj) ? KILLED_BY : KILLED_BY_AN);
1253. 			}
1254. 			if (ship_object(obj, u.ux, u.uy, FALSE)) {
1255. 		    	    thrownobj = (struct obj*)0;
1256. 			    return;
1257. 			}
1258. 			dropy(obj);
1259. 		    }
1260. 		    thrownobj = (struct obj*)0;
1261. 		    return;
1262. 		}
1263. 
1264. 		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
1265. 			breaktest(obj)) {
1266. 		    tmp_at(DISP_FLASH, obj_to_glyph(obj));
1267. 		    tmp_at(bhitpos.x, bhitpos.y);
1268. 		    delay_output();
1269. 		    tmp_at(DISP_END, 0);
1270. 		    breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
1271. 		    breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
1272. 		    return;
1273. 		}
1274. 		if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return;
1275. 		obj_no_longer_held(obj);
1276. 		if (mon && mon->isshk && is_pick(obj)) {
1277. 		    if (cansee(bhitpos.x, bhitpos.y))
1278. 			pline("%s snatches up %s.",
1279. 			      Monnam(mon), the(xname(obj)));
1280. 		    if(*u.ushops)
1281. 			check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1282. 		    (void) mpickobj(mon, obj);	/* may merge and free obj */
1283. 		    thrownobj = (struct obj*)0;
1284. 		    return;
1285. 		}
1286. 		(void) snuff_candle(obj);
1287. 		if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) {
1288. 		    thrownobj = (struct obj*)0;
1289. 		    return;
1290. 		}
1291. 		thrownobj = (struct obj*)0;
1292. 		place_object(obj, bhitpos.x, bhitpos.y);
1293. 		if(*u.ushops && obj != uball)
1294. 		    check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1295. 
1296. 		stackobj(obj);
1297. 		if (obj == uball)
1298. 		    drop_ball(bhitpos.x, bhitpos.y);
1299. 		if (cansee(bhitpos.x, bhitpos.y))
1300. 		    newsym(bhitpos.x,bhitpos.y);
1301. 		if (obj_sheds_light(obj))
1302. 		    vision_full_recalc = 1;
1303. 		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ))
1304. 		    container_impact_dmg(obj);
1305. 	}
1306. }
1307. 
1308. /* an object may hit a monster; various factors adjust the chance of hitting */
1309. int
1310. omon_adj(mon, obj, mon_notices)
1311. struct monst *mon;
1312. struct obj *obj;
1313. boolean mon_notices;
1314. {
1315. 	int tmp = 0;
1316. 
1317. 	/* size of target affects the chance of hitting */
1318. 	tmp += (mon->data->msize - MZ_MEDIUM);		/* -2..+5 */
1319. 	/* sleeping target is more likely to be hit */
1320. 	if (mon->msleeping) {
1321. 	    tmp += 2;
1322. 	    if (mon_notices) mon->msleeping = 0;
1323. 	}
1324. 	/* ditto for immobilized target */
1325. 	if (!mon->mcanmove || !mon->data->mmove) {
1326. 	    tmp += 4;
1327. 	    if (mon_notices && mon->data->mmove && !rn2(10)) {
1328. 		mon->mcanmove = 1;
1329. 		mon->mfrozen = 0;
1330. 	    }
1331. 	}
1332. 	/* some objects are more likely to hit than others */
1333. 	switch (obj->otyp) {
1334. 	case HEAVY_IRON_BALL:
1335. 	    if (obj != uball) tmp += 2;
1336. 	    break;
1337. 	case BOULDER:
1338. 	    tmp += 6;
1339. 	    break;
1340. 	default:
1341. 	    if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
1342. 		    obj->oclass == GEM_CLASS)
1343. 		tmp += hitval(obj, mon);
1344. 	    break;
1345. 	}
1346. 	return tmp;
1347. }
1348. 
1349. /* thrown object misses target monster */
1350. STATIC_OVL void
1351. tmiss(obj, mon)
1352. struct obj *obj;
1353. struct monst *mon;
1354. {
1355.     const char *missile = mshot_xname(obj);
1356. 
1357.     /* If the target can't be seen or doesn't look like a valid target,
1358.        avoid "the arrow misses it," or worse, "the arrows misses the mimic."
1359.        An attentive player will still notice that this is different from
1360.        an arrow just landing short of any target (no message in that case),
1361.        so will realize that there is a valid target here anyway. */
1362.     if (!canseemon(mon) || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER))
1363. 	pline("%s %s.", The(missile), otense(obj, "miss"));
1364.     else
1365. 	miss(missile, mon);
1366.     if (!rn2(3)) wakeup(mon);
1367.     return;
1368. }
1369. 
1370. #define quest_arti_hits_leader(obj,mon)	\
1371.   (obj->oartifact && is_quest_artifact(obj) && (mon->data->msound == MS_LEADER))
1372. 
1373. /*
1374.  * Object thrown by player arrives at monster's location.
1375.  * Return 1 if obj has disappeared or otherwise been taken care of,
1376.  * 0 if caller must take care of it.
1377.  */
1378. int
1379. thitmonst(mon, obj, thrown)
1380. register struct monst *mon;
1381. register struct obj   *obj;
1382. int thrown;
1383. {
1384. 	register int	tmp; /* Base chance to hit */
1385. 	register int	disttmp; /* distance modifier */
1386. 	struct obj *launcher;
1387. 	
1388. 	int otyp = obj->otyp;
1389. 	boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
1390. 
1391. 	/* Differences from melee weapons:
1392. 	 *
1393. 	 * Dex still gives a bonus, but strength does not.
1394. 	 * Polymorphed players lacking attacks may still throw.
1395. 	 * There's a base -1 to hit.
1396. 	 * No bonuses for fleeing or stunned targets (they don't dodge
1397. 	 *    melee blows as readily, but dodging arrows is hard anyway).
1398. 	 * Not affected by traps, etc.
1399. 	 * Certain items which don't in themselves do damage ignore tmp.
1400. 	 * Distance and monster size affect chance to hit.
1401. 	 */
1402. 	/* KMH -- added ring of increase accuracy */
1403. 
1404. 	if (thrown == 1) launcher = uwep;
1405. 	else if (thrown == 2) launcher = uswapwep;
1406. 	else launcher = (struct obj *)0;
1407. 
1408. 	tmp = -1 + Luck + find_mac(mon) + u.uhitinc +
1409. 			maybe_polyd(youmonst.data->mlevel, u.ulevel);
1410. 	if (ACURR(A_DEX) < 4) tmp -= 3;
1411. 	else if (ACURR(A_DEX) < 6) tmp -= 2;
1412. 	else if (ACURR(A_DEX) < 8) tmp -= 1;
1413. 	else if (ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
1414. 
1415. 	/* Modify to-hit depending on distance; but keep it sane.
1416. 	 * Polearms get a distance penalty even when wielded; it's
1417. 	 * hard to hit at a distance.
1418. 	 */
1419. 	disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
1420. 	if(disttmp < -4) disttmp = -4;
1421. 	tmp += disttmp;
1422. 
1423. 	/* gloves are a hinderance to proper use of bows */
1424. 	if (uarmg && launcher && objects[launcher->otyp].oc_skill == P_BOW) {
1425. 	    switch (uarmg->otyp) {
1426. 	    case GAUNTLETS_OF_POWER:    /* metal */
1427. 		tmp -= 2;
1428. 		break;
1429. 	    case GAUNTLETS_OF_FUMBLING:
1430. 		tmp -= 3;
1431. 		break;
1432. 	    case LEATHER_GLOVES:
1433. 	    case GAUNTLETS_OF_SWIMMING:            
1434. 	    case GAUNTLETS_OF_DEXTERITY:
1435. 		break;
1436. 	    default:
1437. 		impossible("Unknown type of gloves (%d)", uarmg->otyp);
1438. 		break;
1439. 	    }
1440. 	}
1441. 
1442. 	tmp += omon_adj(mon, obj, TRUE);
1443. 	if (is_orc(mon->data) && maybe_polyd(is_elf(youmonst.data),
1444. 			Race_if(PM_ELF)))
1445. 	    tmp++;
1446. 	if (guaranteed_hit) {
1447. 	    tmp += 1000; /* Guaranteed hit */
1448. 	}
1449. 
1450. 	/* sleeping unicorns don't catch gems */
1451. 	if (obj->oclass == GEM_CLASS && is_unicorn(mon->data) && !mon->msleeping) {
1452. 	    if (mon->mtame) {
1453. 		pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
1454. 		return 0;
1455. 	    } else {
1456. 		pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1457. 		return gem_accept(mon, obj);
1458. 	    }
1459. 	}
1460. 
1461. 	/* don't make game unwinnable if naive player throws artifact
1462. 	   at leader.... */
1463. 	if (quest_arti_hits_leader(obj, mon)) {
1464. 	    /* not wakeup(), which angers non-tame monsters */
1465. 	    mon->msleeping = 0;
1466. 	    mon->mstrategy &= ~STRAT_WAITMASK;
1467. 
1468. 	    if (mon->mcanmove) {
1469. 		pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1470. 		if (mon->mpeaceful) {
1471. 		    boolean next2u = monnear(mon, u.ux, u.uy);
1472. 
1473. 		    finish_quest(obj);	/* acknowledge quest completion */
1474. 		    pline("%s %s %s back to you.", Monnam(mon),
1475. 			  (next2u ? "hands" : "tosses"), the(xname(obj)));
1476. 		    if (!next2u) sho_obj_return_to_u(obj);
1477. 		    obj = addinv(obj);	/* back into your inventory */
1478. 		    (void) encumber_msg();
1479. 		} else {
1480. 		    /* angry leader caught it and isn't returning it */
1481. 		    (void) mpickobj(mon, obj);
1482. 		}
1483. 		return 1;		/* caller doesn't need to place it */
1484. 	    }
1485. 	    return(0);
1486. 	}
1487. 
1488. 	if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
1489. 		obj->oclass == GEM_CLASS) {
1490. 	    if (is_ammo(obj)) {
1491. 		if (!ammo_and_launcher(obj, launcher)) {
1492. 		    tmp -= 4;
1493. 		} else {
1494. 		    tmp += launcher->spe - greatest_erosion(launcher);
1495. 		    tmp += weapon_hit_bonus(launcher);
1496. 		    if (launcher->oartifact) tmp += spec_abon(launcher, mon);
1497. 		    /*
1498. 		     * Elves and Samurais are highly trained w/bows,
1499. 		     * especially their own special types of bow.
1500. 		     * Polymorphing won't make you a bow expert.
1501. 		     */
1502. 		    if ((Race_if(PM_ELF) || Race_if(PM_DROW) ||
1503. 		    		Role_if(PM_SAMURAI)) &&
1504. 				(!Upolyd || your_race(youmonst.data)) &&
1505. 				objects[launcher->otyp].oc_skill == P_BOW) {
1506. 			tmp++;
1507. 			if (Race_if(PM_ELF) && launcher->otyp == ELVEN_BOW)
1508. 			tmp++;
1509. 			else if (Race_if(PM_DROW) && launcher->otyp == DARK_ELVEN_BOW)
1510. 			    tmp++;
1511. 			else if (Role_if(PM_SAMURAI) && launcher->otyp == YUMI)
1512. 			    tmp++;
1513. 		    }
1514. 		}
1515. 	    } else {
1516. 		if (otyp == BOOMERANG)		/* arbitrary */
1517. 		    tmp += 4;
1518. 		else if (throwing_weapon(obj))	/* meant to be thrown */
1519. 		    tmp += 2;
1520. 		else				/* not meant to be thrown */
1521. 		    tmp -= 2;
1522. 		/* we know we're dealing with a weapon or weptool handled
1523. 		   by WEAPON_SKILLS once ammo objects have been excluded */
1524. 		tmp += weapon_hit_bonus(obj);
1525. 	    }
1526. #ifdef DEBUG
1527. 	    pline("(%i/20)", tmp);
1528. #endif
1529. 
1530. 	    if (tmp >= rnd(20)) {
1531. 		if (hmon(mon,obj,thrown?thrown:3)) {  /* mon still alive */
1532. 		    (void) cutworm(mon, bhitpos.x, bhitpos.y, obj);
1533. 		}
1534. 		exercise(A_DEX, TRUE);
1535. 
1536. 		/* Detonate bolts shot by Hellfire */
1537. 		if (ammo_and_launcher(obj, launcher) &&
1538. 			(launcher->oartifact == ART_HELLFIRE)) {
1539. 		    if (cansee(bhitpos.x,bhitpos.y)) 
1540. 			pline("%s explodes in a ball of fire!", Doname2(obj));
1541. 		    else You_hear("an explosion");
1542. 		    explode(bhitpos.x, bhitpos.y, ZT_SPELL(ZT_FIRE),
1543. 			    d(2,6), WEAPON_CLASS, EXPL_FIERY);
1544. 		}
1545. 
1546. 		/* projectiles other than magic stones
1547. 		 * sometimes disappear when thrown
1548. 		 * WAC - Spoon always disappears after doing damage
1549. 		 */
1550. 		if (((objects[otyp].oc_skill < P_NONE && 
1551. 			objects[otyp].oc_skill > -P_BOOMERANG) ||
1552. 			(obj->oclass == GEM_CLASS && 
1553. 			!objects[otyp].oc_magic))
1554. # ifdef P_SPOON
1555. 			|| (obj->oartifact == ART_HOUCHOU)
1556. # endif
1557. 			/* WAC catch Hellfire */
1558. 			|| (launcher && launcher->oartifact == ART_HELLFIRE 
1559. 			&& is_ammo(obj) && ammo_and_launcher(obj, launcher))
1560. 		   ) {
1561. 		    /* we were breaking 2/3 of everything unconditionally.
1562. 		     * we still don't want anything to survive unconditionally,
1563. 		     * but we need ammo to stay around longer on average.
1564. 		     */
1565. 		    int broken, chance;
1566. 		    chance = 3 + greatest_erosion(obj) - obj->spe;
1567. 		    if (chance > 1)
1568. 			broken = rn2(chance);
1569. 		    else
1570. 			broken = !rn2(4);
1571. 		    if (obj->blessed && !rnl(4))
1572. 			broken = 0;
1573. 
1574. 		    if (broken) {
1575. 			if (*u.ushops)
1576. 			    check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
1577. #ifdef FIREARMS
1578. 			/*
1579. 			 * Thrown grenades and explosive ammo used with the
1580. 			 * relevant launcher explode rather than simply
1581. 			 * breaking.
1582. 			 */
1583. 			if ((thrown == 1 || thrown == 2) && is_grenade(obj)) {
1584. 			    grenade_explode(obj, bhitpos.x, bhitpos.y, TRUE, 0);
1585. 			} else if (ammo_and_launcher(obj, launcher) &&
1586. 				(objects[obj->otyp].oc_dir & EXPLOSION)) {
1587. 			    if (cansee(bhitpos.x,bhitpos.y)) 
1588. 				pline("%s explodes in a ball of fire!",
1589. 					Doname2(obj));
1590. 			    else You_hear("an explosion");
1591. 			    explode(bhitpos.x, bhitpos.y, ZT_SPELL(ZT_FIRE),
1592. 				    d(3,8), WEAPON_CLASS, EXPL_FIERY);
1593. 			    obfree(obj, (struct obj *)0);
1594. 			} else
1595. #endif
1596. 			obfree(obj, (struct obj *)0);
1597. 			return 1;
1598. 		    }
1599. 		}
1600. 		passive_obj(mon, obj, (struct attack *)0);
1601. 	    } else {
1602. 		tmiss(obj, mon);
1603. 	    }
1604. 
1605. 	} else if (otyp == HEAVY_IRON_BALL) {
1606. 	    exercise(A_STR, TRUE);
1607. 	    if (tmp >= rnd(20)) {
1608. 		int was_swallowed = guaranteed_hit;
1609. 
1610. 		exercise(A_DEX, TRUE);
1611. 		if (!hmon(mon,obj,thrown?thrown:3)) {         /* mon killed */
1612. 		    if (was_swallowed && !u.uswallow && obj == uball)
1613. 			return 1;	/* already did placebc() */
1614. 		}
1615. 	    } else {
1616. 		tmiss(obj, mon);
1617. 	    }
1618. 
1619. 	} else if (otyp == BOULDER) {
1620. 	    exercise(A_STR, TRUE);
1621. 	    if (tmp >= rnd(20)) {
1622. 		exercise(A_DEX, TRUE);
1623. 		(void) hmon(mon,obj,thrown?thrown:3);
1624. 	    } else {
1625. 		tmiss(obj, mon);
1626. 	    }
1627. 
1628. 	} else if ((otyp == EGG || otyp == CREAM_PIE ||
1629. 		    otyp == BLINDING_VENOM || otyp == ACID_VENOM) &&
1630. 		(guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1631. 	    (void) hmon(mon, obj, thrown?thrown:3);
1632. 	    return 1;	/* hmon used it up */
1633. 
1634. 	} else if (obj->oclass == POTION_CLASS &&
1635. 		(guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1636. 	    potionhit(mon, obj, TRUE);
1637. 	    return 1;
1638. 
1639. 	} else if (befriend_with_obj(mon->data, obj) ||
1640. 		   (mon->mtame && dogfood(mon, obj) <= ACCFOOD)) {
1641. 	    if (tamedog(mon, obj))
1642. 		return 1;           	/* obj is gone */
1643. 	    else {
1644. 		/* not tmiss(), which angers non-tame monsters */
1645. 		miss(xname(obj), mon);
1646. 		mon->msleeping = 0;
1647. 		mon->mstrategy &= ~STRAT_WAITMASK;
1648. 	    }
1649. 	} else if (guaranteed_hit) {
1650. 	    /* this assumes that guaranteed_hit is due to swallowing */
1651. 	    wakeup(mon);
1652. 	    if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
1653. 		if (is_animal(u.ustuck->data)) {
1654. 			minstapetrify(u.ustuck, TRUE);
1655. 			/* Don't leave a cockatrice corpse available in a statue */
1656. 			if (!u.uswallow) {
1657. 				delobj(obj);
1658. 				return 1;
1659. 			}
1660. 	    	}
1661. 	    }
1662. 	    pline("%s into %s %s.",
1663. 		Tobjnam(obj, "vanish"), s_suffix(mon_nam(mon)),
1664. 		is_animal(u.ustuck->data) ? "entrails" : "currents");
1665. 	} else {
1666. 	    tmiss(obj, mon);
1667. 	}
1668. 	return 0;
1669. }
1670. 
1671. STATIC_OVL int
1672. gem_accept(mon, obj)
1673. register struct monst *mon;
1674. register struct obj *obj;
1675. {
1676. 	char buf[BUFSZ];
1677. 	boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
1678. 	boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
1679. 	int ret = 0;
1680. 	static NEARDATA const char nogood[] = " is not interested in your junk.";
1681. 	static NEARDATA const char acceptgift[] = " accepts your gift.";
1682. 	static NEARDATA const char maybeluck[] = " hesitatingly";
1683. 	static NEARDATA const char noluck[] = " graciously";
1684. 	static NEARDATA const char addluck[] = " gratefully";
1685. 
1686. 	Strcpy(buf,Monnam(mon));
1687. 	mon->mpeaceful = 1;
1688. 	mon->mavenge = 0;
1689. 
1690. 	/* object properly identified */
1691. 	if(obj->dknown && objects[obj->otyp].oc_name_known) {
1692. 		if(is_gem) {
1693. 			if(is_buddy) {
1694. 				Strcat(buf,addluck);
1695. 				change_luck(5);
1696. 			} else {
1697. 				Strcat(buf,maybeluck);
1698. 				change_luck(rn2(7)-3);
1699. 			}
1700. 		} else {
1701. 			Strcat(buf,nogood);
1702. 			goto nopick;
1703. 		}
1704. 	/* making guesses */
1705. 	} else if(obj->onamelth || objects[obj->otyp].oc_uname) {
1706. 		if(is_gem) {
1707. 			if(is_buddy) {
1708. 				Strcat(buf,addluck);
1709. 				change_luck(2);
1710. 			} else {
1711. 				Strcat(buf,maybeluck);
1712. 				change_luck(rn2(3)-1);
1713. 			}
1714. 		} else {
1715. 			Strcat(buf,nogood);
1716. 			goto nopick;
1717. 		}
1718. 	/* value completely unknown to @ */
1719. 	} else {
1720. 		if(is_gem) {
1721. 			if(is_buddy) {
1722. 				Strcat(buf,addluck);
1723. 				change_luck(1);
1724. 			} else {
1725. 				Strcat(buf,maybeluck);
1726. 				change_luck(rn2(3)-1);
1727. 			}
1728. 		} else {
1729. 			Strcat(buf,noluck);
1730. 		}
1731. 	}
1732. 	Strcat(buf,acceptgift);
1733. 	if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
1734. 	(void) mpickobj(mon, obj);	/* may merge and free obj */
1735. 	ret = 1;
1736. 
1737. nopick:
1738. 	if(!Blind) pline("%s", buf);
1739. 	if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
1740. 	return(ret);
1741. }
1742. 
1743. /*
1744.  * Comments about the restructuring of the old breaks() routine.
1745.  *
1746.  * There are now three distinct phases to object breaking:
1747.  *     breaktest() - which makes the check/decision about whether the
1748.  *                   object is going to break.
1749.  *     breakmsg()  - which outputs a message about the breakage,
1750.  *                   appropriate for that particular object. Should
1751.  *                   only be called after a positve breaktest().
1752.  *                   on the object and, if it going to be called,
1753.  *                   it must be called before calling breakobj().
1754.  *                   Calling breakmsg() is optional.
1755.  *     breakobj()  - which actually does the breakage and the side-effects
1756.  *                   of breaking that particular object. This should
1757.  *                   only be called after a positive breaktest() on the
1758.  *                   object.
1759.  *
1760.  * Each of the above routines is currently static to this source module.
1761.  * There are two routines callable from outside this source module which
1762.  * perform the routines above in the correct sequence.
1763.  *
1764.  *   hero_breaks() - called when an object is to be broken as a result
1765.  *                   of something that the hero has done. (throwing it,
1766.  *                   kicking it, etc.)
1767.  *   breaks()      - called when an object is to be broken for some
1768.  *                   reason other than the hero doing something to it.
1769.  */
1770. 
1771. /*
1772.  * The hero causes breakage of an object (throwing, dropping it, etc.)
1773.  * Return 0 if the object didn't break, 1 if the object broke.
1774.  */
1775. int
1776. hero_breaks(obj, x, y, from_invent)
1777. struct obj *obj;
1778. xchar x, y;		/* object location (ox, oy may not be right) */
1779. boolean from_invent;	/* thrown or dropped by player; maybe on shop bill */
1780. {
1781. 	boolean in_view = !Blind;
1782. 	if (!breaktest(obj)) return 0;
1783. 	breakmsg(obj, in_view);
1784. 	breakobj(obj, x, y, TRUE, from_invent);
1785. 	return 1;
1786. }
1787. 
1788. /*
1789.  * The object is going to break for a reason other than the hero doing
1790.  * something to it.
1791.  * Return 0 if the object doesn't break, 1 if the object broke.
1792.  */
1793. int
1794. breaks(obj, x, y)
1795. struct obj *obj;
1796. xchar x, y;		/* object location (ox, oy may not be right) */
1797. {
1798. 	boolean in_view = Blind ? FALSE : cansee(x, y);
1799. 
1800. 	if (!breaktest(obj)) return 0;
1801. 	breakmsg(obj, in_view);
1802. 	breakobj(obj, x, y, FALSE, FALSE);
1803. 	return 1;
1804. }
1805. 
1806. /*
1807.  * Unconditionally break an object. Assumes all resistance checks
1808.  * and break messages have been delivered prior to getting here.
1809.  */
1810. STATIC_OVL void
1811. breakobj(obj, x, y, hero_caused, from_invent)
1812. struct obj *obj;
1813. xchar x, y;		/* object location (ox, oy may not be right) */
1814. boolean hero_caused;	/* is this the hero's fault? */
1815. boolean from_invent;
1816. {
1817. 	int am;
1818. 	if (IS_ALTAR(levl[x][y].typ))
1819. 	    am = levl[x][y].altarmask & AM_MASK;
1820. 	else
1821. 	    am = AM_NONE;
1822. 	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1823. 		case MIRROR:
1824. 			if (hero_caused)
1825. 			    change_luck(-2);
1826. 			break;
1827. 		case POT_WATER:		/* really, all potions */
1828. 			if (obj->otyp == POT_OIL && obj->lamplit) {
1829. 			    splatter_burning_oil(x,y);
1830. 			} else if ((obj->otyp == POT_VAMPIRE_BLOOD ||
1831. 				   obj->otyp == POT_BLOOD) &&
1832. 				   am != AM_CHAOTIC &&
1833. 				   am != AM_NONE) {
1834. 			    /* ALI: If blood is spilt on a lawful or
1835. 			     * neutral altar the effect is similar to
1836. 			     * human sacrifice. There's no effect on
1837. 			     * chaotic or unaligned altars since it is
1838. 			     * not sufficient to summon a demon.
1839. 			     */
1840. 			    if (hero_caused) {
1841. 				/* Regardless of your race/alignment etc.
1842. 				 * Lawful and neutral gods really _dont_
1843. 				 * like vampire or (presumed) human blood
1844. 				 * on their altars.
1845. 				 */
1846. 				pline("You'll regret this infamous offense!");
1847. 				exercise(A_WIS, FALSE);
1848. 			    }
1849. 			    /* curse the lawful/neutral altar */
1850. 			    pline_The("altar is stained with blood.");
1851. 			    if (!Is_astralevel(&u.uz))
1852. 				levl[x][y].altarmask = AM_CHAOTIC;
1853. 			    angry_priest();
1854. 			} else if (distu(x,y) <= 2) {
1855. 			    if (!breathless(youmonst.data) || haseyes(youmonst.data)) {
1856. 				if (obj->otyp != POT_WATER) {
1857. 					if (!breathless(youmonst.data))
1858. 			    		     /* [what about "familiar odor" when known?] */
1859. 					    You("smell a peculiar odor...");
1860. 					else {
1861. 					    int numeyes = eyecount(youmonst.data);
1862. 					    Your("%s water%s.",
1863. 						 (numeyes == 1) ? body_part(EYE) :
1864. 							makeplural(body_part(EYE)),
1865. 						 (numeyes == 1) ? "s" : "");
1866. 					}
1867. 				}
1868. 				potionbreathe(obj);
1869. 			    }
1870. 			}
1871. 			/* monster breathing isn't handled... [yet?] */
1872. 			break;
1873. 		case EGG:
1874. 			/* breaking your own eggs is bad luck */
1875. 			if (hero_caused && obj->spe && obj->corpsenm >= LOW_PM)
1876. 			    change_luck((schar) -min(obj->quan, 5L));
1877. 			break;
1878. 	}
1879. 	if (hero_caused) {
1880. 	    if (from_invent) {
1881. 		if (*u.ushops)
1882. 			check_shop_obj(obj, x, y, TRUE);
1883. 	    } else if (!obj->no_charge && costly_spot(x, y)) {
1884. 		/* it is assumed that the obj is a floor-object */
1885. 		char *o_shop = in_rooms(x, y, SHOPBASE);
1886. 		struct monst *shkp = shop_keeper(*o_shop);
1887. 
1888. 		if (shkp) {		/* (implies *o_shop != '\0') */
1889. 		    static NEARDATA long lastmovetime = 0L;
1890. 		    static NEARDATA boolean peaceful_shk = FALSE;
1891. 		    /*  We want to base shk actions on her peacefulness
1892. 			at start of this turn, so that "simultaneous"
1893. 			multiple breakage isn't drastically worse than
1894. 			single breakage.  (ought to be done via ESHK)  */
1895. 		    if (moves != lastmovetime)
1896. 			peaceful_shk = shkp->mpeaceful;
1897. 		    if (stolen_value(obj, x, y, peaceful_shk, FALSE, TRUE) > 0L &&
1898. 			(*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy)) &&
1899. 			moves != lastmovetime) make_angry_shk(shkp, x, y);
1900. 		    lastmovetime = moves;
1901. 		}
1902. 	    }
1903. 	}
1904. 	delobj(obj);
1905. }
1906. 
1907. /*
1908.  * Check to see if obj is going to break, but don't actually break it.
1909.  * Return 0 if the object isn't going to break, 1 if it is.
1910.  */
1911. boolean
1912. breaktest(obj)
1913. struct obj *obj;
1914. {
1915. 	if (obj_resists(obj, 1, 99)) return 0;
1916. 	if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact &&
1917. 		obj->oclass != GEM_CLASS)
1918. 	    return 1;
1919. 	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1920. #ifdef TOURIST
1921. 		case EXPENSIVE_CAMERA:
1922. #endif
1923. 		case POT_WATER:		/* really, all potions */
1924. 		case EGG:
1925. 		case CREAM_PIE:
1926. 		case MELON:
1927. 		case ACID_VENOM:
1928. 		case BLINDING_VENOM:
1929. 			return 1;
1930. 		default:
1931. 			return 0;
1932. 	}
1933. }
1934. 
1935. STATIC_OVL void
1936. breakmsg(obj, in_view)
1937. struct obj *obj;
1938. boolean in_view;
1939. {
1940. 	const char *to_pieces;
1941. 
1942. 	to_pieces = "";
1943. 	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1944. 		default: /* glass or crystal wand */
1945. 		    if (obj->oclass != WAND_CLASS)
1946. 			impossible("breaking odd object?");
1947. 		case CRYSTAL_PLATE_MAIL:
1948. 		case LENSES:
1949. 		case MIRROR:
1950. 		case CRYSTAL_BALL:
1951. #ifdef TOURIST
1952. 		case EXPENSIVE_CAMERA:
1953. #endif
1954. 			to_pieces = " into a thousand pieces";
1955. 			/*FALLTHRU*/
1956. 		case POT_WATER:		/* really, all potions */
1957. 			if (!in_view)
1958. 			    You_hear("%s shatter!", something);
1959. 			else
1960. 			    pline("%s shatter%s%s!", Doname2(obj),
1961. 				(obj->quan==1) ? "s" : "", to_pieces);
1962. 			break;
1963. 		case EGG:
1964. 		case MELON:
1965. 			pline("Splat!");
1966. 			break;
1967. 		case CREAM_PIE:
1968. 			if (in_view) pline("What a mess!");
1969. 			break;
1970. 		case ACID_VENOM:
1971. 		case BLINDING_VENOM:
1972. 			pline("Splash!");
1973. 			break;
1974. 	}
1975. }
1976. 
1977. STATIC_OVL int
1978. throw_gold(obj)
1979. struct obj *obj;
1980. {
1981. 	int range, odx, ody;
1982. #ifndef GOLDOBJ
1983. 	long zorks = obj->quan;
1984. #endif
1985. 	register struct monst *mon;
1986. 
1987. 	if(!u.dx && !u.dy && !u.dz) {
1988. #ifndef GOLDOBJ
1989. 		u.ugold += obj->quan;
1990. 		flags.botl = 1;
1991. 		dealloc_obj(obj);
1992. #endif
1993. 		You("cannot throw gold at yourself.");
1994. 		return(0);
1995. 	}
1996. #ifdef GOLDOBJ
1997.         freeinv(obj);
1998. #endif
1999. 	if(u.uswallow) {
2000. 		pline(is_animal(u.ustuck->data) ?
2001. 			"%s in the %s's entrails." : "%s into %s.",
2002. #ifndef GOLDOBJ
2003. 			"The gold disappears", mon_nam(u.ustuck));
2004. 		u.ustuck->mgold += zorks;
2005. 		dealloc_obj(obj);
2006. #else
2007. 			"The money disappears", mon_nam(u.ustuck));
2008. 		add_to_minv(u.ustuck, obj);
2009. #endif
2010. 		return(1);
2011. 	}
2012. 
2013. 	if(u.dz) {
2014. 		if (u.dz < 0 && !Is_airlevel(&u.uz) &&
2015. 					!Underwater && !Is_waterlevel(&u.uz)) {
2016. 	pline_The("gold hits the %s, then falls back on top of your %s.",
2017. 		    ceiling(u.ux,u.uy), body_part(HEAD));
2018. 		    /* some self damage? */
2019. 		    if(uarmh) pline("Fortunately, you are wearing a helmet!");
2020. 		}
2021. 		bhitpos.x = u.ux;
2022. 		bhitpos.y = u.uy;
2023. 	} else {
2024. 		/* consistent with range for normal objects */
2025. 		range = (int)((ACURRSTR)/2 - obj->owt/40);
2026. 
2027. 		/* see if the gold has a place to move into */
2028. 		odx = u.ux + u.dx;
2029. 		ody = u.uy + u.dy;
2030. 		if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
2031. 			bhitpos.x = u.ux;
2032. 			bhitpos.y = u.uy;
2033. 		} else {
2034. 			mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
2035. 				   (int FDECL((*),(MONST_P,OBJ_P)))0,
2036. 				   (int FDECL((*),(OBJ_P,OBJ_P)))0,
2037. 				   &obj);
2038. 			if (!obj)
2039. 			    return 1;
2040. 			if(mon) {
2041. 			    if (ghitm(mon, obj))	/* was it caught? */
2042. 				return 1;
2043. 			} else {
2044. 			    if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
2045. 				return 1;
2046. 			}
2047. 		}
2048. 	}
2049. 
2050. 	if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
2051. 	if(u.dz > 0)
2052. 		pline_The("gold hits the %s.", surface(bhitpos.x,bhitpos.y));
2053. 	place_object(obj,bhitpos.x,bhitpos.y);
2054. 	if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
2055. 	stackobj(obj);
2056. 	newsym(bhitpos.x,bhitpos.y);
2057. 	return(1);
2058. }
2059. 
2060. /*dothrow.c*/

Around Wikia's network

Random Wiki