Source:NetHack 3.0.0/dothrow.c

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

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. }