Source:NetHack 3.0.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.0.0. To link to a particular line, write [[NetHack 3.0.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.0	88/10/22
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 gem_accept P((struct monst *, struct obj *));
10.   static int throw_gold P((struct obj *));
11.   static const char toss_objs[] = { '0', GOLD_SYM, '#', WEAPON_SYM, 0 };
12.   #ifdef WORM
13.   extern boolean notonhead;
14.   #endif
15.   
16.   int
17.   dothrow() {
18.   	register struct obj *obj;
19.   
20.   	obj = getobj(toss_objs, "throw");
21.   	/* it is also possible to throw food */
22.   	/* (or jewels, or iron balls... ) */
23.   
24.   	if(!obj || !getdir(1)) {       /* ask "in what direction?" */
25.   		if(obj && obj->olet == GOLD_SYM) u.ugold += OGOLD(obj);
26.   		return(0);
27.   	}
28.   
29.   	if(obj->olet == GOLD_SYM) return(throw_gold(obj));
30.   
31.   	if(!canletgo(obj,"throw"))
32.   		return(0);
33.   	if(obj->otyp == BOULDER
34.   #ifdef POLYSELF
35.   					&& !throws_rocks(uasmon)
36.   #endif
37.   								) {
38.   		pline("It's too heavy.");
39.   		return(1);
40.   	}
41.   	if(!u.dx && !u.dy && !u.dz) {
42.   		You("cannot throw an object at yourself.");
43.   		return(0);
44.   	}
45.   	u_wipe_engr(2);
46.   
47.   	if(obj == uwep) {
48.   	    if(welded(obj)) {
49.   		weldmsg(obj, FALSE);
50.   		return(1);
51.   	    }
52.   	    if(obj->quan > 1)
53.   		setuwep(splitobj(obj, 1));
54.   	    else {
55.   		setuwep((struct obj *)0);
56.   		if (uwep) return(1); /* unwielded, died, rewielded */
57.   	    }
58.   	}
59.   	else if(obj->quan > 1)
60.   		(void) splitobj(obj, 1);
61.   	freeinv(obj);
62.   	return(throwit(obj));
63.   }
64.   
65.   static void
66.   hitfloor(obj)
67.   register struct obj *obj;
68.   {
69.   #ifdef ALTARS
70.   	if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
71.   	else
72.   #endif
73.   		pline("%s hits the floor.", Doname2(obj));
74.   	if (breaks(obj, TRUE)) return;
75.   	else if(obj->olet == POTION_SYM) {
76.   		pline("The flask breaks, and you smell a peculiar odor...");
77.   		potionbreathe(obj);
78.   		obfree(obj, (struct obj *)0);
79.   	} else
80.   		dropy(obj);
81.   }
82.   
83.   int
84.   throwit(obj)
85.   register struct obj *obj;
86.   {
87.   	register struct monst *mon;
88.   	register int range;
89.   
90.   	if(u.uswallow) {
91.   		mon = u.ustuck;
92.   		bhitpos.x = mon->mx;
93.   		bhitpos.y = mon->my;
94.   	} else if(u.dz) {
95.   	  if(u.dz < 0) {
96.   	    pline("%s hits the ceiling, then falls back on top of your %s.",
97.   		Doname2(obj),		/* note: obj->quan == 1 */
98.   		body_part(HEAD));
99.   	    if(obj->olet == POTION_SYM)
100.  		potionhit(&youmonst, obj);
101.  	    else {
102.  		if(uarmh) pline("Fortunately, you are wearing a helmet!");
103.  		losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object");
104.  		if (!breaks(obj, TRUE)) dropy(obj);
105.  	    }
106.  	  } else hitfloor(obj);
107.  	  return(1);
108.  
109.  	} else if(obj->otyp == BOOMERANG) {
110.  		mon = boomhit(u.dx, u.dy);
111.  		if(mon == &youmonst) {		/* the thing was caught */
112.  			(void) addinv(obj);
113.  			return(1);
114.  		}
115.  	} else {
116.  		if(obj->otyp == PICK_AXE && shkcatch(obj))
117.  		    return(1);
118.  
119.  		range = (int)((ACURR(A_STR) > 18 ? 20 : ACURR(A_STR))/2 - obj->owt/4);
120.  		if (obj == uball) {
121.  			if (u.ustuck) range = 1;
122.  			else if (range >= 5) range = 5;
123.  		}
124.  		if (range < 1) range = 1;
125.  
126.  		if ((obj->olet == WEAPON_SYM || obj->olet == GEM_SYM) &&
127.  		    uwep &&
128.  		    objects[obj->otyp].w_propellor ==
129.  			-objects[uwep->otyp].w_propellor)
130.  				range++;
131.  #ifdef POLYSELF
132.  		if (obj->otyp == BOULDER) range = 20;
133.  #endif
134.  
135.  		mon = bhit(u.dx, u.dy, range, obj->olet,
136.  			(int (*)()) 0, (int (*)()) 0, obj);
137.  	}
138.  	if(mon) {
139.  		/* awake monster if sleeping */
140.  		wakeup(mon);
141.  #ifdef WORM
142.  		if(bhitpos.x != mon->mx || bhitpos.y != mon->my)
143.  			notonhead = TRUE;
144.  #endif
145.  		if(thitmonst(mon, obj)) return(1);
146.  	}
147.  	if(!u.uswallow)  {
148.  		char let = obj->olet;
149.  
150.  		/* the code following might become part of dropy() */
151.  		if (breaks(obj, TRUE)) {
152.  			tmp_at(-1, let);
153.  			tmp_at(-3, (int)AT_OBJ);
154.  			tmp_at(bhitpos.x, bhitpos.y);
155.  			tmp_at(-1, -1);
156.  			return(1);
157.  		}
158.  		if(flooreffects(obj,bhitpos.x,bhitpos.y)) return(1);
159.  #ifdef WORM
160.  		if(obj->otyp == CRYSKNIFE)
161.  			obj->otyp = WORM_TOOTH;
162.  #endif
163.  		obj->ox = bhitpos.x;
164.  		obj->oy = bhitpos.y;
165.  		obj->nobj = fobj;
166.  		fobj = obj;
167.  		levl[bhitpos.x][bhitpos.y].omask = 1;
168.  		if(obj->unpaid && costly_spot(bhitpos.x, bhitpos.y))
169.  			subfrombill(obj);
170.  		stackobj(obj);
171.  		if(obj == uball &&
172.  			(bhitpos.x != u.ux || bhitpos.y != u.uy)){
173.  			if(u.utrap){
174.  				if(u.utraptype == TT_PIT)
175.  					pline("The ball pulls you out of the pit!");
176.  				else if(u.utraptype == TT_WEB)  {
177.  					pline("The ball pulls you out of the web!");
178.  					pline("The web is destroyed!");
179.  					deltrap(t_at(u.ux,u.uy));
180.  				} else {
181.  				register long side =
182.  					rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
183.  				pline("The ball pulls you out of the bear trap.");
184.  				Your("%s %s is severely damaged.",
185.  					(side == LEFT_SIDE) ? "left" : "right",
186.  					body_part(LEG));
187.  				set_wounded_legs(side, 500+rn2(1000));
188.  				losehp(2, "thrown ball");
189.  				}
190.  				u.utrap = 0;
191.  			}
192.  			unsee();
193.  			u.ux = bhitpos.x - u.dx;
194.  			u.uy = bhitpos.y - u.dy;
195.  			movobj(uchain,u.ux,u.uy);
196.  			setsee();
197.  			spoteffects();
198.  		}
199.  		if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
200.  	}  else
201.  		mpickobj(u.ustuck,obj);
202.  	return(1);
203.  }
204.  
205.  int
206.  thitmonst(mon, obj)
207.  register struct monst *mon;
208.  register struct obj   *obj;
209.  {
210.  	register int	tmp; /* Base chance to hit */
211.  
212.  	/* Differences from melee weapons:
213.  	 *
214.  	 * Dex still gives a bonus, but strength does not.
215.  	 * Polymorphed players lacking attacks may still throw.
216.  	 * There's a base -2 to hit.
217.  	 * No bonuses for fleeing or stunned targets (they don't dodge
218.  	 *    melee blows as readily, but dodging arrows is hard anyway).
219.  	 * Not affected by traps, etc...
220.  	 * Certain items which don't in themselves do damage ignore tmp.
221.  	 */
222.  	tmp = -2 + Luck + mon->data->ac;
223.  #ifdef POLYSELF
224.  	if (u.umonnum >= 0) tmp += uasmon->mlevel;
225.  	else
226.  #endif
227.  		tmp += u.ulevel;
228.  	if(ACURR(A_DEX) < 4) tmp -= 3;
229.  	else if(ACURR(A_DEX) < 6) tmp -= 2;
230.  	else if(ACURR(A_DEX) < 8) tmp -= 1;
231.  	else if(ACURR(A_DEX) > 15) tmp += (ACURR(A_DEX) - 15);
232.  
233.  	if(mon->msleep) {
234.  		mon->msleep = 0;
235.  		tmp += 2;
236.  	}
237.  	if(mon->mfroz) {
238.  		tmp += 4;
239.  		if(!rn2(10)) mon->mfroz = 0;
240.  	}
241.  	if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
242.  	if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
243.  
244.  	if(obj->olet == GEM_SYM && mon->data->mlet == S_UNICORN) {
245.  		if (mon->mtame)
246.  			kludge("%s catches and drops the %s.",
247.  				Monnam(mon), xname(obj));
248.  		else {
249.  			kludge("%s catches the %s.", Monnam(mon), xname(obj));
250.  			gem_accept(mon, obj);
251.  		}
252.  		return(1);
253.  	}
254.  	if(obj->olet == WEAPON_SYM || obj->otyp == ROCK || obj->olet == GEM_SYM) {
255.  		if(obj->otyp < DART || obj->otyp == ROCK || obj->olet == GEM_SYM) {
256.  		    if (!uwep ||
257.  			objects[obj->otyp].w_propellor !=
258.  			-objects[uwep->otyp].w_propellor)
259.  			    tmp -= 4;
260.  		    else    tmp += uwep->spe;
261.  		} else if(obj->otyp == BOOMERANG) tmp += 4;
262.  		tmp += obj->spe;
263.  		if(tmp >= rnd(20)) {
264.  			if(hmon(mon,obj,1) == TRUE){
265.  			  /* mon still alive */
266.  #ifdef WORM
267.  			  cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
268.  #endif
269.  			} else mon = 0;
270.  			/* projectiles thrown disappear sometimes */
271.  			if((obj->otyp < BOOMERANG || obj->olet == GEM_SYM)
272.  								&& rn2(3)) {
273.  				/* check bill; free */
274.  				obfree(obj, (struct obj *)0);
275.  				return(1);
276.  			}
277.  		} else miss(xname(obj), mon);
278.  	} else if(obj->otyp == HEAVY_IRON_BALL) {
279.  		if(obj != uball) tmp += 2;
280.  		if(tmp >= rnd(20)) {
281.  			if(hmon(mon,obj,1) == FALSE)
282.  				mon = 0;	/* he died */
283.  		} else miss(xname(obj), mon);
284.  	} else if (obj->otyp == BOULDER) {
285.  		tmp += 6;  /* Likely to hit! */
286.  		if(tmp >= rnd(20)) {
287.  			if(hmon(mon,obj,1) == FALSE)
288.  				mon = 0;	/* he died */
289.  		} else miss(xname(obj), mon);
290.  	} else if((obj->otyp == CREAM_PIE
291.  #ifdef POLYSELF
292.  			|| obj->otyp == BLINDING_VENOM
293.  #endif
294.  					) && ACURR(A_DEX) >= rnd(10)) {
295.  		(void) hmon(mon,obj,1); /* can't die from it */
296.  #ifdef POLYSELF
297.  	} else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
298.  		if(hmon(mon,obj,1) == FALSE)
299.  			mon = 0;
300.  #endif
301.  	} else if(obj->olet == POTION_SYM && ACURR(A_DEX) >= rnd(15)) {
302.  		potionhit(mon, obj);
303.  		return(1);
304.  	} else {
305.  		pline("The %s misses %s.", xname(obj),
306.  			cansee(bhitpos.x,bhitpos.y) ? mon_nam(mon) : "it");
307.  		if(obj->olet == FOOD_SYM &&
308.  		  (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE))
309.  			if(tamedog(mon,obj)) return(1);
310.  	}
311.  	return(0);
312.  }
313.  
314.  static void
315.  gem_accept(mon, obj)
316.  register struct monst *mon;
317.  register struct obj *obj;
318.  {
319.  	char buf[BUFSZ];
320.  	static const char nogood[] = " is not interested in your junk.";
321.  	static const char maybeluck[] = " hesitatingly accepts your gift.";
322.  	static const char addluck[] = " graciously accepts your gift.";
323.  
324.  	Strcpy(buf,Monnam(mon));
325.  
326.  	mon->mpeaceful = 1;
327.  	if(obj->dknown && objects[obj->otyp].oc_name_known)  {
328.  		if(objects[obj->otyp].g_val > 0)  {
329.  		    if(mon->data == &mons[
330.  				((u.ualigntyp== U_CHAOTIC) ? PM_BLACK_UNICORN :
331.  				 (u.ualigntyp == U_LAWFUL) ? PM_WHITE_UNICORN
332.  						  : PM_GREY_UNICORN)]) {
333.  			    Strcat(buf, addluck);
334.  			    change_luck(5);
335.  		    } else {
336.  			    Strcat(buf, maybeluck);
337.  			    change_luck(rn2(7)-3);
338.  		    }
339.  		} else {
340.  		    Strcat(buf,nogood);
341.  		    goto nopick;
342.  		}
343.  	}  else  {  /* value unknown to @ */
344.  		change_luck(1);
345.  		Strcat(buf,addluck);
346.  	}
347.  	mpickobj(mon, obj);
348.  nopick:
349.  	if(!Blind) pline(buf);
350.  	rloc(mon);
351.  }
352.  
353.  /* returns 0 if object doesn't break	*/
354.  /* returns 1 if object broke 		*/
355.  int
356.  breaks(obj, loose)
357.  register struct obj   *obj;
358.  register boolean loose;		/* if not loose, obj is in fobj chain */
359.  {
360.  	switch(obj->otyp) {
361.  #ifdef MEDUSA
362.  		case MIRROR:
363.  			change_luck(-2);	/* and fall through */
364.  #endif
365.  		case EXPENSIVE_CAMERA:
366.  		case CRYSTAL_BALL:
367.  			if(!Blind)
368.  			    pline("%s shatters into a thousand pieces!",
369.  				Doname2(obj));
370.  			else You("hear something shatter!");
371.  			break;
372.  		case EGG:
373.  			pline("Splat!");
374.  			break;
375.  		case CREAM_PIE:
376.  			pline("What a mess!");
377.  			break;
378.  		case ACID_VENOM:
379.  		case BLINDING_VENOM:
380.  			pline("Splash!");
381.  			break;
382.  		default:
383.  			return 0;
384.  	}
385.  
386.  	if(loose) {
387.  		unpobj(obj);
388.  		obfree(obj, (struct obj *)0);
389.  	} else {
390.  		addtobill(obj, FALSE);
391.  		delobj(obj);
392.  	}
393.  	return(1);
394.  }
395.  
396.  static boolean 
397.  martial() 
398.  {
399.  	return((pl_character[0] == 'S' || pl_character[0] == 'P'));
400.  }
401.  
402.  static int
403.  throw_gold(obj)
404.  struct obj *obj;
405.  {
406.  	int range = 0, odx, ody;
407.  	long zorks = OGOLD(obj);
408.  	register struct monst *mon;
409.  
410.  	free((genericptr_t) obj);
411.  	if(zorks < 0) {
412.  		/* watch negative overflows a la drop() */
413.  		u.ugold += zorks;
414.  	pline("The LRS would be very interested to know you have that much.");
415.  		return(0);
416.  	}
417.  
418.  	if(u.uswallow) {
419.  		pline("The gold disappears in the %s's entrails.", 
420.  					mon_nam(u.ustuck));
421.  		u.ustuck->mgold += zorks;
422.  		return(1);
423.  	}
424.  
425.  	if(u.dz) {
426.  	  	if(u.dz < 0) {
427.  	    pline("The gold hits the ceiling, then falls back on top of your %s.",
428.  		    body_part(HEAD));
429.  		    /* some self damage? */
430.  		    if(uarmh) pline("Fortunately, you are wearing a helmet!");
431.  		} else pline("The gold hits the floor.");
432.  		bhitpos.x = u.ux; /* a msg is needed here */
433.  		bhitpos.y = u.uy;
434.  		goto skip;
435.  	}
436.  
437.  	range = rnd((int)ACURR(A_STR));
438.  	if(martial()) range = range + rnd(3);
439.  
440.  	/* see if the gold has a place to move into */
441.  	odx = u.ux + u.dx;
442.  	ody = u.uy + u.dy;
443.  	if(bad_kick_throw_pos(odx,ody)) {
444.  		bhitpos.x = u.ux;
445.  		bhitpos.y = u.uy;
446.  	} else {
447.  		if (mon = ghit(u.dx, u.dy, range))
448.  		    if (ghitm(mon, zorks))	/* was it caught? */
449.  			zorks = 0;
450.  	}
451.  skip:
452.  	if (zorks)	/* perhaps it was caught */
453.  	    mkgold(zorks, bhitpos.x, bhitpos.y);
454.  	if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
455.  	return(1);
456.  }