Source:NetHack 3.2.0/dothrow.c

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

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

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