Wikihack
Advertisement

Below is the full text to dothrow.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/12/10	*/
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 void FDECL(hitfloor, (struct obj *));
10.   static int FDECL(gem_accept, (struct monst *, struct obj *));
11.   static int FDECL(throw_gold, (struct obj *));
12.   static void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
13.   
14.   static const char NEARDATA toss_objs[] =
15.   	{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
16.   extern boolean notonhead;	/* for long worms */
17.   
18.   int
19.   dothrow()
20.   {
21.   	register struct obj *obj;
22.   
23.   	if(check_capacity(NULL)) return(0);
24.   	obj = getobj(toss_objs, "throw");
25.   	/* it is also possible to throw food */
26.   	/* (or jewels, or iron balls... ) */
27.   
28.   	if(!obj || !getdir(NULL)) {       /* ask "in what direction?" */
29.   		if (obj && obj->oclass == GOLD_CLASS) {
30.   		    u.ugold += obj->quan;
31.   		    flags.botl = 1;
32.   		    dealloc_obj(obj);
33.   		}
34.   		return(0);
35.   	}
36.   
37.   	if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
38.   
39.   	if(!canletgo(obj,"throw"))
40.   		return(0);
41.   	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
42.   		You("must be wielding %s in order to throw it.", xname(obj));
43.   		return(0);
44.   	}
45.   	if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) != 125)
46.   	   || (obj->otyp == BOULDER
47.   #ifdef POLYSELF
48.   					&& !throws_rocks(uasmon)
49.   #endif
50.   								)) {
51.   		pline("It's too heavy.");
52.   		return(1);
53.   	}
54.   	if(!u.dx && !u.dy && !u.dz) {
55.   		You("cannot throw an object at yourself.");
56.   		return(0);
57.   	}
58.   	u_wipe_engr(2);
59.   
60.   	if(obj == uwep) {
61.   	    if(welded(obj)) {
62.   		weldmsg(obj, FALSE);
63.   		return(1);
64.   	    }
65.   	    if(obj->quan > 1L)
66.   		setuwep(splitobj(obj, 1L));
67.   	    else {
68.   		setuwep((struct obj *)0);
69.   		if (uwep) return(1); /* unwielded, died, rewielded */
70.   	    }
71.   	}
72.   	else if(obj->quan > 1L)
73.   		(void) splitobj(obj, 1L);
74.   	freeinv(obj);
75.   	return(throwit(obj));
76.   }
77.   
78.   static void
79.   hitfloor(obj)
80.   register struct obj *obj;
81.   {
82.   	if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
83.   		dropy(obj);
84.   		if(*u.ushops)
85.   		    check_shop_obj(obj, obj->ox, obj->oy, FALSE);
86.   		return;
87.   	}
88.   	if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
89.   	else
90.   		pline("%s hits the floor.", Doname2(obj));
91.   	if (breaks(obj, TRUE)) return;
92.   	else if(obj->oclass == POTION_CLASS) {
93.   		pline("The flask breaks, and you smell a peculiar odor...");
94.   		potionbreathe(obj);
95.   		if(*u.ushops)
96.   		    check_shop_obj(obj, u.ux, u.uy, TRUE);
97.   		obfree(obj, (struct obj *)0);
98.   	} else {
99.   		if(ship_object(obj, u.ux, u.uy, FALSE)) 
100.  		    return;
101.  		dropy(obj);
102.  		if(*u.ushops)
103.  		    check_shop_obj(obj, obj->ox, obj->oy, FALSE);
104.  	}
105.  }
106.  
107.  /*
108.   * The player moves through the air for a few squares as a result of
109.   * throwing or kicking something.  To simplify matters, bumping into monsters
110.   * won't cause damage but will wake them and make them angry.
111.   * Auto-pickup isn't done, since you don't have control over your movements
112.   * at the time.
113.   * dx and dy should be the direction of the hurtle, not of the original
114.   * kick or throw.
115.   */
116.  void
117.  hurtle(dx, dy, range)
118.      int dx, dy, range;
119.  {
120.      register struct monst *mon;
121.      struct obj *obj;
122.      int nx, ny;
123.  
124.      if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
125.  
126.      nomul(-range);
127.      You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
128.      while(range--) {
129.  	nx = u.ux + dx;
130.  	ny = u.uy + dy;
131.  
132.  	if(!isok(nx,ny)) break;
133.  	if(IS_ROCK(levl[nx][ny].typ) || closed_door(nx,ny)) {
134.  	    pline("Ouch!");
135.  	    losehp(rnd(2+range), IS_ROCK(levl[nx][ny].typ) ?
136.  		   "bumping to a wall" : "bumping into a door", KILLED_BY);
137.  	    break;
138.  	}
139.  
140.  	if (obj = sobj_at(BOULDER,nx,ny)) {
141.  	    You("bump into a %s.  Ouch!", xname(obj));
142.  	    losehp(rnd(2+range), "bumping to a boulder", KILLED_BY);
143.  	    break;
144.  	}
145.  
146.  	u.ux = nx;
147.  	u.uy = ny;
148.  	newsym(u.ux - dx, u.uy - dy);
149.  	if(mon = m_at(u.ux, u.uy)) {
150.  	    You("bump into %s.", a_monnam(mon));
151.  	    wakeup(mon);
152.  	    if(Is_airlevel(&u.uz))
153.  		mnexto(mon);
154.  	    else {
155.  		/* sorry, not ricochets */
156.  		u.ux -= dx;
157.  		u.uy -= dy;
158.  	    }
159.  	    range = 0;
160.  	}
161.  
162.  	newsym(u.ux, u.uy);
163.  
164.  	if(range) {
165.  	    flush_screen(1);
166.  	    delay_output();
167.  	}
168.      }
169.  }
170.  
171.  static void
172.  check_shop_obj(obj, x, y, broken)
173.  register struct obj *obj;
174.  register xchar x, y;
175.  register boolean broken;
176.  {
177.  	register struct monst *shkp = 
178.  			shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
179.  
180.  	if(!shkp) return;
181.  	if(!inside_shop(u.ux, u.uy)) return;
182.  
183.  	if(broken) {
184.  	        if(obj->unpaid) {
185.  		    (void)stolen_value(obj, u.ux, u.uy, 
186.  				 (shkp && shkp->mpeaceful), FALSE);
187.  		    subfrombill(obj, shkp);
188.  		}
189.  		return;
190.  	}
191.  
192.          if(!costly_spot(x, y) ||
193.  	           *in_rooms(u.ux, u.uy, 0) != *in_rooms(x, y, 0)) { 
194.  	        if(!inside_shop(x, y) && obj->unpaid) {
195.  		    (void)stolen_value(obj, u.ux, u.uy, 
196.  				 (shkp && shkp->mpeaceful), FALSE);
197.  		    subfrombill(obj, shkp);
198.  		}
199.  	} else
200.  	        if(costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
201.  		    if(obj->unpaid) subfrombill(obj, shkp);
202.  		    else if(!(x == shkp->mx && y == shkp->my))
203.  		            sellobj(obj, x, y);
204.  		}
205.  }
206.  
207.  
208.  int
209.  throwit(obj)
210.  register struct obj *obj;
211.  {
212.  	register struct monst *mon;
213.  	register int range, urange;
214.  	boolean impaired = (Confusion || Stunned || Blind ||
215.  			   Hallucination || Fumbling);
216.  	int do_death = 0;
217.  
218.  	if (obj->cursed && (u.dx || u.dy) && !rn2(7)) {
219.  		boolean slipok = TRUE;
220.  	    if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
221.  		&& uwep && (objects[obj->otyp].w_propellor > 0) &&
222.  		(objects[obj->otyp].w_propellor ==
223.                                               -objects[uwep->otyp].w_propellor))
224.  		pline("The %s misfires!", xname(obj));
225.  	    else {
226.  		/* only slip if it's meant to be thrown */
227.  		if((obj->otyp >= DART && obj->otyp <= JAVELIN) ||
228.  		   (obj->otyp >= DAGGER && obj->otyp <= CRYSKNIFE &&
229.  		    obj->otyp != ATHAME) || obj->otyp == WAR_HAMMER)
230.  		    pline("The %s slips as you throw it!", xname(obj));
231.  		else slipok = FALSE;
232.  	    }
233.  	    if (slipok) {
234.  		u.dx = rn2(3)-1;
235.  		u.dy = rn2(3)-1;
236.  		if (!u.dx && !u.dy) u.dz = 1;
237.  		impaired = TRUE;
238.  	    }
239.  	}
240.  
241.  	if(u.uswallow) {
242.  		mon = u.ustuck;
243.  		bhitpos.x = mon->mx;
244.  		bhitpos.y = mon->my;
245.  	} else if(u.dz) {
246.  	  if (u.dz < 0 && pl_character[0] == 'V' &&
247.  	      obj->oartifact == ART_MJOLLNIR && !impaired) {
248.  	      pline("%s hits the ceiling and returns to your hand!",
249.  		    The(xname(obj)));
250.  	      obj = addinv(obj);
251.  	      setuwep(obj);
252.  	      return(1);
253.  	  }
254.  	  if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
255.  	    pline("%s hits the ceiling, then falls back on top of your %s.",
256.  		Doname2(obj),		/* note: obj->quan == 1 */
257.  		body_part(HEAD));
258.  	    if(obj->oclass == POTION_CLASS)
259.  		potionhit(&youmonst, obj);
260.  	    else {
261.  	        int dmg = rnd((int)(obj->owt));
262.  	      
263.  		if (uarmh) {
264.  		    if(is_metallic(uarmh)) {
265.  		        pline("Fortunately, you are wearing a hard helmet.");
266.  			dmg = 1;
267.  		    } else if (flags.verbose)
268.  		        Your("%s does not protect you.", xname(uarmh));
269.  		} else if (obj->otyp == CORPSE &&
270.  				obj->corpsenm == PM_COCKATRICE) {
271.  #ifdef POLYSELF
272.  		    if(!resists_ston(uasmon))
273.  			if(!(poly_when_stoned(uasmon) &&
274.  					polymon(PM_STONE_GOLEM))) {
275.  #endif
276.  			killer = doname(obj);
277.  			You("turn to stone.");
278.  			do_death = STONING;
279.  #ifdef POLYSELF
280.  		    }
281.  #endif
282.  		}
283.  
284.  		if (!breaks(obj, TRUE)) {
285.  		    if(!ship_object(obj, u.ux, u.uy, FALSE)) {
286.  			dropy(obj);
287.  			if(*u.ushops)
288.  			    check_shop_obj(obj, obj->ox, obj->oy, FALSE);
289.  		    }
290.  		}
291.  		if (do_death == STONING)
292.  		    done(STONING);
293.  		else
294.  		    losehp(dmg, "falling object", KILLED_BY_AN);
295.  	    }
296.  	  } else hitfloor(obj);
297.  	  return(1);
298.  
299.  	} else if(obj->otyp == BOOMERANG && !Underwater) {
300.  		if(Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, 1);
301.  		mon = boomhit(u.dx, u.dy);
302.  		if(mon == &youmonst) {		/* the thing was caught */
303.  			exercise(A_DEX, TRUE);
304.  			(void) addinv(obj);
305.  			return(1);
306.  		}
307.  	} else {
308.  		urange = (int)(ACURRSTR)/2;
309.  		range = urange - (int)(obj->owt/40);
310.  		if (obj == uball) {
311.  			if (u.ustuck) range = 1;
312.  			else if (range >= 5) range = 5;
313.  		}
314.  		if (range < 1) range = 1;
315.  
316.  		if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
317.                      && uwep && objects[obj->otyp].w_propellor) {
318.  		    if (objects[obj->otyp].w_propellor ==
319.  			                     -objects[uwep->otyp].w_propellor)
320.  			range++;
321.  		    else
322.  			range /= 2;
323.  		}
324.  
325.  		if (Is_airlevel(&u.uz) || Levitation) {
326.  		    /* action, reaction... */
327.  		    urange -= range;
328.  		    if(urange < 1) urange = 1;
329.  		    range -= urange;
330.  		    if(range < 1) range = 1;
331.  		}
332.  
333.  #ifdef POLYSELF
334.  		if (obj->otyp == BOULDER) range = 20;
335.  #endif
336.  		if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
337.  		    range = 1;
338.  
339.  		if (Underwater) range = 1;
340.  
341.  		mon = bhit(u.dx,u.dy,range,THROWN_WEAPON,
342.  			   (int (*)()) 0,(int (*)()) 0,obj);
343.  
344.  		/* have to do this after bhit() so u.ux & u.uy are correct */
345.  		if(Is_airlevel(&u.uz) || Levitation)
346.  		    hurtle(-u.dx, -u.dy, urange);
347.  	}
348.  	if(mon) {
349.  		if(mon->isshk && (!inside_shop(u.ux, u.uy) ||
350.  		   !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops))) { 
351.  		    if(obj->otyp == PICK_AXE) {
352.  		        register struct obj *otmp;
353.  
354.  			/* check if the pick axe was caught through  */
355.  			/* a successful call to shkcatch() in bhit() */
356.  	                for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
357.  		             if (otmp == obj) return(1);
358.  		    }
359.  		    wakeup(mon);
360.  		    hot_pursuit(mon);
361.  		}
362.  		(void) snuff_candle(obj);
363.  		/* awake monster if sleeping */
364.  		wakeup(mon);
365.  		notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
366.  		if(thitmonst(mon, obj)) return(1);
367.  	}
368.  	if(!u.uswallow) {
369.  		/* the code following might become part of dropy() */
370.  		int obj_glyph = obj_to_glyph(obj);
371.  		boolean gone = FALSE;
372.  
373.  		if (obj->oartifact == ART_MJOLLNIR && pl_character[0] == 'V') {
374.  		    /* we must be wearing Gauntlets of Power to get here */
375.  		    int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
376.  
377.  		    tmp_at(DISP_FLASH, obj_glyph);
378.  		    while(x != u.ux || y != u.uy) {
379.  			tmp_at(x, y);
380.  			delay_output();
381.  			x -= u.dx; y -= u.dy;
382.  		    }
383.  		    tmp_at(DISP_END, 0);
384.  
385.  		    if(!impaired) {
386.  			pline("%s returns to your hand!", The(xname(obj)));
387.  			obj = addinv(obj);
388.  			setuwep(obj);
389.  			if(cansee(bhitpos.x, bhitpos.y))
390.  			    newsym(bhitpos.x,bhitpos.y);
391.  		    } else {
392.  			int dmg = rnd(4);
393.  			if (Blind)
394.  			    pline("%s hits your %s!",
395.  				  The(xname(obj)), body_part(ARM));
396.  			else
397.  			    pline("%s flies back toward you, hitting your %s!",
398.  				  The(xname(obj)), body_part(ARM));
399.  			(void) artifact_hit((struct monst *) 0, &youmonst,
400.  					    obj, &dmg, 0);
401.  			losehp(dmg, xname(obj), KILLED_BY);
402.  			if(ship_object(obj, u.ux, u.uy, FALSE)) 
403.  		            return (1);
404.  			dropy(obj);
405.  		    }
406.  		    return (1);
407.  		}
408.  		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && !u.uinwater &&
409.  		    obj->oclass == POTION_CLASS && rn2(2)) {
410.  		    if(distu(bhitpos.x, bhitpos.y) < 3 && rn2(5)) {
411.  			pline("The flask breaks, and you smell a peculiar odor...");
412.  			potionbreathe(obj);
413.  		    } else if(!Blind)
414.  			pline("The flask breaks.");
415.  		    else pline("Crash!");
416.  		    if(*u.ushops)
417.  		        check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
418.  		    obfree(obj, (struct obj *)0);
419.  		    gone = TRUE;
420.  		}
421.  		if (gone || (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
422.  			     breaks(obj, TRUE))) {
423.  		    tmp_at(DISP_FLASH, obj_glyph);
424.  		    tmp_at(bhitpos.x, bhitpos.y);
425.  		    delay_output();
426.  		    tmp_at(DISP_END, 0);
427.  		    return(1);
428.  		}
429.  		if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
430.  		if(obj->otyp == CRYSKNIFE)
431.  			obj->otyp = WORM_TOOTH;
432.  	        if(mon && mon->isshk && obj->otyp == PICK_AXE) {
433.  		        mpickobj(mon, obj);
434.  			if(*u.ushops)
435.  			    check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
436.  			return(1);
437.  		}
438.  		(void) snuff_candle(obj);
439.  		if(!mon && obj != uball) {
440.  		    if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
441.  		        return(1);
442.  		}
443.  		obj->nobj = fobj;
444.  		fobj = obj;
445.  		place_object(obj, bhitpos.x, bhitpos.y);
446.  		if(*u.ushops && obj != uball)
447.  		    check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
448.  		stackobj(obj);
449.  		if (obj == uball) drop_ball(bhitpos.x, bhitpos.y);
450.  		if(cansee(bhitpos.x, bhitpos.y)) newsym(bhitpos.x,bhitpos.y);
451.  	} else {
452.  		/* ball is not picked up by monster */
453.  		if (obj != uball) mpickobj(u.ustuck,obj);
454.  	}
455.  	return(1);
456.  }
457.  
458.  int
459.  thitmonst(mon, obj)
460.  register struct monst *mon;
461.  register struct obj   *obj;
462.  {
463.  	register int	tmp; /* Base chance to hit */
464.  	register int	disttmp; /* distance modifier */
465.  
466.  	/* Differences from melee weapons:
467.  	 *
468.  	 * Dex still gives a bonus, but strength does not.
469.  	 * Polymorphed players lacking attacks may still throw.
470.  	 * There's a base -1 to hit.
471.  	 * No bonuses for fleeing or stunned targets (they don't dodge
472.  	 *    melee blows as readily, but dodging arrows is hard anyway).
473.  	 * Not affected by traps, etc.
474.  	 * Certain items which don't in themselves do damage ignore tmp.
475.  	 * Distance and monster size affect chance to hit.
476.  	 */
477.  	tmp = -1 + Luck + find_mac(mon);
478.  #ifdef POLYSELF
479.  	if (u.umonnum >= 0) tmp += uasmon->mlevel;
480.  	else
481.  #endif
482.  		tmp += u.ulevel;
483.  	if(ACURR(A_DEX) < 4) tmp -= 3;
484.  	else if(ACURR(A_DEX) < 6) tmp -= 2;
485.  	else if(ACURR(A_DEX) < 8) tmp -= 1;
486.  	else if(ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
487.  
488.  	/* modify to-hit depending on distance; but keep it sane */
489.  	disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
490.  	if(disttmp < -4) disttmp = -4;
491.  	tmp += disttmp;
492.  
493.  	/* it's easier to hit a larger target */
494.  	if(bigmonst(mon->data)) tmp++;
495.  
496.  	if(mon->msleep) {
497.  		mon->msleep = 0;
498.  		tmp += 2;
499.  	}
500.  	if(!mon->mcanmove || !mon->data->mmove) {
501.  		tmp += 4;
502.  		if(!rn2(10)) {
503.  			mon->mcanmove = 1;
504.  			mon->mfrozen = 0;
505.  		}
506.  	}
507.  	if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
508.  	if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
509.  
510.  	if(obj->oclass == GEM_CLASS && mon->data->mlet == S_UNICORN) {
511.  		if (mon->mtame) {
512.  			pline("%s catches and drops %s.",
513.  				Monnam(mon), the(xname(obj)));
514.  			return(0);
515.  		} else {
516.  			pline("%s catches %s.", Monnam(mon), the(xname(obj)));
517.  			return(gem_accept(mon, obj));
518.  		}
519.  	}
520.  	if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
521.  	   obj->otyp == UNICORN_HORN || obj->oclass == GEM_CLASS) {
522.  		if(obj->otyp < DART || obj->oclass == GEM_CLASS) {
523.  		    if (!uwep ||
524.  			objects[obj->otyp].w_propellor !=
525.  			-objects[uwep->otyp].w_propellor) {
526.  			tmp -= 4;
527.  		    } else {
528.  			tmp += uwep->spe - uwep->oeroded;
529.  			/*
530.  			 * Elves and Samurais are highly trained w/bows,
531.  			 * especially their own special types of bow.
532.  			 * Polymorphing won't make you a bow expert.
533.  			 */
534.  			if ((pl_character[0] == 'E' || pl_character[0] == 'S')
535.  			     && -objects[uwep->otyp].w_propellor == WP_BOW)
536.  			    tmp++;
537.  			if (pl_character[0] == 'E' && uwep->otyp == ELVEN_BOW)
538.  			    tmp++;
539.  			if (pl_character[0] == 'S' && uwep->otyp == YUMI)
540.  			    tmp++;
541.  		    }
542.  		} else if(obj->otyp == BOOMERANG) tmp += 4;
543.  		tmp += obj->spe;
544.  		tmp += hitval(obj, mon->data);
545.  		if(tmp >= rnd(20)) {
546.  			if(hmon(mon,obj,1)){
547.  			  /* mon still alive */
548.  			  cutworm(mon, bhitpos.x, bhitpos.y, obj);
549.  			}
550.  			exercise(A_DEX, TRUE);
551.  			/* projectiles thrown disappear sometimes */
552.  			if((obj->otyp < BOOMERANG || obj->oclass == GEM_CLASS)
553.  								&& rn2(3)) {
554.  			        if(*u.ushops)
555.  		                     check_shop_obj(obj, bhitpos.x, 
556.  						           bhitpos.y, TRUE);
557.  				/* check bill; free */
558.  				obfree(obj, (struct obj *)0);
559.  				return(1);
560.  			}
561.  		} else miss(xname(obj), mon);
562.  	} else if(obj->otyp == HEAVY_IRON_BALL) {
563.  		if(obj != uball) tmp += 2;
564.  		exercise(A_STR, TRUE);
565.  		if(tmp >= rnd(20)) {
566.  			(void) hmon(mon,obj,1);
567.  			exercise(A_DEX, TRUE);
568.  		} else miss(xname(obj), mon);
569.  	} else if (obj->otyp == BOULDER) {
570.  		tmp += 6;  /* Likely to hit! */
571.  		exercise(A_STR, TRUE);
572.  		if(tmp >= rnd(20)) {
573.  			(void) hmon(mon,obj,1);
574.  			exercise(A_DEX, TRUE);
575.  		} else miss(xname(obj), mon);
576.  	} else if((obj->otyp == CREAM_PIE
577.  #ifdef POLYSELF
578.  			|| obj->otyp == BLINDING_VENOM
579.  #endif
580.  					) && ACURR(A_DEX) >= rnd(10)) {
581.  		(void) hmon(mon,obj,1); /* can't die from it */
582.  #ifdef POLYSELF
583.  	} else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
584.  		(void) hmon(mon,obj,1);
585.  #endif
586.  	} else if(obj->oclass == POTION_CLASS && ACURR(A_DEX) >= rnd(15)) {
587.  		potionhit(mon, obj);
588.  		return(1);
589.  	} else {
590.  		pline("%s misses %s.", The(xname(obj)), mon_nam(mon));
591.  		if(obj->oclass == FOOD_CLASS && is_domestic(mon->data))
592.  			if(tamedog(mon,obj)) return(1);
593.  	}
594.  	return(0);
595.  }
596.  
597.  static int
598.  gem_accept(mon, obj)
599.  register struct monst *mon;
600.  register struct obj *obj;
601.  {
602.  	char buf[BUFSZ];
603.  	boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
604.  	boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
605.  	int ret = 0;
606.  	static const char NEARDATA nogood[] = " is not interested in your junk.";
607.  	static const char NEARDATA acceptgift[] = " accepts your gift.";
608.  	static const char NEARDATA maybeluck[] = " hesitatingly";
609.  	static const char NEARDATA noluck[] = " graciously";
610.  	static const char NEARDATA addluck[] = " gratefully";
611.  
612.  	Strcpy(buf,Monnam(mon));
613.  
614.  	mon->mpeaceful = 1;
615.  
616.  	/* object properly identified */
617.  	if(obj->dknown && objects[obj->otyp].oc_name_known) {
618.  		if(is_gem) {
619.  			if(is_buddy) {
620.  				Strcat(buf,addluck);
621.  				change_luck(5);
622.  			} else {
623.  				Strcat(buf,maybeluck);
624.  				change_luck(rn2(7)-3);
625.  			}
626.  		} else {
627.  			Strcat(buf,nogood);
628.  			goto nopick;
629.  		}
630.  	/* making guesses */
631.  	} else if(obj->onamelth || objects[obj->otyp].oc_uname) {
632.  		if(is_gem) {
633.  			if(is_buddy) {
634.  				Strcat(buf,addluck);
635.  				change_luck(2);
636.  			} else {
637.  				Strcat(buf,maybeluck);
638.  				change_luck(rn2(3)-1);
639.  			}
640.  		} else {
641.  			Strcat(buf,nogood);
642.  			goto nopick;
643.  		}
644.  	/* value completely unknown to @ */
645.  	} else {
646.  		if(is_gem) {
647.  			if(is_buddy) {
648.  				Strcat(buf,addluck);
649.  				change_luck(1);
650.  			} else {
651.  				Strcat(buf,maybeluck);
652.  				change_luck(rn2(3)-1);
653.  			}
654.  		} else {
655.  			Strcat(buf,noluck);
656.  		}
657.  	}
658.   	Strcat(buf,acceptgift);
659.  	mpickobj(mon, obj);
660.  	if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
661.  	ret = 1;
662.  
663.  nopick:
664.  	if(!Blind) pline(buf);
665.  	rloc(mon);
666.  	return(ret);
667.  }
668.  
669.  /* returns 0 if object doesn't break	*/
670.  /* returns 1 if object broke 		*/
671.  int
672.  breaks(obj, loose)
673.  register struct obj   *obj;
674.  register boolean loose;		/* if not loose, obj is in fobj chain */
675.  {
676.  	switch(obj->otyp) {
677.  		case MIRROR:
678.  			change_luck(-2);	/* and fall through */
679.  		case CRYSTAL_BALL:
680.  #ifdef TOURIST
681.  		case EXPENSIVE_CAMERA:
682.  #endif
683.  			if(!Blind)
684.  			    pline("%s shatters into a thousand pieces!",
685.  				Doname2(obj));
686.  			else You("hear something shatter!");
687.  			break;
688.  		case EGG:
689.  			pline("Splat!");
690.  			break;
691.  		case CREAM_PIE:
692.  			pline("What a mess!");
693.  			break;
694.  		case ACID_VENOM:
695.  		case BLINDING_VENOM:
696.  			pline("Splash!");
697.  			break;
698.  		default:
699.  			return 0;
700.  	}
701.  
702.  	/* it is currently assumed that 'loose' is co-extensive
703.  	 * with 'thrown'.  if this changes, an explicit 'thrown'
704.  	 * arg must be added to breaks() to ensure proper 
705.  	 * treatment of shop objs.
706.  	 */
707.  	if(loose) {
708.  		newsym(obj->ox,obj->oy);
709.  		if(*u.ushops) 
710.  	            check_shop_obj(obj, obj->ox, obj->oy, TRUE);
711.  		obfree(obj, (struct obj *)0);
712.  	} else {
713.  	        /* it is assumed that the obj is a floor-object */ 
714.  	        register struct monst *shkp;
715.  	        boolean costly, insider;
716.  		long loss = 0L;
717.  
718.  #ifdef GCC_WARN
719.  		shkp = (struct monst *) 0;
720.  #endif
721.  
722.  		costly = (costly_spot(obj->ox, obj->oy) && 
723.  				   (shkp = shop_keeper(*in_rooms(obj->ox,
724.  				  obj->oy, SHOPBASE))) != (struct monst *)0);
725.  		insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
726.  			 *in_rooms(obj->ox, obj->oy, SHOPBASE) == *u.ushops);
727.  
728.  		if(costly)
729.  		    loss = stolen_value(obj, u.ux, u.uy, 
730.  				 (shkp && shkp->mpeaceful), FALSE);
731.  		if(loss && !insider)
732.  		    make_angry_shk(shkp, obj->ox, obj->oy);
733.  
734.  		delobj(obj);
735.  	}
736.  	return(1);
737.  }
738.  
739.  /*
740.   *  Note that the gold object is *not* attached to the fobj chain.
741.   */
742.  static int
743.  throw_gold(obj)
744.  struct obj *obj;
745.  {
746.  	int range, odx, ody;
747.  	long zorks = obj->quan;
748.  	register struct monst *mon;
749.  
750.  	if(u.uswallow) {
751.  		pline(is_animal(u.ustuck->data) ?
752.  			"%s in the %s's entrails." : "%s into %s.",
753.  			"The gold disappears", mon_nam(u.ustuck));
754.  		u.ustuck->mgold += zorks;
755.  		dealloc_obj(obj);
756.  		return(1);
757.  	}
758.  
759.  	if(u.dz) {
760.  	  	if(u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
761.  	pline("The gold hits the ceiling, then falls back on top of your %s.",
762.  		    body_part(HEAD));
763.  		    /* some self damage? */
764.  		    if(uarmh) pline("Fortunately, you are wearing a helmet!");
765.  		}
766.  		if(flooreffects(obj,u.ux,u.uy,"fall")) return(1);
767.  		if(u.dz > 0) pline("The gold hits the floor.");
768.  		obj->nobj = fobj;	/* add the gold to the object list */
769.  		fobj = obj;
770.  		place_object(obj,u.ux,u.uy);
771.                  if(*u.ushops) sellobj(obj, u.ux, u.uy);
772.  		stackobj(obj);
773.  		newsym(u.ux,u.uy);
774.  		return 1;
775.  	}
776.  
777.  	/* consistent with range for normal objects */
778.  	range = (int)((ACURRSTR)/2 - obj->owt/40);
779.  
780.  	/* see if the gold has a place to move into */
781.  	odx = u.ux + u.dx;
782.  	ody = u.uy + u.dy;
783.  	if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
784.  		bhitpos.x = u.ux;
785.  		bhitpos.y = u.uy;
786.  	} else {
787.  		mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
788.  			       (int (*)()) 0, (int (*)()) 0, obj);
789.  		if(mon) {
790.  		    if (ghitm(mon, obj))	/* was it caught? */
791.  			return 1;
792.  		} else {
793.  		    if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) 
794.  		        return 1;
795.  		}
796.  	}
797.  
798.  	if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
799.  	obj->nobj = fobj;	/* add the gold to the object list */
800.  	fobj = obj;
801.  	place_object(obj,bhitpos.x,bhitpos.y);
802.          if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
803.  	stackobj(obj);
804.  	newsym(bhitpos.x,bhitpos.y);
805.  	return(1);
806.  }
807.  
808.  /*dothrow.c*/
Advertisement