Fandom

Wikihack

Source:NetHack 3.3.0/dothrow.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to dothrow.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.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.
1.    /*	SCCS Id: @(#)dothrow.c	3.3	1999/12/02	*/
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_DCL int FDECL(throw_obj, (struct obj *,int));
10.   STATIC_DCL void NDECL(autoquiver);
11.   STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *));
12.   STATIC_DCL int FDECL(throw_gold, (struct obj *));
13.   STATIC_DCL void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
14.   STATIC_DCL void FDECL(breakobj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P,BOOLEAN_P));
15.   STATIC_DCL void FDECL(breakmsg, (struct obj *,BOOLEAN_P));
16.   STATIC_DCL boolean FDECL(toss_up,(struct obj *, BOOLEAN_P));
17.   STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
18.   STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj *obj));
19.   
20.   
21.   static NEARDATA const char toss_objs[] =
22.   	{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
23.   /* different default choices when wielding a sling (gold must be included) */
24.   static NEARDATA const char bullets[] =
25.   	{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, GEM_CLASS, 0 };
26.   
27.   extern boolean notonhead;	/* for long worms */
28.   
29.   
30.   /* Throw the selected object, asking for direction */
31.   STATIC_OVL int
32.   throw_obj(obj, shotlimit)
33.   struct obj *obj;
34.   int shotlimit;
35.   {
36.   	struct obj *otmp;
37.   	int multishot = 1;
38.   	schar skill;
39.   
40.   	/* ask "in what direction?" */
41.   	if (!getdir((char *)0)) {
42.   		if (obj->oclass == GOLD_CLASS) {
43.   		    u.ugold += obj->quan;
44.   		    flags.botl = 1;
45.   		    dealloc_obj(obj);
46.   		}
47.   		return(0);
48.   	}
49.   
50.   	if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
51.   
52.   	if(!canletgo(obj,"throw"))
53.   		return(0);
54.   	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
55.   	    pline("%s must be wielded before it can be thrown.",
56.   		The(xname(obj)));
57.   		return(0);
58.   	}
59.   	if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) < STR19(25))
60.   	   || (obj->otyp == BOULDER && !throws_rocks(youmonst.data))) {
61.   		pline("It's too heavy.");
62.   		return(1);
63.   	}
64.   	if(!u.dx && !u.dy && !u.dz) {
65.   		You("cannot throw an object at yourself.");
66.   		return(0);
67.   	}
68.   	u_wipe_engr(2);
69.   
70.   	/* Multishot calculations
71.   	 * Avoid sling ammunition, to avoid throwing all of the hero's
72.   	 * gemstones at unicorns, all luckstones, etc.
73.   	 */
74.   	skill = objects[obj->otyp].oc_skill;
75.   	if (((ammo_and_launcher(obj, uwep) && skill != -P_SLING) ||
76.   			skill == P_DAGGER || skill == P_DART ||
77.   			skill == P_SHURIKEN) && !Confusion) {
78.   	    /* Bonus if the player is proficient in this weapon... */
79.   	    switch (P_SKILL(weapon_type(obj))) {
80.   	    default:	break; /* No bonus */
81.   	    case P_SKILLED:	multishot++; break;
82.   	    case P_EXPERT:	multishot += 2; break;
83.   	    }
84.   	    /* ...or is using a special weapon for their role... */
85.   	    switch (Role_switch) {
86.   	    case PM_RANGER:
87.   		multishot++;
88.   		break;
89.   	    case PM_ROGUE:
90.   		if (skill == P_DAGGER) multishot++;
91.   		break;
92.   	    case PM_SAMURAI:
93.   		if (obj->otyp == YA && uwep && uwep->otyp == YUMI) multishot++;
94.   		break;
95.   	    default:
96.   		break;	/* No bonus */
97.   	    }
98.   	    /* ...or using their race's special bow */
99.   	    switch (Race_switch) {
100.  	    case PM_ELF:
101.  		if (obj->otyp == ELVEN_ARROW && uwep &&
102.  				uwep->otyp == ELVEN_BOW) multishot++;
103.  		break;
104.  	    default:
105.  		break;	/* No bonus */
106.  	    }
107.  	}
108.  
109.  	if (obj->quan < multishot) multishot = (int)obj->quan;
110.  	multishot = rnd(multishot);
111.  	if (shotlimit > 0 && multishot > shotlimit) multishot = shotlimit;
112.  
113.  	while (obj && multishot-- > 0) {
114.  		/* Split this object off from its slot */
115.  		otmp = (struct obj *)0;
116.  		if (obj == uquiver) {
117.  			if(obj->quan > 1L)
118.  				setuqwep(otmp = splitobj(obj, 1L));
119.  			else {
120.  				setuqwep((struct obj *)0);
121.  				if (uquiver) return(1);
122.  			}
123.  		} else if (obj == uswapwep) {
124.  			if(obj->quan > 1L)
125.  				setuswapwep(otmp = splitobj(obj, 1L));
126.  			else {
127.  				setuswapwep((struct obj *)0);
128.  				if (uswapwep) return(1);
129.  			}
130.  		} else if (obj == uwep) {
131.  	    if(welded(obj)) {
132.  		weldmsg(obj);
133.  		return(1);
134.  	    }
135.  	    if(obj->quan > 1L)
136.  				setworn(otmp = splitobj(obj, 1L), W_WEP);
137.  		/* not setuwep; do not change unweapon */
138.  	    else {
139.  		setuwep((struct obj *)0);
140.  		if (uwep) return(1); /* unwielded, died, rewielded */
141.  	    }
142.  		} else if(obj->quan > 1L)
143.  			otmp = splitobj(obj, 1L);
144.  	freeinv(obj);
145.  	throwit(obj);
146.  		obj = otmp;
147.  	}	/* while (multishot) */
148.  	return(1);
149.  }
150.  
151.  
152.  int
153.  dothrow()
154.  {
155.  	register struct obj *obj;
156.  	int shotlimit;
157.  
158.  	/*
159.  	 * Since some characters shoot multiple missiles at one time,
160.  	 * allow user to specify a count prefix for 'f' or 't' to limit
161.  	 * number of items thrown (to avoid possibly hitting something
162.  	 * behind target after killing it, or perhaps to conserve ammo).
163.  	 *
164.  	 * Prior to 3.3.0, command ``3t meant ``t(shoot) t(shoot) t(shoot)
165.  	 * and took 3 turns.  Now it means ``t(shoot at most 3 missiles).
166.  	 */
167.  	/* kludge to work around parse()'s pre-decrement of `multi' */
168.  	shotlimit = (multi || save_cm) ? multi + 1 : 0;
169.  	multi = 0;		/* reset; it's been used up */
170.  
171.  	if(check_capacity((char *)0)) return(0);
172.  	obj = getobj(uwep && uwep->otyp==SLING ? bullets : toss_objs, "throw");
173.  	/* it is also possible to throw food */
174.  	/* (or jewels, or iron balls... ) */
175.  
176.  	if (!obj) return(0);
177.  	return throw_obj(obj, shotlimit);
178.  }
179.  
180.  
181.  /* KMH -- Automatically fill quiver */
182.  /* Suggested by Jeffrey Bay <jbay@convex.hp.com> */
183.  static void
184.  autoquiver ()
185.  {
186.  	register struct obj *otmp, *oammo = 0, *omissile = 0, *omisc = 0;
187.  
188.  
189.  	if (uquiver)
190.  		return;
191.  
192.  	/* Scan through the inventory */
193.  	for (otmp = invent; otmp; otmp = otmp->nobj) {
194.  		if (otmp->owornmask)
195.  			/* Skip it */;
196.  		else if (is_ammo(otmp)) {
197.  			if (ammo_and_launcher(otmp, uwep))
198.  				/* Ammo matched with launcher (bow and arrow, crossbow and bolt) */
199.  				oammo = otmp;
200.  			else
201.  				/* Mismatched ammo (no better than an ordinary weapon) */
202.  				omisc = otmp;
203.  		} else if (is_missile(otmp))
204.  			/* Missile (dart, shuriken, etc.) */
205.  			omissile = otmp;
206.  		else if (otmp->oclass == WEAPON_CLASS)
207.  			/* Ordinary weapon */
208.  			omisc = otmp;
209.  	}
210.  
211.  	/* Pick the best choice */
212.  	if (oammo)
213.  		setuqwep(oammo);
214.  	else if (omissile)
215.  		setuqwep(omissile);
216.  	else if (omisc)
217.  		setuqwep(omisc);
218.  
219.  	return;
220.  }
221.  
222.  
223.  /* Throw from the quiver */
224.  int
225.  dofire()
226.  {
227.  	int shotlimit;
228.  
229.  	if(check_capacity((char *)0)) return(0);
230.  	if (!uquiver) {
231.  		if (!flags.autoquiver) {
232.  			/* Don't automatically fill the quiver */
233.  			You("have no ammunition readied!");
234.  			return(dothrow());
235.  		}
236.  		autoquiver();
237.  		if (!uquiver) {
238.  			You("have nothing appropriate for your quiver!");
239.  			return(dothrow());
240.  		} else {
241.  			You("fill your quiver:");
242.  			prinv((char *)0, uquiver, 0L);
243.  		}
244.  	}
245.  
246.  	/*
247.  	 * Since some characters shoot multiple missiles at one time,
248.  	 * allow user to specify a count prefix for 'f' or 't' to limit
249.  	 * number of items thrown (to avoid possibly hitting something
250.  	 * behind target after killing it, or perhaps to conserve ammo).
251.  	 *
252.  	 * The number specified can never increase the number of missiles.
253.  	 * Using ``5f when the shooting skill (plus RNG) dictates launch
254.  	 * of 3 projectiles will result in 3 being shot, not 5.
255.  	 */
256.  	/* kludge to work around parse()'s pre-decrement of `multi' */
257.  	shotlimit = (multi || save_cm) ? multi + 1 : 0;
258.  	multi = 0;		/* reset; it's been used up */
259.  
260.  	return throw_obj(uquiver, shotlimit);
261.  }
262.  
263.  
264.  /*
265.   * Object hits floor at hero's feet.  Called from drop() and throwit().
266.   */
267.  void
268.  hitfloor(obj)
269.  register struct obj *obj;
270.  {
271.  	if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
272.  		dropy(obj);
273.  		return;
274.  	}
275.  	if (IS_ALTAR(levl[u.ux][u.uy].typ))
276.  		doaltarobj(obj);
277.  	else
278.  		pline("%s hit%s the %s.", Doname2(obj),
279.  		      (obj->quan == 1L) ? "s" : "", surface(u.ux,u.uy));
280.  
281.  	if (hero_breaks(obj, u.ux, u.uy, TRUE)) return;
282.  	if (ship_object(obj, u.ux, u.uy, FALSE)) return;
283.  	dropy(obj);
284.  }
285.  
286.  /*
287.   * The player moves through the air for a few squares as a result of
288.   * throwing or kicking something.  To simplify matters, bumping into monsters
289.   * won't cause damage but will wake them and make them angry.
290.   * Auto-pickup isn't done, since you don't have control over your movements
291.   * at the time.
292.   * dx and dy should be the direction of the hurtle, not of the original
293.   * kick or throw.
294.   */
295.  void
296.  hurtle(dx, dy, range, verbos)
297.      int dx, dy, range;
298.      boolean verbos;
299.  {
300.      register struct monst *mon;
301.      struct obj *obj;
302.      int nx, ny;
303.  
304.      /* The chain is stretched vertically, so you shouldn't be able to move
305.       * very far diagonally.  The premise that you should be able to move one
306.       * spot leads to calculations that allow you to only move one spot away
307.       * from the ball, if you are levitating over the ball, or one spot
308.       * towards the ball, if you are at the end of the chain.  Rather than
309.       * bother with all of that, assume that there is no slack in the chain
310.       * for diagonal movement, give the player a message and return.
311.       */
312.      if(Punished && !carried(uball)) {
313.  	You_feel("a tug from the iron ball.");
314.  	nomul(0);
315.  	return;
316.      } else if (u.utrap) {
317.  	You("are anchored by the %s.",
318.  	    u.utraptype == TT_WEB ? "web" : u.utraptype == TT_LAVA ? "lava" :
319.  		u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) : "trap");
320.  	nomul(0);
321.  	return;
322.      }
323.  
324.      if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
325.  
326.      nomul(-range);
327.      if (verbos)
328.  	You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
329.      while(range--) {
330.  	nx = u.ux + dx;
331.  	ny = u.uy + dy;
332.  
333.  	if(!isok(nx,ny)) break;
334.  	if(IS_ROCK(levl[nx][ny].typ) || closed_door(nx,ny) ||
335.  	   (IS_DOOR(levl[nx][ny].typ) && (levl[nx][ny].doormask & D_ISOPEN))) {
336.  	    pline("Ouch!");
337.  	    losehp(rnd(2+range), IS_ROCK(levl[nx][ny].typ) ?
338.  		   "bumping into a wall" : "bumping into a door", KILLED_BY);
339.  	    break;
340.  	}
341.  
342.  	if ((obj = sobj_at(BOULDER,nx,ny)) != 0) {
343.  	    You("bump into a %s.  Ouch!", xname(obj));
344.  	    losehp(rnd(2+range), "bumping into a boulder", KILLED_BY);
345.  	    break;
346.  	}
347.  
348.  	u.ux = nx;
349.  	u.uy = ny;
350.  	newsym(u.ux - dx, u.uy - dy);
351.  	if ((mon = m_at(u.ux, u.uy)) != 0) {
352.  	    You("bump into %s.", a_monnam(mon));
353.  	    wakeup(mon);
354.  	    if(Is_airlevel(&u.uz))
355.  		mnexto(mon);
356.  	    else {
357.  		/* sorry, not ricochets */
358.  		u.ux -= dx;
359.  		u.uy -= dy;
360.  	    }
361.  	    range = 0;
362.  	}
363.  
364.  	vision_recalc(1);		/* update for new position */
365.  
366.  	if(range) {
367.  	    flush_screen(1);
368.  	    delay_output();
369.  	}
370.      }
371.  }
372.  
373.  STATIC_OVL void
374.  check_shop_obj(obj, x, y, broken)
375.  register struct obj *obj;
376.  register xchar x, y;
377.  register boolean broken;
378.  {
379.  	struct monst *shkp = shop_keeper(*u.ushops);
380.  
381.  	if(!shkp) return;
382.  
383.  	if(broken) {
384.  		if (obj->unpaid) {
385.  		    (void)stolen_value(obj, u.ux, u.uy,
386.  				       (boolean)shkp->mpeaceful, FALSE);
387.  		    subfrombill(obj, shkp);
388.  		}
389.  		obj->no_charge = 1;
390.  		return;
391.  	}
392.  
393.  	if (!costly_spot(x, y) || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
394.  		/* thrown out of a shop or into a different shop */
395.  		if (obj->unpaid) {
396.  		    (void)stolen_value(obj, u.ux, u.uy,
397.  				       (boolean)shkp->mpeaceful, FALSE);
398.  		    subfrombill(obj, shkp);
399.  		}
400.  	} else {
401.  		if (costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
402.  		    if(obj->unpaid) subfrombill(obj, shkp);
403.  		    else if(!(x == shkp->mx && y == shkp->my))
404.  			    sellobj(obj, x, y);
405.  		}
406.  	}
407.  }
408.  
409.  /*
410.   * Hero tosses an object upwards with appropriate consequences.
411.   *
412.   * Returns FALSE if the object is gone.
413.   */
414.  STATIC_OVL boolean
415.  toss_up(obj, hitsroof)
416.  struct obj *obj;
417.  boolean hitsroof;
418.  {
419.      const char *almost;
420.      /* note: obj->quan == 1 */
421.  
422.      if (hitsroof) {
423.  	if (breaktest(obj)) {
424.  		pline("%s hits the %s.", Doname2(obj), ceiling(u.ux, u.uy));
425.  		breakmsg(obj, !Blind);
426.  		breakobj(obj, u.ux, u.uy, TRUE, TRUE);
427.  		return FALSE;
428.  	}
429.  	almost = "";
430.      } else {
431.  	almost = " almost";
432.      }
433.      pline("%s%s hits the %s, then falls back on top of your %s.",
434.  	  Doname2(obj), almost, ceiling(u.ux,u.uy), body_part(HEAD));
435.  
436.      /* object now hits you */
437.  
438.      if (obj->oclass == POTION_CLASS) {
439.  	potionhit(&youmonst, obj, TRUE);
440.      } else if (breaktest(obj)) {
441.  	int otyp = obj->otyp, ocorpsenm = obj->corpsenm;
442.  	int blindinc;
443.  
444.  	breakmsg(obj, !Blind);
445.  	breakobj(obj, u.ux, u.uy, TRUE, TRUE);
446.  	obj = 0;	/* it's now gone */
447.  	switch (otyp) {
448.  	case EGG:
449.  		if (touch_petrifies(&mons[ocorpsenm]) &&
450.  		    !uarmh && !Stone_resistance &&
451.  		    !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)))
452.  		goto petrify;
453.  	case CREAM_PIE:
454.  	case BLINDING_VENOM:
455.  		pline("You've got it all over your face!");
456.  		blindinc = rnd(25);
457.  		if (blindinc && !Blindfolded) {
458.  		    if (otyp != BLINDING_VENOM)
459.  			u.ucreamed += blindinc;
460.  		    else if (!Blind)
461.  			pline("It blinds you!");
462.  		    make_blinded(Blinded + blindinc, FALSE);
463.  		}
464.  		break;
465.  	default:
466.  		break;
467.  	}
468.  	return FALSE;
469.      } else {		/* neither potion nor other breaking object */
470.  	boolean less_damage = uarmh && is_metallic(uarmh);
471.  	int dmg = dmgval(obj, &youmonst);
472.  
473.  	if (!dmg) {	/* probably wasn't a weapon; base damage on weight */
474.  	    dmg = (int) obj->owt / 100;
475.  	    if (dmg < 1) dmg = 1;
476.  	    else if (dmg > 6) dmg = 6;
477.  	    if (youmonst.data == &mons[PM_SHADE] &&
478.  		    objects[obj->otyp].oc_material != SILVER)
479.  		dmg = 0;
480.  	}
481.  	if (dmg > 1 && less_damage) dmg = 1;
482.  	if (dmg > 0) dmg += u.udaminc;
483.  	if (dmg < 0) dmg = 0;	/* beware negative rings of increase damage */
484.  
485.  	if (uarmh) {
486.  	    if (less_damage && dmg < (Upolyd ? u.mh : u.uhp))
487.  		pline("Fortunately, you are wearing a hard helmet.");
488.  	    else if (flags.verbose &&
489.  		    !(obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])))
490.  		Your("%s does not protect you.", xname(uarmh));
491.  	} else if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
492.  	    if (!Stone_resistance &&
493.  		    !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
494.   petrify:
495.  		killer_format = KILLED_BY;
496.  		killer = "elementary physics";	/* "what goes up..." */
497.  		You("turn to stone.");
498.  		if (obj) dropy(obj);	/* bypass most of hitfloor() */
499.  		done(STONING);
500.  		return obj ? TRUE : FALSE;
501.  	    }
502.  	}
503.  	hitfloor(obj);
504.  	losehp(dmg, "falling object", KILLED_BY_AN);
505.      }
506.      return TRUE;
507.  }
508.  
509.  /* return true for weapon meant to be thrown; excludes ammo */
510.  STATIC_OVL boolean
511.  throwing_weapon(obj)
512.  struct obj *obj;
513.  {
514.  	return (is_missile(obj) || is_spear(obj) ||
515.  			/* daggers and knife (excludes scalpel) */
516.  			(is_blade(obj) && (objects[obj->otyp].oc_dir & PIERCE)) ||
517.  			/* special cases [might want to add AXE] */
518.  			obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
519.  }
520.  
521.  /* the currently thrown object is returning to you (not for boomerangs) */
522.  STATIC_OVL void
523.  sho_obj_return_to_u(obj)
524.  struct obj *obj;
525.  {
526.      /* might already be our location (bounced off a wall) */
527.      if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
528.  	int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
529.  
530.  	tmp_at(DISP_FLASH, obj_to_glyph(obj));
531.  	while(x != u.ux || y != u.uy) {
532.  	    tmp_at(x, y);
533.  	    delay_output();
534.  	    x -= u.dx; y -= u.dy;
535.  	}
536.  	tmp_at(DISP_END, 0);
537.      }
538.  }
539.  
540.  void
541.  throwit(obj)
542.  register struct obj *obj;
543.  {
544.  	register struct monst *mon;
545.  	register int range, urange;
546.  	boolean impaired = (Confusion || Stunned || Blind ||
547.  			   Hallucination || Fumbling);
548.  
549.  	if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
550.  	    boolean slipok = TRUE;
551.  	    if (ammo_and_launcher(obj, uwep))
552.  		pline("%s misfires!", The(xname(obj)));
553.  	    else {
554.  		/* only slip if it's greased or meant to be thrown */
555.  		if (obj->greased || throwing_weapon(obj))
556.  		    /* BUG: this message is grammatically incorrect if obj has
557.  		       a plural name; greased gloves or boots for instance. */
558.  		    pline("%s slips as you throw it!", The(xname(obj)));
559.  		else slipok = FALSE;
560.  	    }
561.  	    if (slipok) {
562.  		u.dx = rn2(3)-1;
563.  		u.dy = rn2(3)-1;
564.  		if (!u.dx && !u.dy) u.dz = 1;
565.  		impaired = TRUE;
566.  	    }
567.  	}
568.  
569.  	if(u.uswallow) {
570.  		mon = u.ustuck;
571.  		bhitpos.x = mon->mx;
572.  		bhitpos.y = mon->my;
573.  	} else if(u.dz) {
574.  	    if (u.dz < 0 && Role_if(PM_VALKYRIE) &&
575.  		    obj->oartifact == ART_MJOLLNIR && !impaired) {
576.  		pline("%s hits the %s and returns to your hand!",
577.  		      The(xname(obj)), ceiling(u.ux,u.uy));
578.  		obj = addinv(obj);
579.  		(void) encumber_msg();
580.  		setuwep(obj);
581.  	    } else if (u.dz < 0 && !Is_airlevel(&u.uz) &&
582.  		    !Underwater && !Is_waterlevel(&u.uz)) {
583.  		(void) toss_up(obj, rn2(5));
584.  	    } else {
585.  		hitfloor(obj);
586.  	    }
587.  	    return;
588.  
589.  	} else if(obj->otyp == BOOMERANG && !Underwater) {
590.  		if(Is_airlevel(&u.uz) || Levitation)
591.  		    hurtle(-u.dx, -u.dy, 1, TRUE);
592.  		mon = boomhit(u.dx, u.dy);
593.  		if(mon == &youmonst) {		/* the thing was caught */
594.  			exercise(A_DEX, TRUE);
595.  			(void) addinv(obj);
596.  			(void) encumber_msg();
597.  			return;
598.  		}
599.  	} else {
600.  		urange = (int)(ACURRSTR)/2;
601.  		/* balls are easy to throw or at least roll */
602.  		/* also, this insures the maximum range of a ball is greater
603.  		 * than 1, so the effects from throwing attached balls are
604.  		 * actually possible
605.  		 */
606.  		if (obj->otyp == HEAVY_IRON_BALL)
607.  			range = urange - (int)(obj->owt/100);
608.  		else
609.  			range = urange - (int)(obj->owt/40);
610.  		if (obj == uball) {
611.  			if (u.ustuck) range = 1;
612.  			else if (range >= 5) range = 5;
613.  		}
614.  		if (range < 1) range = 1;
615.  
616.  		if (is_ammo(obj)) {
617.  		    if (ammo_and_launcher(obj, uwep))
618.  			range++;
619.  		    else
620.  			range /= 2;
621.  		}
622.  
623.  		if (Is_airlevel(&u.uz) || Levitation) {
624.  		    /* action, reaction... */
625.  		    urange -= range;
626.  		    if(urange < 1) urange = 1;
627.  		    range -= urange;
628.  		    if(range < 1) range = 1;
629.  		}
630.  
631.  		if (obj->otyp == BOULDER)
632.  		    range = 20;		/* you must be giant */
633.  		else if (obj->oartifact == ART_MJOLLNIR)
634.  		    range = (range + 1) / 2;	/* it's heavy */
635.  		else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
636.  		    range = 1;
637.  
638.  		if (Underwater) range = 1;
639.  
640.  		mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
641.  			   (int FDECL((*),(MONST_P,OBJ_P)))0,
642.  			   (int FDECL((*),(OBJ_P,OBJ_P)))0,
643.  			   obj);
644.  
645.  		/* have to do this after bhit() so u.ux & u.uy are correct */
646.  		if(Is_airlevel(&u.uz) || Levitation)
647.  		    hurtle(-u.dx, -u.dy, urange, TRUE);
648.  	}
649.  
650.  	if (mon) {
651.  		boolean obj_gone;
652.  
653.  		if (mon->isshk &&
654.  			obj->where == OBJ_MINVENT && obj->ocarry == mon)
655.  		    return;		/* alert shk caught it */
656.  		(void) snuff_candle(obj);
657.  		notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
658.  		obj_gone = thitmonst(mon, obj);
659.  
660.  		/* [perhaps this should be moved into thitmonst or hmon] */
661.  		if (mon->isshk &&
662.  			(!inside_shop(u.ux, u.uy) ||
663.  			 !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)))
664.  		    hot_pursuit(mon);
665.  
666.  		if (obj_gone) return;
667.  	}
668.  
669.  	if (u.uswallow) {
670.  		/* ball is not picked up by monster */
671.  		if (obj != uball) mpickobj(u.ustuck,obj);
672.  	} else {
673.  		/* the code following might become part of dropy() */
674.  		if (obj->oartifact == ART_MJOLLNIR &&
675.  			Role_if(PM_VALKYRIE) && rn2(100)) {
676.  		    /* we must be wearing Gauntlets of Power to get here */
677.  		    sho_obj_return_to_u(obj);	    /* display its flight */
678.  
679.  		    if (!impaired && rn2(100)) {
680.  			pline("%s returns to your hand!", The(xname(obj)));
681.  			obj = addinv(obj);
682.  			(void) encumber_msg();
683.  			setuwep(obj);
684.  			if(cansee(bhitpos.x, bhitpos.y))
685.  			    newsym(bhitpos.x,bhitpos.y);
686.  		    } else {
687.  			int dmg = rnd(4);
688.  			if (Blind)
689.  			    pline("%s hits your %s!",
690.  				  The(xname(obj)), body_part(ARM));
691.  			else
692.  			    pline("%s flies back toward you, hitting your %s!",
693.  				  The(xname(obj)), body_part(ARM));
694.  			(void) artifact_hit((struct monst *) 0, &youmonst,
695.  					    obj, &dmg, 0);
696.  			losehp(dmg, xname(obj), KILLED_BY);
697.  			if(ship_object(obj, u.ux, u.uy, FALSE))
698.  		            return;
699.  			dropy(obj);
700.  		    }
701.  		    return;
702.  		}
703.  
704.  		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
705.  			breaktest(obj)) {
706.  		    tmp_at(DISP_FLASH, obj_to_glyph(obj));
707.  		    tmp_at(bhitpos.x, bhitpos.y);
708.  		    delay_output();
709.  		    tmp_at(DISP_END, 0);
710.  		    breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
711.  		    breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
712.  		    return;
713.  		}
714.  		if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return;
715.  		if (obj->otyp == CRYSKNIFE && (!obj->oerodeproof || !rn2(10))) {
716.  		    obj->otyp = WORM_TOOTH;
717.  		    obj->oerodeproof = 0;
718.  		}
719.  		if (mon && mon->isshk && is_pick(obj)) {
720.  		    if (cansee(bhitpos.x, bhitpos.y))
721.  			pline("%s snatches up %s.",
722.  			      Monnam(mon), the(xname(obj)));
723.  		    mpickobj(mon, obj);
724.  		    if(*u.ushops)
725.  			check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
726.  		    return;
727.  		}
728.  		(void) snuff_candle(obj);
729.  		if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
730.  		    return;
731.  		place_object(obj, bhitpos.x, bhitpos.y);
732.  		if(*u.ushops && obj != uball)
733.  		    check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
734.  
735.  		stackobj(obj);
736.  		if (obj == uball)
737.  		    drop_ball(bhitpos.x, bhitpos.y);
738.  		if (cansee(bhitpos.x, bhitpos.y))
739.  		    newsym(bhitpos.x,bhitpos.y);
740.  		if (obj_sheds_light(obj))
741.  		    vision_full_recalc = 1;
742.  	}
743.  }
744.  
745.  /* an object may hit a monster; various factors adjust the chance of hitting */
746.  int
747.  omon_adj(mon, obj, mon_notices)
748.  struct monst *mon;
749.  struct obj *obj;
750.  boolean mon_notices;
751.  {
752.  	int tmp = 0;
753.  
754.  	/* size of target affects the chance of hitting */
755.  	tmp += (mon->data->msize - MZ_MEDIUM);		/* -2..+5 */
756.  	/* sleeping target is more likely to be hit */
757.  	if (mon->msleeping) {
758.  	    tmp += 2;
759.  	    if (mon_notices) mon->msleeping = 0;
760.  	}
761.  	/* ditto for immobilized target */
762.  	if (!mon->mcanmove || !mon->data->mmove) {
763.  	    tmp += 4;
764.  	    if (mon_notices && mon->data->mmove && !rn2(10)) {
765.  		mon->mcanmove = 1;
766.  		mon->mfrozen = 0;
767.  	    }
768.  	}
769.  	/* some objects are more likely to hit than others */
770.  	switch (obj->otyp) {
771.  	case HEAVY_IRON_BALL:
772.  	    if (obj != uball) tmp += 2;
773.  	    break;
774.  	case BOULDER:
775.  	    tmp += 6;
776.  	    break;
777.  	default:
778.  	    if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
779.  		    obj->oclass == GEM_CLASS)
780.  		tmp += hitval(obj, mon);
781.  	    break;
782.  	}
783.  	return tmp;
784.  }
785.  
786.  /* thrown object misses target monster */
787.  STATIC_OVL void
788.  tmiss(obj, mon)
789.  struct obj *obj;
790.  struct monst *mon;
791.  {
792.      miss(xname(obj), mon);
793.      if (!rn2(3)) wakeup(mon);
794.      return;
795.  }
796.  
797.  #define quest_arti_hits_leader(obj,mon)	\
798.    (obj->oartifact && is_quest_artifact(obj) && (mon->data->msound == MS_LEADER))
799.  
800.  /*
801.   * Object thrown by player arrives at monster's location.
802.   * Return 1 if obj has disappeared or otherwise been taken care of,
803.   * 0 if caller must take care of it.
804.   */
805.  int
806.  thitmonst(mon, obj)
807.  register struct monst *mon;
808.  register struct obj   *obj;
809.  {
810.  	register int	tmp; /* Base chance to hit */
811.  	register int	disttmp; /* distance modifier */
812.  	int otyp = obj->otyp;
813.  	boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
814.  
815.  	/* Differences from melee weapons:
816.  	 *
817.  	 * Dex still gives a bonus, but strength does not.
818.  	 * Polymorphed players lacking attacks may still throw.
819.  	 * There's a base -1 to hit.
820.  	 * No bonuses for fleeing or stunned targets (they don't dodge
821.  	 *    melee blows as readily, but dodging arrows is hard anyway).
822.  	 * Not affected by traps, etc.
823.  	 * Certain items which don't in themselves do damage ignore tmp.
824.  	 * Distance and monster size affect chance to hit.
825.  	 */
826.  	tmp = -1 + Luck + find_mac(mon) + u.uhitinc +
827.  			maybe_polyd(youmonst.data->mlevel, u.ulevel);
828.  	if (ACURR(A_DEX) < 4) tmp -= 3;
829.  	else if (ACURR(A_DEX) < 6) tmp -= 2;
830.  	else if (ACURR(A_DEX) < 8) tmp -= 1;
831.  	else if (ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
832.  
833.  	/* modify to-hit depending on distance; but keep it sane */
834.  	disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
835.  	if(disttmp < -4) disttmp = -4;
836.  	tmp += disttmp;
837.  
838.  	/* gloves are a hinderance to proper use of bows */
839.  	if (uarmg && uwep && objects[uwep->otyp].oc_skill == P_BOW) {
840.  	    switch (uarmg->otyp) {
841.  	    case GAUNTLETS_OF_POWER:    /* metal */
842.  		tmp -= 2;
843.  		break;
844.  	    case GAUNTLETS_OF_FUMBLING:
845.  		tmp -= 3;
846.  		break;
847.  	    case LEATHER_GLOVES:
848.  	    case GAUNTLETS_OF_DEXTERITY:
849.  		break;
850.  	    default:
851.  		impossible("Unknown type of gloves (%d)", uarmg->otyp);
852.  		break;
853.  	    }
854.  	}
855.  
856.  	tmp += omon_adj(mon, obj, TRUE);
857.  	if (is_orc(mon->data) && maybe_polyd(is_elf(youmonst.data),
858.  			Race_if(PM_ELF)))
859.  	    tmp++;
860.  	if (guaranteed_hit) {
861.  	    tmp += 1000; /* Guaranteed hit */
862.  	}
863.  
864.  	if (obj->oclass == GEM_CLASS && is_unicorn(mon->data)) {
865.  	    if (mon->mtame) {
866.  		pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
867.  		return 0;
868.  	    } else {
869.  		pline("%s catches %s.", Monnam(mon), the(xname(obj)));
870.  		return gem_accept(mon, obj);
871.  	    }
872.  	}
873.  
874.  	/* don't make game unwinnable if naive player throws artifact
875.  	   at leader.... */
876.  	if (quest_arti_hits_leader(obj, mon)) {
877.  	    /* not wakeup(), which angers non-tame monsters */
878.  	    mon->msleeping = 0;
879.  	    mon->mstrategy &= ~STRAT_WAITMASK;
880.  
881.  	    if (mon->mcanmove) {
882.  		pline("%s catches %s.", Monnam(mon), the(xname(obj)));
883.  		if (mon->mpeaceful) {
884.  		    boolean next2u = monnear(mon, u.ux, u.uy);
885.  
886.  		    finish_quest(obj);	/* acknowledge quest completion */
887.  		    pline("%s %s %s back to you.", Monnam(mon),
888.  			  (next2u ? "hands" : "tosses"), the(xname(obj)));
889.  		    if (!next2u) sho_obj_return_to_u(obj);
890.  		    obj = addinv(obj);	/* back into your inventory */
891.  		    (void) encumber_msg();
892.  		} else {
893.  		    /* angry leader caught it and isn't returning it */
894.  		    mpickobj(mon, obj);
895.  		}
896.  		return 1;		/* caller doesn't need to place it */
897.  	    }
898.  	    return(0);
899.  	}
900.  
901.  	if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
902.  		obj->oclass == GEM_CLASS) {
903.  	    if (is_ammo(obj)) {
904.  		if (!ammo_and_launcher(obj, uwep)) {
905.  		    tmp -= 4;
906.  		} else {
907.  		    tmp += uwep->spe - greatest_erosion(uwep);
908.  		    tmp += weapon_hit_bonus(uwep);
909.  		    /*
910.  		     * Elves and Samurais are highly trained w/bows,
911.  		     * especially their own special types of bow.
912.  		     * Polymorphing won't make you a bow expert.
913.  		     */
914.  		    if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI)) &&
915.  				objects[uwep->otyp].oc_skill == P_BOW) {
916.  			tmp++;
917.  			if (is_elf(youmonst.data) && uwep->otyp == ELVEN_BOW) tmp++;
918.  			else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI) tmp++;
919.  		    }
920.  		}
921.  	    } else {
922.  		if (otyp == BOOMERANG)		/* arbitrary */
923.  		    tmp += 4;
924.  		else if (throwing_weapon(obj))	/* meant to be thrown */
925.  		    tmp += 2;
926.  		else				/* not meant to be thrown */
927.  		    tmp -= 2;
928.  		/* we know we're dealing with a weapon or weptool handled
929.  		   by WEAPON_SKILLS once ammo objects have been excluded */
930.  		tmp += weapon_hit_bonus(obj);
931.  	    }
932.  
933.  	    if (tmp >= rnd(20)) {
934.  		if (hmon(mon,obj,1)) {	/* mon still alive */
935.  		    cutworm(mon, bhitpos.x, bhitpos.y, obj);
936.  		}
937.  		exercise(A_DEX, TRUE);
938.  		/* projectiles other than magic stones
939.  		   sometimes disappear when thrown */
940.  		if (objects[otyp].oc_skill < P_NONE &&
941.  				objects[otyp].oc_skill > -P_BOOMERANG &&
942.  				!objects[otyp].oc_magic && rn2(3)) {
943.  		    if (*u.ushops)
944.  			check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
945.  		    obfree(obj, (struct obj *)0);
946.  		    return 1;
947.  		}
948.  	    } else {
949.  		tmiss(obj, mon);
950.  	    }
951.  
952.  	} else if (otyp == HEAVY_IRON_BALL) {
953.  	    exercise(A_STR, TRUE);
954.  	    if (tmp >= rnd(20)) {
955.  		int was_swallowed = guaranteed_hit;
956.  
957.  		exercise(A_DEX, TRUE);
958.  		if (!hmon(mon,obj,1)) {		/* mon killed */
959.  		    if (was_swallowed && !u.uswallow && obj == uball)
960.  			return 1;	/* already did placebc() */
961.  		}
962.  	    } else {
963.  		tmiss(obj, mon);
964.  	    }
965.  
966.  	} else if (otyp == BOULDER) {
967.  	    exercise(A_STR, TRUE);
968.  	    if (tmp >= rnd(20)) {
969.  		exercise(A_DEX, TRUE);
970.  		(void) hmon(mon,obj,1);
971.  	    } else {
972.  		tmiss(obj, mon);
973.  	    }
974.  
975.  	} else if ((otyp == EGG || otyp == CREAM_PIE ||
976.  		    otyp == BLINDING_VENOM || otyp == ACID_VENOM) &&
977.  		(guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
978.  	    (void) hmon(mon, obj, 1);
979.  	    return 1;	/* hmon used it up */
980.  
981.  	} else if (obj->oclass == POTION_CLASS &&
982.  		(guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
983.  	    potionhit(mon, obj, TRUE);
984.  	    return 1;
985.  
986.  	} else if (obj->oclass == FOOD_CLASS &&
987.  		   is_domestic(mon->data) && tamedog(mon,obj)) {
988.  	    return 1;		/* food is gone */
989.  	} else if (guaranteed_hit) {
990.  	    /* this assumes that guaranteed_hit is due to swallowing */
991.  	    pline("%s vanishes into %s %s.",
992.  		The(xname(obj)), s_suffix(mon_nam(mon)),
993.  		is_animal(u.ustuck->data) ? "entrails" : "currents");
994.  	    wakeup(mon);
995.  	} else {
996.  	    tmiss(obj, mon);
997.  	}
998.  
999.  	return 0;
1000. }
1001. 
1002. STATIC_OVL int
1003. gem_accept(mon, obj)
1004. register struct monst *mon;
1005. register struct obj *obj;
1006. {
1007. 	char buf[BUFSZ];
1008. 	boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
1009. 	boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
1010. 	int ret = 0;
1011. 	static NEARDATA const char nogood[] = " is not interested in your junk.";
1012. 	static NEARDATA const char acceptgift[] = " accepts your gift.";
1013. 	static NEARDATA const char maybeluck[] = " hesitatingly";
1014. 	static NEARDATA const char noluck[] = " graciously";
1015. 	static NEARDATA const char addluck[] = " gratefully";
1016. 
1017. 	Strcpy(buf,Monnam(mon));
1018. 	mon->mpeaceful = 1;
1019. 
1020. 	/* object properly identified */
1021. 	if(obj->dknown && objects[obj->otyp].oc_name_known) {
1022. 		if(is_gem) {
1023. 			if(is_buddy) {
1024. 				Strcat(buf,addluck);
1025. 				change_luck(5);
1026. 			} else {
1027. 				Strcat(buf,maybeluck);
1028. 				change_luck(rn2(7)-3);
1029. 			}
1030. 		} else {
1031. 			Strcat(buf,nogood);
1032. 			goto nopick;
1033. 		}
1034. 	/* making guesses */
1035. 	} else if(obj->onamelth || objects[obj->otyp].oc_uname) {
1036. 		if(is_gem) {
1037. 			if(is_buddy) {
1038. 				Strcat(buf,addluck);
1039. 				change_luck(2);
1040. 			} else {
1041. 				Strcat(buf,maybeluck);
1042. 				change_luck(rn2(3)-1);
1043. 			}
1044. 		} else {
1045. 			Strcat(buf,nogood);
1046. 			goto nopick;
1047. 		}
1048. 	/* value completely unknown to @ */
1049. 	} else {
1050. 		if(is_gem) {
1051. 			if(is_buddy) {
1052. 				Strcat(buf,addluck);
1053. 				change_luck(1);
1054. 			} else {
1055. 				Strcat(buf,maybeluck);
1056. 				change_luck(rn2(3)-1);
1057. 			}
1058. 		} else {
1059. 			Strcat(buf,noluck);
1060. 		}
1061. 	}
1062. 	Strcat(buf,acceptgift);
1063. 	mpickobj(mon, obj);
1064. 	if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
1065. 	ret = 1;
1066. 
1067. nopick:
1068. 	if(!Blind) pline(buf);
1069. 	rloc(mon);
1070. 	return(ret);
1071. }
1072. 
1073. /*
1074.  * Comments about the restructuring of the old breaks() routine.
1075.  *
1076.  * There are now three distinct phases to object breaking:
1077.  *     breaktest() - which makes the check/decision about whether the
1078.  *                   object is going to break.
1079.  *     breakmsg()  - which outputs a message about the breakage,
1080.  *                   appropriate for that particular object. Should
1081.  *                   only be called after a positve breaktest().
1082.  *                   on the object and, if it going to be called,
1083.  *                   it must be called before calling breakobj().
1084.  *                   Calling breakmsg() is optional.
1085.  *     breakobj()  - which actually does the breakage and the side-effects
1086.  *                   of breaking that particular object. This should
1087.  *                   only be called after a positive breaktest() on the
1088.  *                   object.
1089.  *
1090.  * Each of the above routines is currently static to this source module.
1091.  * There are two routines callable from outside this source module which
1092.  * perform the routines above in the correct sequence.
1093.  *
1094.  *   hero_breaks() - called when an object is to be broken as a result
1095.  *                   of something that the hero has done. (throwing it,
1096.  *                   kicking it, etc.)
1097.  *   breaks()      - called when an object is to be broken for some
1098.  *                   reason other than the hero doing something to it.
1099.  */
1100. 
1101. /*
1102.  * The hero causes breakage of an object (throwing, dropping it, etc.)
1103.  * Return 0 if the object didn't break, 1 if the object broke.
1104.  */
1105. int
1106. hero_breaks(obj, x, y, from_invent)
1107. struct obj *obj;
1108. xchar x, y;		/* object location (ox, oy may not be right) */
1109. boolean from_invent;	/* thrown or dropped by player; maybe on shop bill */
1110. {
1111. 	boolean in_view = !Blind;
1112. 	if (!breaktest(obj)) return 0;
1113. 	breakmsg(obj, in_view);
1114. 	breakobj(obj, x, y, TRUE, from_invent);
1115. 	return 1;
1116. }
1117. 
1118. /*
1119.  * The object is going to break for a reason other than the hero doing
1120.  * something to it.
1121.  * Return 0 if the object doesn't break, 1 if the object broke.
1122.  */
1123. int
1124. breaks(obj, x, y)
1125. struct obj *obj;
1126. xchar x, y;		/* object location (ox, oy may not be right) */
1127. {
1128. 	boolean in_view = Blind ? FALSE : cansee(x, y);
1129. 
1130. 	if (!breaktest(obj)) return 0;
1131. 	breakmsg(obj, in_view);
1132. 	breakobj(obj, x, y, FALSE, FALSE);
1133. 	return 1;
1134. }
1135. 
1136. /*
1137.  * Unconditionally break an object. Assumes all resistance checks
1138.  * and break messages have been delivered prior to getting here.
1139.  * This routine assumes the cause is the hero if heros_fault is TRUE.
1140.  *
1141.  */
1142. STATIC_OVL void
1143. breakobj(obj, x, y, heros_fault, from_invent)
1144. struct obj *obj;
1145. xchar x, y;		/* object location (ox, oy may not be right) */
1146. boolean heros_fault;
1147. boolean from_invent;
1148. {
1149. 	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1150. 		case MIRROR:
1151. 			if (heros_fault)
1152. 			    change_luck(-2);
1153. 			break;
1154. 		case POT_WATER:		/* really, all potions */
1155. 			if (obj->otyp == POT_OIL && obj->lamplit) {
1156. 			    splatter_burning_oil(x,y);
1157. 			} else if (distu(x,y) <= 2) {
1158. 			    /* [what about "familiar odor" when known?] */
1159. 			    if (obj->otyp != POT_WATER)
1160. 				You("smell a peculiar odor...");
1161. 			    potionbreathe(obj);
1162. 			}
1163. 			/* monster breathing isn't handled... [yet?] */
1164. 			break;
1165. 		case EGG:
1166. 			/* breaking your own eggs is bad luck */
1167. 			if (heros_fault && obj->spe && obj->corpsenm >= LOW_PM)
1168. 			    change_luck((schar) -min(obj->quan, 5L));
1169. 			break;
1170. 	}
1171. 	if (heros_fault) {
1172. 	    if (from_invent) {
1173. 		if (*u.ushops)
1174. 			check_shop_obj(obj, x, y, TRUE);
1175. 	    } else if (!obj->no_charge && costly_spot(x, y)) {
1176. 		/* it is assumed that the obj is a floor-object */
1177. 		char *o_shop = in_rooms(x, y, SHOPBASE);
1178. 		struct monst *shkp = shop_keeper(*o_shop);
1179. 
1180. 		if (shkp) {		/* (implies *o_shop != '\0') */
1181. 		    static NEARDATA long lastmovetime = 0L;
1182. 		    static NEARDATA boolean peaceful_shk = FALSE;
1183. 		    /*  We want to base shk actions on her peacefulness
1184. 			at start of this turn, so that "simultaneous"
1185. 			multiple breakage isn't drastically worse than
1186. 			single breakage.  (ought to be done via ESHK)  */
1187. 		    if (moves != lastmovetime)
1188. 			peaceful_shk = shkp->mpeaceful;
1189. 		    if (stolen_value(obj, x, y, peaceful_shk, FALSE) > 0L &&
1190. 			(*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy)) &&
1191. 			moves != lastmovetime) make_angry_shk(shkp, x, y);
1192. 		    lastmovetime = moves;
1193. 		}
1194. 	    }
1195. 	}
1196. 	delobj(obj);
1197. }
1198. 
1199. /*
1200.  * Check to see if obj is going to break, but don't actually break it.
1201.  * Return 0 if the object isn't going to break, 1 if it is.
1202.  */
1203. boolean
1204. breaktest(obj)
1205. struct obj *obj;
1206. {
1207. 	if (obj_resists(obj, 1, 99)) return 0;
1208. 	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1209. 		case MIRROR:
1210. 		case CRYSTAL_BALL:
1211. #ifdef TOURIST
1212. 		case EXPENSIVE_CAMERA:
1213. #endif
1214. 		case POT_WATER:		/* really, all potions */
1215. 		case EGG:
1216. 		case CREAM_PIE:
1217. 		case ACID_VENOM:
1218. 		case BLINDING_VENOM:
1219. 			return 1;
1220. 		default:
1221. 			return 0;
1222. 	}
1223. }
1224. 
1225. STATIC_OVL void
1226. breakmsg(obj, in_view)
1227. struct obj *obj;
1228. boolean in_view;
1229. {
1230. 	const char *to_pieces;
1231. 
1232. 	to_pieces = "";
1233. 	switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
1234. 		case MIRROR:
1235. 		case CRYSTAL_BALL:
1236. #ifdef TOURIST
1237. 		case EXPENSIVE_CAMERA:
1238. #endif
1239. 			to_pieces = " into a thousand pieces";
1240. 			/*FALLTHRU*/
1241. 		case POT_WATER:		/* really, all potions */
1242. 			if (!in_view)
1243. 			    You_hear("%s shatter!", something);
1244. 			else
1245. 			    pline("%s shatters%s!", Doname2(obj), to_pieces);
1246. 			break;
1247. 		case EGG:
1248. 			pline("Splat!");
1249. 			break;
1250. 		case CREAM_PIE:
1251. 			if (in_view) pline("What a mess!");
1252. 			break;
1253. 		case ACID_VENOM:
1254. 		case BLINDING_VENOM:
1255. 			pline("Splash!");
1256. 			break;
1257. 	}
1258. }
1259. 
1260. /*
1261.  *  Note that the gold object is *not* attached to the fobj chain.
1262.  */
1263. STATIC_OVL int
1264. throw_gold(obj)
1265. struct obj *obj;
1266. {
1267. 	int range, odx, ody;
1268. 	long zorks = obj->quan;
1269. 	register struct monst *mon;
1270. 
1271. 	if(u.uswallow) {
1272. 		pline(is_animal(u.ustuck->data) ?
1273. 			"%s in the %s's entrails." : "%s into %s.",
1274. 			"The gold disappears", mon_nam(u.ustuck));
1275. 		u.ustuck->mgold += zorks;
1276. 		dealloc_obj(obj);
1277. 		return(1);
1278. 	}
1279. 
1280. 	if(u.dz) {
1281. 		if (u.dz < 0 && !Is_airlevel(&u.uz) &&
1282. 					!Underwater && !Is_waterlevel(&u.uz)) {
1283. 	pline_The("gold hits the %s, then falls back on top of your %s.",
1284. 		    ceiling(u.ux,u.uy), body_part(HEAD));
1285. 		    /* some self damage? */
1286. 		    if(uarmh) pline("Fortunately, you are wearing a helmet!");
1287. 		}
1288. 		bhitpos.x = u.ux;
1289. 		bhitpos.y = u.uy;
1290. 	} else {
1291. 		/* consistent with range for normal objects */
1292. 		range = (int)((ACURRSTR)/2 - obj->owt/40);
1293. 
1294. 		/* see if the gold has a place to move into */
1295. 		odx = u.ux + u.dx;
1296. 		ody = u.uy + u.dy;
1297. 		if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
1298. 			bhitpos.x = u.ux;
1299. 			bhitpos.y = u.uy;
1300. 		} else {
1301. 			mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
1302. 				   (int FDECL((*),(MONST_P,OBJ_P)))0,
1303. 				   (int FDECL((*),(OBJ_P,OBJ_P)))0,
1304. 				   obj);
1305. 			if(mon) {
1306. 			    if (ghitm(mon, obj))	/* was it caught? */
1307. 				return 1;
1308. 			} else {
1309. 			    if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
1310. 				return 1;
1311. 			}
1312. 		}
1313. 	}
1314. 
1315. 	if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
1316. 	if(u.dz > 0)
1317. 		pline_The("gold hits the %s.", surface(bhitpos.x,bhitpos.y));
1318. 	place_object(obj,bhitpos.x,bhitpos.y);
1319. 	if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
1320. 	stackobj(obj);
1321. 	newsym(bhitpos.x,bhitpos.y);
1322. 	return(1);
1323. }
1324. 
1325. /*dothrow.c*/

Also on Fandom

Random Wiki