Source:NetHack 3.2.0/dothrow.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to dothrow.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/dothrow.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)dothrow.c	3.2	96/03/23	*/
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.    
9.    static int FDECL(gem_accept, (struct monst *, struct obj *));
10.   static int FDECL(throw_gold, (struct obj *));
11.   static void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
12.   
13.   static NEARDATA const char toss_objs[] =
14.   	{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
15.   /* different default choices when wielding a sling (gold must be included) */
16.   static NEARDATA const char bullets[] =
17.   	{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, GEM_CLASS, 0 };
18.   
19.   extern boolean notonhead;	/* for long worms */
20.   
21.   int
22.   dothrow()
23.   {
24.   	register struct obj *obj;
25.   
26.   	if(check_capacity((char *)0)) return(0);
27.   	obj = getobj(uwep && uwep->otyp==SLING ? bullets : toss_objs, "throw");
28.   	/* it is also possible to throw food */
29.   	/* (or jewels, or iron balls... ) */
30.   
31.   	if (!obj) return(0);
32.   	if (!getdir((char *)0)) {       /* ask "in what direction?" */
33.   		if (obj->oclass == GOLD_CLASS) {
34.   		    u.ugold += obj->quan;
35.   		    flags.botl = 1;
36.   		    dealloc_obj(obj);
37.   		}
38.   		return(0);
39.   	}
40.   
41.   
42.   	if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
43.   
44.   	if(!canletgo(obj,"throw"))
45.   		return(0);
46.   	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
47.   	    pline("%s must be wielded before it can be thrown.",
48.   		The(xname(obj)));
49.   		return(0);
50.   	}
51.   	if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) < 125)
52.   	   || (obj->otyp == BOULDER && !throws_rocks(uasmon))) {
53.   		pline("It's too heavy.");
54.   		return(1);
55.   	}
56.   	if(!u.dx && !u.dy && !u.dz) {
57.   		You("cannot throw an object at yourself.");
58.   		return(0);
59.   	}
60.   	u_wipe_engr(2);
61.   
62.   	if(obj == uwep) {
63.   	    if(welded(obj)) {
64.   		weldmsg(obj, FALSE);
65.   		return(1);
66.   	    }
67.   	    if(obj->quan > 1L)
68.   		setworn(splitobj(obj, 1L), W_WEP);
69.   		/* not setuwep; do not change unweapon */
70.   	    else {
71.   		setuwep((struct obj *)0);
72.   		if (uwep) return(1); /* unwielded, died, rewielded */
73.   	    }
74.   	}
75.   	else if(obj->quan > 1L)
76.   		(void) splitobj(obj, 1L);
77.   	freeinv(obj);
78.   	throwit(obj);
79.   	return(1);
80.   }
81.   
82.   /*
83.    * Object hits floor at hero's feet.  Called from drop() and throwit().
84.    */
85.   void
86.   hitfloor(obj)
87.   register struct obj *obj;
88.   {
89.   	if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
90.   		dropy(obj);
91.   		return;
92.   	}
93.   	if (IS_ALTAR(levl[u.ux][u.uy].typ))
94.   		doaltarobj(obj);
95.   	else
96.   		pline("%s hit%s the %s.", Doname2(obj),
97.   		      (obj->quan == 1L) ? "s" : "", surface(u.ux,u.uy));
98.   
99.   	if (breaks(obj, u.ux, u.uy, TRUE)) return;
100.  	if (ship_object(obj, u.ux, u.uy, FALSE)) return;
101.  	dropy(obj);
102.  }
103.  
104.  /*
105.   * The player moves through the air for a few squares as a result of
106.   * throwing or kicking something.  To simplify matters, bumping into monsters
107.   * won't cause damage but will wake them and make them angry.
108.   * Auto-pickup isn't done, since you don't have control over your movements
109.   * at the time.
110.   * dx and dy should be the direction of the hurtle, not of the original
111.   * kick or throw.
112.   */
113.  void
114.  hurtle(dx, dy, range)
115.      int dx, dy, range;
116.  {
117.      register struct monst *mon;
118.      struct obj *obj;
119.      int nx, ny;
120.  
121.      /* The chain is stretched vertically, so you shouldn't be able to move
122.       * very far diagonally.  The premise that you should be able to move one
123.       * spot leads to calculations that allow you to only move one spot away
124.       * from the ball, if you are levitating over the ball, or one spot
125.       * towards the ball, if you are at the end of the chain.  Rather than
126.       * bother with all of that, assume that there is no slack in the chain
127.       * for diagonal movement, give the player a message and return.
128.       */
129.      if(Punished && !carried(uball)) {
130.  	You_feel("a tug from the iron ball.");
131.  	nomul(0);
132.  	return;
133.      } else if (u.utrap) {
134.  	You("are anchored by the %s.",
135.  	    u.utraptype == TT_WEB ? "web" : u.utraptype == TT_LAVA ? "lava" :
136.  		u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) : "trap");
137.  	nomul(0);
138.  	return;
139.      }
140.  
141.      if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
142.  
143.      nomul(-range);
144.      You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
145.      while(range--) {
146.  	nx = u.ux + dx;
147.  	ny = u.uy + dy;
148.  
149.  	if(!isok(nx,ny)) break;
150.  	if(IS_ROCK(levl[nx][ny].typ) || closed_door(nx,ny) ||
151.  	   (IS_DOOR(levl[nx][ny].typ) && (levl[nx][ny].doormask & D_ISOPEN))) {
152.  	    pline("Ouch!");
153.  	    losehp(rnd(2+range), IS_ROCK(levl[nx][ny].typ) ?
154.  		   "bumping into a wall" : "bumping into a door", KILLED_BY);
155.  	    break;
156.  	}
157.  
158.  	if ((obj = sobj_at(BOULDER,nx,ny)) != 0) {
159.  	    You("bump into a %s.  Ouch!", xname(obj));
160.  	    losehp(rnd(2+range), "bumping into a boulder", KILLED_BY);
161.  	    break;
162.  	}
163.  
164.  	u.ux = nx;
165.  	u.uy = ny;
166.  	newsym(u.ux - dx, u.uy - dy);
167.  	if ((mon = m_at(u.ux, u.uy)) != 0) {
168.  	    You("bump into %s.", a_monnam(mon));
169.  	    wakeup(mon);
170.  	    if(Is_airlevel(&u.uz))
171.  		mnexto(mon);
172.  	    else {
173.  		/* sorry, not ricochets */
174.  		u.ux -= dx;
175.  		u.uy -= dy;
176.  	    }
177.  	    range = 0;
178.  	}
179.  
180.  	vision_recalc(1);		/* update for new position */
181.  
182.  	if(range) {
183.  	    flush_screen(1);
184.  	    delay_output();
185.  	}
186.      }
187.  }
188.  
189.  static void
190.  check_shop_obj(obj, x, y, broken)
191.  register struct obj *obj;
192.  register xchar x, y;
193.  register boolean broken;
194.  {
195.  	struct monst *shkp = shop_keeper(*u.ushops);
196.  
197.  	if(!shkp) return;
198.  
199.  	if(broken) {
200.  		if (obj->unpaid) {
201.  		    (void)stolen_value(obj, u.ux, u.uy,
202.  				       (boolean)shkp->mpeaceful, FALSE);
203.  		    subfrombill(obj, shkp);
204.  		}
205.  		obj->no_charge = 1;
206.  		return;
207.  	}
208.  
209.  	if (!costly_spot(x, y) || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
210.  		/* thrown out of a shop or into a different shop */
211.  		if (obj->unpaid) {
212.  		    (void)stolen_value(obj, u.ux, u.uy,
213.  				       (boolean)shkp->mpeaceful, FALSE);
214.  		    subfrombill(obj, shkp);
215.  		}
216.  	} else {
217.  		if (costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
218.  		    if(obj->unpaid) subfrombill(obj, shkp);
219.  		    else if(!(x == shkp->mx && y == shkp->my))
220.  			    sellobj(obj, x, y);
221.  		}
222.  	}
223.  }
224.  
225.  
226.  void
227.  throwit(obj)
228.  register struct obj *obj;
229.  {
230.  	register struct monst *mon;
231.  	register int range, urange;
232.  	boolean impaired = (Confusion || Stunned || Blind ||
233.  			   Hallucination || Fumbling);
234.  	int do_death = 0;
235.  
236.  	if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
237.  	    boolean slipok = TRUE;
238.  	    if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
239.  		&& uwep && (objects[obj->otyp].w_propellor > 0) &&
240.  		(objects[obj->otyp].w_propellor ==
241.  					     -objects[uwep->otyp].w_propellor))
242.  		pline("%s misfires!", The(xname(obj)));
243.  	    else {
244.  		/* only slip if it's greased or meant to be thrown */
245.  		if(obj->greased ||
246.  		    objects[obj->otyp].oc_wepcat == WEP_MISSILE ||
247.  		    objects[obj->otyp].oc_wepcat == WEP_SPEAR ||
248.  		    (objects[obj->otyp].oc_wepcat == WEP_BLADE &&
249.  		     (objects[obj->otyp].oc_dir & PIERCE)) ||
250.  		    obj->otyp == WAR_HAMMER || obj->otyp == AKLYS)
251.  		    pline("%s slips as you throw it!", The(xname(obj)));
252.  		else slipok = FALSE;
253.  	    }
254.  	    if (slipok) {
255.  		u.dx = rn2(3)-1;
256.  		u.dy = rn2(3)-1;
257.  		if (!u.dx && !u.dy) u.dz = 1;
258.  		impaired = TRUE;
259.  	    }
260.  	}
261.  
262.  	if(u.uswallow) {
263.  		mon = u.ustuck;
264.  		bhitpos.x = mon->mx;
265.  		bhitpos.y = mon->my;
266.  	} else if(u.dz) {
267.  	  if (u.dz < 0 && Role_is('V') &&
268.  		obj->oartifact == ART_MJOLLNIR && !impaired) {
269.  	      pline("%s hits the %s and returns to your hand!",
270.  		    The(xname(obj)), ceiling(u.ux,u.uy));
271.  	      obj = addinv(obj);
272.  	      (void) encumber_msg();
273.  	      setuwep(obj);
274.  	      return;
275.  	  }
276.  	  if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
277.  	      pline("%s hits the %s, then falls back on top of your %s.",
278.  		  Doname2(obj),		/* note: obj->quan == 1 */
279.  		  ceiling(u.ux,u.uy),
280.  		  body_part(HEAD));
281.  	      if(obj->oclass == POTION_CLASS)
282.  		  potionhit(&youmonst, obj);
283.  	      else {
284.  		  int dmg = rnd((int)(obj->owt));
285.  		
286.  		  if (uarmh) {
287.  		      if(is_metallic(uarmh)) {
288.  			  pline("Fortunately, you are wearing a hard helmet.");
289.  			  dmg = 1;
290.  		      } else if (flags.verbose)
291.  			  Your("%s does not protect you.", xname(uarmh));
292.  		  } else if (obj->otyp == CORPSE &&
293.  				  obj->corpsenm == PM_COCKATRICE) {
294.  		      if (!resists_ston(&youmonst) &&
295.  			  !(poly_when_stoned(uasmon) &&
296.  					  polymon(PM_STONE_GOLEM))) {
297.  			  killer = doname(obj);
298.  			  You("turn to stone.");
299.  			  do_death = STONING;
300.  		      }
301.  		  }
302.  
303.  		  hitfloor(obj);
304.  		  if (do_death == STONING)
305.  		      done(STONING);
306.  		  else
307.  		      losehp(dmg, "falling object", KILLED_BY_AN);
308.  	      }
309.  	  } else hitfloor(obj);
310.  	  return;
311.  
312.  	} else if(obj->otyp == BOOMERANG && !Underwater) {
313.  		if(Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, 1);
314.  		mon = boomhit(u.dx, u.dy);
315.  		if(mon == &youmonst) {		/* the thing was caught */
316.  			exercise(A_DEX, TRUE);
317.  			(void) addinv(obj);
318.  			(void) encumber_msg();
319.  			return;
320.  		}
321.  	} else {
322.  		urange = (int)(ACURRSTR)/2;
323.  		range = urange - (int)(obj->owt/40);
324.  		if (obj == uball) {
325.  			if (u.ustuck) range = 1;
326.  			else if (range >= 5) range = 5;
327.  		}
328.  		if (range < 1) range = 1;
329.  
330.  		if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
331.  		    && uwep && objects[obj->otyp].w_propellor) {
332.  		    if (objects[obj->otyp].w_propellor ==
333.  			                     -objects[uwep->otyp].w_propellor)
334.  			range++;
335.  		    else
336.  			range /= 2;
337.  		}
338.  
339.  		if (Is_airlevel(&u.uz) || Levitation) {
340.  		    /* action, reaction... */
341.  		    urange -= range;
342.  		    if(urange < 1) urange = 1;
343.  		    range -= urange;
344.  		    if(range < 1) range = 1;
345.  		}
346.  
347.  		if (obj->otyp == BOULDER) range = 20;
348.  		if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
349.  		    range = 1;
350.  
351.  		if (Underwater) range = 1;
352.  
353.  		mon = bhit(u.dx,u.dy,range,THROWN_WEAPON,
354.  			   (int (*)()) 0,(int (*)()) 0,obj);
355.  
356.  		/* have to do this after bhit() so u.ux & u.uy are correct */
357.  		if(Is_airlevel(&u.uz) || Levitation)
358.  		    hurtle(-u.dx, -u.dy, urange);
359.  	}
360.  	if(mon) {
361.  		if (mon->isshk) {
362.  		    if (obj->where == OBJ_MINVENT && obj->ocarry == mon)
363.  			return;		/* alert shk caught it */
364.  		    if (!inside_shop(u.ux, u.uy) ||
365.  		     !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)) {
366.  			wakeup(mon);
367.  			hot_pursuit(mon);
368.  		    }
369.  		} else if (!mon->meating || obj->oclass != FOOD_CLASS)
370.  		    wakeup(mon);	/* awake monster if sleeping */
371.  
372.  		(void) snuff_candle(obj);
373.  		notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
374.  		if (thitmonst(mon, obj)) return;
375.  	}
376.  
377.  	if (u.uswallow) {
378.  		/* ball is not picked up by monster */
379.  		if (obj != uball) mpickobj(u.ustuck,obj);
380.  	} else {
381.  		/* the code following might become part of dropy() */
382.  		int obj_glyph = obj_to_glyph(obj);
383.  
384.  		if (obj->oartifact == ART_MJOLLNIR &&
385.  			Role_is('V') && rn2(100)) {
386.  		    /* we must be wearing Gauntlets of Power to get here */
387.  
388.  		    /* might already be our location (bounced off a wall) */
389.  		    if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
390.  			int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
391.  
392.  			tmp_at(DISP_FLASH, obj_glyph);
393.  			while(x != u.ux || y != u.uy) {
394.  			    tmp_at(x, y);
395.  			    delay_output();
396.  			    x -= u.dx; y -= u.dy;
397.  			}
398.  			tmp_at(DISP_END, 0);
399.  		    }
400.  
401.  		    if (!impaired && rn2(100)) {
402.  			pline("%s returns to your hand!", The(xname(obj)));
403.  			obj = addinv(obj);
404.  			(void) encumber_msg();
405.  			setuwep(obj);
406.  			if(cansee(bhitpos.x, bhitpos.y))
407.  			    newsym(bhitpos.x,bhitpos.y);
408.  		    } else {
409.  			int dmg = rnd(4);
410.  			if (Blind)
411.  			    pline("%s hits your %s!",
412.  				  The(xname(obj)), body_part(ARM));
413.  			else
414.  			    pline("%s flies back toward you, hitting your %s!",
415.  				  The(xname(obj)), body_part(ARM));
416.  			(void) artifact_hit((struct monst *) 0, &youmonst,
417.  					    obj, &dmg, 0);
418.  			losehp(dmg, xname(obj), KILLED_BY);
419.  			if(ship_object(obj, u.ux, u.uy, FALSE))
420.  		            return;
421.  			dropy(obj);
422.  		    }
423.  		    return;
424.  		}
425.  
426.  		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
427.  			breaks(obj, bhitpos.x, bhitpos.y, TRUE)) {
428.  		    tmp_at(DISP_FLASH, obj_glyph);
429.  		    tmp_at(bhitpos.x, bhitpos.y);
430.  		    delay_output();
431.  		    tmp_at(DISP_END, 0);
432.  		    return;
433.  		}
434.  		if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return;
435.  		if(obj->otyp == CRYSKNIFE)
436.  		    obj->otyp = WORM_TOOTH;
437.  		if (mon && mon->isshk && obj->otyp == PICK_AXE) {
438.  		    if (cansee(bhitpos.x, bhitpos.y))
439.  			pline("%s snatches up %s.",
440.  			      Monnam(mon), the(xname(obj)));
441.  		    mpickobj(mon, obj);
442.  		    if(*u.ushops)
443.  			check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
444.  		    return;
445.  		}
446.  		(void) snuff_candle(obj);
447.  		if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
448.  		    return;
449.  		place_object(obj, bhitpos.x, bhitpos.y);
450.  		if(*u.ushops && obj != uball)
451.  		    check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
452.  
453.  		stackobj(obj);
454.  		if (obj == uball)
455.  		    drop_ball(bhitpos.x, bhitpos.y);
456.  		if (cansee(bhitpos.x, bhitpos.y))
457.  		    newsym(bhitpos.x,bhitpos.y);
458.  		if (obj_sheds_light(obj))
459.  		    vision_full_recalc = 1;
460.  	}
461.  }
462.  
463.  /* an object may hit a monster; various factors adjust the chance of hitting */
464.  int
465.  omon_adj(mon, obj, mon_notices)
466.  struct monst *mon;
467.  struct obj *obj;
468.  boolean mon_notices;
469.  {
470.  	int tmp = 0;
471.  
472.  	/* size of target affects the chance of hitting */
473.  	tmp += (mon->data->msize - MZ_MEDIUM);		/* -2..+5 */
474.  	/* sleeping target is more likely to be hit */
475.  	if (mon->msleep) {
476.  	    tmp += 2;
477.  	    if (mon_notices) mon->msleep = 0;
478.  	}
479.  	/* ditto for immobilized target */
480.  	if (!mon->mcanmove || !mon->data->mmove) {
481.  	    tmp += 4;
482.  	    if (mon_notices && mon->data->mmove && !rn2(10)) {
483.  		mon->mcanmove = 1;
484.  		mon->mfrozen = 0;
485.  	    }
486.  	}
487.  	/* some objects are more likely to hit than others */
488.  	switch (obj->otyp) {
489.  	case HEAVY_IRON_BALL:
490.  	    if (obj != uball) tmp += 2;
491.  	    break;
492.  	case BOULDER:
493.  	    tmp += 6;
494.  	    break;
495.  	default:
496.  	    if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
497.  		    obj->oclass == GEM_CLASS)
498.  		tmp += hitval(obj, mon);
499.  	    break;
500.  	}
501.  	return tmp;
502.  }
503.  
504.  /*
505.   * Object thrown by player arrives at monster's location.
506.   * Return 1 if obj has disappeared or otherwise been taken care of,
507.   * 0 if caller must take care of it.
508.   */
509.  int
510.  thitmonst(mon, obj)
511.  register struct monst *mon;
512.  register struct obj   *obj;
513.  {
514.  	register int	tmp; /* Base chance to hit */
515.  	register int	disttmp; /* distance modifier */
516.  	int otyp = obj->otyp;
517.  	boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
518.  	
519.  	/* Differences from melee weapons:
520.  	 *
521.  	 * Dex still gives a bonus, but strength does not.
522.  	 * Polymorphed players lacking attacks may still throw.
523.  	 * There's a base -1 to hit.
524.  	 * No bonuses for fleeing or stunned targets (they don't dodge
525.  	 *    melee blows as readily, but dodging arrows is hard anyway).
526.  	 * Not affected by traps, etc.
527.  	 * Certain items which don't in themselves do damage ignore tmp.
528.  	 * Distance and monster size affect chance to hit.
529.  	 */
530.  	tmp = -1 + Luck + find_mac(mon) + maybe_polyd(uasmon->mlevel, u.ulevel);
531.  	if (ACURR(A_DEX) < 4) tmp -= 3;
532.  	else if (ACURR(A_DEX) < 6) tmp -= 2;
533.  	else if (ACURR(A_DEX) < 8) tmp -= 1;
534.  	else if (ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
535.  
536.  	/* modify to-hit depending on distance; but keep it sane */
537.  	disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
538.  	if(disttmp < -4) disttmp = -4;
539.  	tmp += disttmp;
540.  
541.  	/* gloves are a hinderance to proper use of bows */
542.  	if (uarmg && uwep && -objects[uwep->otyp].w_propellor == WP_BOW) {
543.  	    switch (uarmg->otyp) {
544.  	    case GAUNTLETS_OF_POWER:    /* metal */
545.  		tmp -= 2;
546.  		break;
547.  	    case GAUNTLETS_OF_FUMBLING:
548.  		tmp -= 3;
549.  		break;
550.  	    case LEATHER_GLOVES:
551.  	    case GAUNTLETS_OF_DEXTERITY:
552.  		break;
553.  	    default:
554.  		impossible("Unknown type of gloves (%d)", uarmg->otyp);
555.  		break;
556.  	    }
557.  	}
558.  
559.  	tmp += omon_adj(mon, obj, TRUE);
560.  	if (is_orc(mon->data) && maybe_polyd(is_elf(uasmon), Role_is('E')))
561.  	    tmp++;
562.  	if (guaranteed_hit) {
563.  	    tmp += 1000; /* Guaranteed hit */
564.  	}
565.  
566.  	if (obj->oclass == GEM_CLASS && mon->data->mlet == S_UNICORN) {
567.  	    if (mon->mtame) {
568.  		pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
569.  		return 0;
570.  	    } else {
571.  		pline("%s catches %s.", Monnam(mon), the(xname(obj)));
572.  		return gem_accept(mon, obj);
573.  	    }
574.  	}
575.  
576.  	/* don't make game unwinnable if naive player throws artifact
577.  	   at leader.... */
578.  	if (mon->data->msound == MS_LEADER && is_quest_artifact(obj)) {
579.  	    if (mon->mcanmove)
580.  		pline("%s ignores %s.", Monnam(mon), the(xname(obj)));
581.  	    return(0);
582.  	}
583.  
584.  	if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
585.  		obj->oclass == GEM_CLASS) {
586.  	    if (objects[otyp].oc_wepcat == WEP_AMMO) {
587.  		if (!uwep || objects[otyp].w_propellor !=
588.  				-objects[uwep->otyp].w_propellor) {
589.  		    tmp -= 4;
590.  		} else {
591.  		    tmp += uwep->spe - uwep->oeroded;
592.  		    /*
593.  		     * Elves and Samurais are highly trained w/bows,
594.  		     * especially their own special types of bow.
595.  		     * Polymorphing won't make you a bow expert.
596.  		     */
597.  		    if ((Role_is('E') || Role_is('S')) &&
598.  				-objects[uwep->otyp].w_propellor == WP_BOW) {
599.  			tmp++;
600.  			if (Role_is('E') && uwep->otyp == ELVEN_BOW) tmp++;
601.  			else if (Role_is('S') && uwep->otyp == YUMI) tmp++;
602.  		    }
603.  		}
604.  	    } else if (otyp == BOOMERANG) {
605.  		tmp += 4;
606.  	    }
607.  
608.  	    if (tmp >= rnd(20)) {
609.  		if (hmon(mon,obj,1)) {	/* mon still alive */
610.  		    cutworm(mon, bhitpos.x, bhitpos.y, obj);
611.  		}
612.  		exercise(A_DEX, TRUE);
613.  		/* projectiles other than magic stones
614.  		   sometimes disappear when thrown */
615.  		if ((otyp < BOOMERANG ||
616.  			(obj->oclass == GEM_CLASS && !objects[otyp].oc_magic))
617.  		    && rn2(3)) {
618.  		    if (*u.ushops)
619.  			check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
620.  		    obfree(obj, (struct obj *)0);
621.  		    return 1;
622.  		}
623.  	    } else {
624.  		miss(xname(obj), mon);
625.  	    }
626.  
627.  	} else if (otyp == HEAVY_IRON_BALL) {
628.  	    exercise(A_STR, TRUE);
629.  	    if (tmp >= rnd(20)) {
630.  		int was_swallowed = guaranteed_hit;
631.  
632.  		exercise(A_DEX, TRUE);
633.  		if (!hmon(mon,obj,1)) {		/* mon killed */
634.  		    if (was_swallowed && !u.uswallow && obj == uball)
635.  			return 1;	/* already did placebc() */
636.  		}
637.  	    } else {
638.  		miss(xname(obj), mon);
639.  	    }
640.  
641.  	} else if (otyp == BOULDER) {
642.  	    exercise(A_STR, TRUE);
643.  	    if (tmp >= rnd(20)) {
644.  		exercise(A_DEX, TRUE);
645.  		(void) hmon(mon,obj,1);
646.  	    } else {
647.  		miss(xname(obj), mon);
648.  	    }
649.  
650.  	} else if ((otyp == EGG || otyp == CREAM_PIE
651.  		   || otyp == BLINDING_VENOM || otyp == ACID_VENOM)
652.  		   && ACURR(A_DEX) >= rnd(15)) {
653.  	    (void) hmon(mon, obj, 1);
654.  	    return 1;	/* hmon used it up */
655.  
656.  	} else if (obj->oclass == POTION_CLASS && ((ACURR(A_DEX) >= rnd(15))
657.  	    || guaranteed_hit)) {
658.  	    potionhit(mon, obj);
659.  	    return 1;
660.  
661.  	} else if (obj->oclass == FOOD_CLASS &&
662.  		   is_domestic(mon->data) && tamedog(mon,obj)) {
663.  	    return 1;		/* food is gone */
664.  	} else {
665.  	    if (guaranteed_hit)
666.  		/* this assumes that guaranteed_hit is due to swallowing */
667.  	    	pline("%s vanishes into %s %s.",
668.  	    		The(xname(obj)), s_suffix(mon_nam(mon)),
669.  			is_animal(u.ustuck->data) ? "entrails" : "currents");
670.  	    else
671.  		    pline("%s misses %s.", The(xname(obj)), mon_nam(mon));
672.  	}
673.  
674.  	return 0;
675.  }
676.  
677.  static int
678.  gem_accept(mon, obj)
679.  register struct monst *mon;
680.  register struct obj *obj;
681.  {
682.  	char buf[BUFSZ];
683.  	boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
684.  	boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
685.  	int ret = 0;
686.  	static NEARDATA const char nogood[] = " is not interested in your junk.";
687.  	static NEARDATA const char acceptgift[] = " accepts your gift.";
688.  	static NEARDATA const char maybeluck[] = " hesitatingly";
689.  	static NEARDATA const char noluck[] = " graciously";
690.  	static NEARDATA const char addluck[] = " gratefully";
691.  
692.  	Strcpy(buf,Monnam(mon));
693.  	mon->mpeaceful = 1;
694.  	/* undo throwit() -> wakeup() -> setmangry() -> adjalign(-1) */
695.  	if (is_gem && is_buddy) adjalign(1);
696.  
697.  	/* object properly identified */
698.  	if(obj->dknown && objects[obj->otyp].oc_name_known) {
699.  		if(is_gem) {
700.  			if(is_buddy) {
701.  				Strcat(buf,addluck);
702.  				change_luck(5);
703.  			} else {
704.  				Strcat(buf,maybeluck);
705.  				change_luck(rn2(7)-3);
706.  			}
707.  		} else {
708.  			Strcat(buf,nogood);
709.  			goto nopick;
710.  		}
711.  	/* making guesses */
712.  	} else if(obj->onamelth || objects[obj->otyp].oc_uname) {
713.  		if(is_gem) {
714.  			if(is_buddy) {
715.  				Strcat(buf,addluck);
716.  				change_luck(2);
717.  			} else {
718.  				Strcat(buf,maybeluck);
719.  				change_luck(rn2(3)-1);
720.  			}
721.  		} else {
722.  			Strcat(buf,nogood);
723.  			goto nopick;
724.  		}
725.  	/* value completely unknown to @ */
726.  	} else {
727.  		if(is_gem) {
728.  			if(is_buddy) {
729.  				Strcat(buf,addluck);
730.  				change_luck(1);
731.  			} else {
732.  				Strcat(buf,maybeluck);
733.  				change_luck(rn2(3)-1);
734.  			}
735.  		} else {
736.  			Strcat(buf,noluck);
737.  		}
738.  	}
739.  	Strcat(buf,acceptgift);
740.  	mpickobj(mon, obj);
741.  	if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
742.  	ret = 1;
743.  
744.  nopick:
745.  	if(!Blind) pline(buf);
746.  	rloc(mon);
747.  	return(ret);
748.  }
749.  
750.  /*
751.   * Check to see if obj breaks.  This routine assumes the cause is the hero,
752.   * and that the break is in sight of the hero.
753.   *
754.   * This assumption is probably not true from the call in scatter().
755.   * This routine needs to be generalized.
756.   *
757.   * Return 0 if the object doesn't break, 1 if the object broke.
758.   */
759.  int
760.  breaks(obj, x, y, from_invent)
761.  struct obj *obj;
762.  int x, y;			/* object location (ox, oy may not be right) */
763.  boolean from_invent;	/* thrown or dropped by player; maybe on shop bill */
764.  {
765.  	const char *to_pieces;
766.  
767.  	if (obj_resists(obj, 1, 100)) return 0;
768.  
769.  	to_pieces = "";
770.  	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
771.  		case MIRROR:
772.  			if (!flags.mon_moving)
773.  			    change_luck(-2);
774.  			/*FALLTHRU*/
775.  		case CRYSTAL_BALL:
776.  #ifdef TOURIST
777.  		case EXPENSIVE_CAMERA:
778.  #endif
779.  			to_pieces = " into a thousand pieces";
780.  			/*FALLTHRU*/
781.  		case POT_WATER:		/* really, all potions */
782.  			if (Blind)
783.  			    You_hear("%s shatter!", something);
784.  			else
785.  			    pline("%s shatters%s!", Doname2(obj), to_pieces);
786.  
787.  			if (obj->oclass == POTION_CLASS) {
788.  			    if (obj->otyp == POT_OIL && obj->lamplit)
789.  				splatter_burning_oil(x,y);
790.  			    else if (distu(x,y) <= 2) {
791.  				You("smell a peculiar odor...");
792.  				potionbreathe(obj);
793.  			    }
794.  			    /* monster breathing isn't handled... [yet?] */
795.  			}
796.  			break;
797.  		case EGG:
798.  			if (!flags.mon_moving) {
799.  			    if (obj->spe && obj->corpsenm >= LOW_PM)
800.  				if (obj->quan < 5)
801.  				    change_luck((schar) -(obj->quan));
802.  				else
803.  				    change_luck(-5);
804.  			}
805.  			pline("Splat!");
806.  			break;
807.  		case CREAM_PIE:
808.  			pline("What a mess!");
809.  			break;
810.  		case ACID_VENOM:
811.  		case BLINDING_VENOM:
812.  			pline("Splash!");
813.  			break;
814.  		default:
815.  			return 0;
816.  	}
817.  
818.  	if (from_invent) {
819.  		if (*u.ushops)
820.  		    check_shop_obj(obj, x, y, TRUE);
821.  	} else if (!flags.mon_moving && !obj->no_charge && costly_spot(x, y)) {
822.  		/* it is assumed that the obj is a floor-object */
823.  		char *o_shop = in_rooms(x, y, SHOPBASE);
824.  		struct monst *shkp = shop_keeper(*o_shop);
825.  
826.  		if (shkp) {		/* (implies *o_shop != '\0') */
827.  		    static NEARDATA long lastmovetime = 0L;
828.  		    static NEARDATA boolean peaceful_shk = FALSE;
829.  		    /* We want to base shk actions on her peacefulness
830.  		       at start of this turn, so that "simultaneous"
831.  		       multiple breakage isn't drastically worse than
832.  		       single breakage.  (ought to be done via ESHK)  */
833.  		    if (moves != lastmovetime) peaceful_shk = shkp->mpeaceful;
834.  		    if (stolen_value(obj, x, y, peaceful_shk, FALSE) > 0L &&
835.  			(*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy)) &&
836.  			moves != lastmovetime) make_angry_shk(shkp, x, y);
837.  		    lastmovetime = moves;
838.  		}
839.  	}
840.  
841.  	delobj(obj);
842.  	return 1;
843.  }
844.  
845.  /*
846.   *  Note that the gold object is *not* attached to the fobj chain.
847.   */
848.  static int
849.  throw_gold(obj)
850.  struct obj *obj;
851.  {
852.  	int range, odx, ody;
853.  	long zorks = obj->quan;
854.  	register struct monst *mon;
855.  
856.  	if(u.uswallow) {
857.  		pline(is_animal(u.ustuck->data) ?
858.  			"%s in the %s's entrails." : "%s into %s.",
859.  			"The gold disappears", mon_nam(u.ustuck));
860.  		u.ustuck->mgold += zorks;
861.  		dealloc_obj(obj);
862.  		return(1);
863.  	}
864.  
865.  	if(u.dz) {
866.  		if (u.dz < 0 && !Is_airlevel(&u.uz) &&
867.  					!Underwater && !Is_waterlevel(&u.uz)) {
868.  	pline_The("gold hits the %s, then falls back on top of your %s.",
869.  		    ceiling(u.ux,u.uy), body_part(HEAD));
870.  		    /* some self damage? */
871.  		    if(uarmh) pline("Fortunately, you are wearing a helmet!");
872.  		}
873.  		bhitpos.x = u.ux;
874.  		bhitpos.y = u.uy;
875.  	} else {
876.  		/* consistent with range for normal objects */
877.  		range = (int)((ACURRSTR)/2 - obj->owt/40);
878.  
879.  		/* see if the gold has a place to move into */
880.  		odx = u.ux + u.dx;
881.  		ody = u.uy + u.dy;
882.  		if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
883.  			bhitpos.x = u.ux;
884.  			bhitpos.y = u.uy;
885.  		} else {
886.  			mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
887.  				       (int (*)()) 0, (int (*)()) 0, obj);
888.  			if(mon) {
889.  			    if (ghitm(mon, obj))	/* was it caught? */
890.  				return 1;
891.  			} else {
892.  			    if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
893.  				return 1;
894.  			}
895.  		}
896.  	}
897.  
898.  	if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
899.  	if(u.dz > 0)
900.  		pline_The("gold hits the %s.", surface(bhitpos.x,bhitpos.y));
901.  	place_object(obj,bhitpos.x,bhitpos.y);
902.  	if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
903.  	stackobj(obj);
904.  	newsym(bhitpos.x,bhitpos.y);
905.  	return(1);
906.  }
907.  
908.  /*dothrow.c*/