Source:SLASH'EM 0.0.7E7F2/mthrowu.c

Below is the full text to mthrowu.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/mthrowu.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

1.   /*	SCCS Id: @(#)mthrowu.c	3.4	2003/05/09	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   STATIC_DCL int FDECL(drop_throw,(struct monst *, struct obj *,BOOLEAN_P,int,int)); 8.    9.    #define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y)) 10.   11.   #define POLE_LIM 5	/* How far monsters can use pole-weapons */ 12.   13.   #ifndef OVLB 14.   15.   const char *breathwep[]; 16.   17.   #else /* OVLB */ 18.   19.   /*  20.    * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.  21. */ 22.   NEARDATA const char *breathwep[] = { 23.  				"fragments", 24.  				"fire", 25.  				"frost", 26.  				"sleep gas", 27.  				"a disintegration blast", 28.  				"lightning", 29.  				"poison gas", 30.  				"acid", 31.  				"strange breath #8", 32.  				"strange breath #9" 33.  };  34.    35.   /* hero is hit by something other than a monster */ 36.  int 37.  thitu(tlev, dam, obj, name) 38.  int tlev, dam; 39.  struct obj *obj; 40.  const char *name;	/* if null, then format `obj' */ 41.  {  42.   	const char *onm, *knm; 43.  	boolean is_acid; 44.  	int kprefix = KILLED_BY_AN; 45.  	char onmbuf[BUFSZ], knmbuf[BUFSZ]; 46.   47.   	if (!name) { 48.  	    if (!obj) panic("thitu: name & obj both null?"); 49.  	    name = strcpy(onmbuf,  50.   			 (obj->quan > 1L) ? doname(obj) : mshot_xname(obj)); 51.  	    knm = strcpy(knmbuf, killer_xname(obj)); 52.  	    kprefix = KILLED_BY;  /* killer_name supplies "an" if warranted */ 53.  	} else { 54.  	    knm = name; 55.  	    /* [perhaps ought to check for plural here to] */ 56.  	    if (!strncmpi(name, "the ", 4) ||  57.   		    !strncmpi(name, "an ", 3) ||  58.   		    !strncmpi(name, "a ", 2)) kprefix = KILLED_BY; 59.  	}  60.   	onm = (obj && obj_is_pname(obj)) ? the(name) : 61.  			    (obj && obj->quan > 1L) ? name : an(name); 62.  	is_acid = (obj && obj->otyp == ACID_VENOM); 63.   64.   	if(u.uac + tlev <= rnd(20)) { 65.  		if(Blind || !flags.verbose) pline("It misses."); 66.  		else You("are almost hit by %s.", onm); 67.  		return(0); 68.  	} else { 69.  		if(Blind || !flags.verbose) You("are hit!"); 70.  		else You("are hit by %s%s", onm, exclam(dam)); 71.   72.   		if (obj && objects[obj->otyp].oc_material == SILVER  73.   				&& hates_silver(youmonst.data)) { 74.  			dam += rnd(20); 75.  			pline_The("silver sears your flesh!"); 76.  			exercise(A_CON, FALSE); 77.  		}  78.   		if (is_acid && Acid_resistance) 79.  			pline("It doesn't seem to hurt you."); 80.  		else { 81.  			if (is_acid) pline("It burns!"); 82.  			if (Half_physical_damage) dam = (dam+1) / 2; 83.  			losehp(dam, knm, kprefix); 84.  			exercise(A_STR, FALSE); 85.  		}  86.   		return(1); 87.  	}  88.   }  89.    90.   /* Be sure this corresponds with what happens to player-thrown objects in  91. * dothrow.c (for consistency). --KAA 92.   * Returns 0 if object still exists (not destroyed). 93.   */  94.    95.   STATIC_OVL int 96.  drop_throw(mon, obj, ohit, x, y)  97. register struct monst *mon; 98.  register struct obj *obj; 99.  boolean ohit; 100. int x,y; 101. {  102.  	struct obj *mwep = (struct obj *) 0; 103. 	  104.  	int retvalu = 1; 105. 	int create; 106. 	struct monst *mtmp; 107. 	struct trap *t; 108.  109.  	if (mon) mwep = MON_WEP(mon); 110.  111.  	if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS ||  112.  /* WAC added Spoon throw code */  113.  # ifdef P_SPOON  114.                      (obj->oartifact == ART_HOUCHOU) ||  115.  # endif  116.  #ifdef FIREARMS  117.  		    /* WAC -- assume monsters don't throw without  118.  		    	using the right propellor */  119.                      (is_bullet(obj)) ||  120.  #endif  121.  		    (ohit && obj->otyp == EGG)) 122. 		create = 0; 123. 	else if (ohit && (is_multigen(obj) || obj->otyp == ROCK)) 124. 		create = !rn2(3); 125. 	else create = 1; 126.  127.  #ifdef FIREARMS 128. 	/* Detonate rockets */ 129. 	if (is_grenade(obj)) { 130. 		if (!ohit) { 131. 			create = 1; /* Don't destroy */ 132. 			arm_bomb(obj, FALSE); 133. 		} else { 134. 			grenade_explode(obj, bhitpos.x, bhitpos.y, FALSE, 0); 135. 			obj = (struct obj *)0; 136. 		}  137.  	} else if (objects[obj->otyp].oc_dir & EXPLOSION) { 138. 	    	if (cansee(bhitpos.x,bhitpos.y)) 139. 	    		pline("%s explodes in a ball of fire!", Doname2(obj)); 140. 	    	else You_hear("an explosion"); 141. 		explode(bhitpos.x, bhitpos.y, -ZT_SPELL(ZT_FIRE), d(3,8),  142.  		    WEAPON_CLASS, EXPL_FIERY); 143. 	}  144.  #endif 145.  146.  	/* D: Detonate crossbow bolts from Hellfire if they hit */ 147. 	if (ohit && mwep && mwep->oartifact == ART_HELLFIRE  148.  		  && is_ammo(obj) && ammo_and_launcher(obj, mwep)) { 149. 	   150.  		if (cansee(bhitpos.x,bhitpos.y)) 151. 			pline("%s explodes in a ball of fire!", Doname2(obj)); 152. 		else 153. 			You_hear("an explosion"); 154.  155.  		explode(bhitpos.x, bhitpos.y, -ZT_SPELL(ZT_FIRE),  156.  		    d(2,6), WEAPON_CLASS, EXPL_FIERY); 157.  158.  		/* D: Exploding bolts will be destroyed */ 159. 		create = 0; 160. 	}  161.   162.  	if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && 163. 			(t = t_at(x, y)) && ((t->ttyp == PIT) ||  164.  			(t->ttyp == SPIKED_PIT)))) { 165. 		int objgone = 0; 166.  167.  		if (down_gate(x, y) != -1) 168. 			objgone = ship_object(obj, x, y, FALSE); 169. 		if (!objgone) { 170. 			if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */ 171. 			    place_object(obj, x, y); 172. 			    if (!mtmp && x == u.ux && y == u.uy) 173. 				mtmp = &youmonst; 174. 			    if (mtmp && ohit) 175. 				passive_obj(mtmp, obj, (struct attack *)0); 176. 			    stackobj(obj); 177. 			    retvalu = 0; 178. 			}  179.  		}  180.  	} else if (obj) obfree(obj, (struct obj*) 0); 181.  182.  	return retvalu; 183. }  184.   185.  #endif /* OVLB */ 186. #ifdef OVL1 187.  188.  /* an object launched by someone/thing other than player attacks a monster; 189.    return 1 if the object has stopped moving (hit or its range used up) */ 190. int 191. ohitmon(mon, mtmp, otmp, range, verbose) 192. struct monst *mon;  /* monster thrower (if applicable) */ 193. struct monst *mtmp;	/* accidental target */ 194. struct obj *otmp;	/* missile; might be destroyed by drop_throw */ 195. int range;		/* how much farther will object travel if it misses */ 196. 			/* Use -1 to signify to keep going even after hit, */ 197. 			/* unless its gone (used for rolling_boulder_traps) */ 198. boolean verbose;  /* give message(s) even when you can't see what happened */ 199. {  200.  	int damage, tmp; 201. 	boolean vis, ismimic; 202. 	int objgone = 1; 203.  204.  	ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER; 205. 	vis = cansee(bhitpos.x, bhitpos.y); 206.  207.  	tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); 208. 	if (tmp < rnd(20)) { 209. 	    if (!ismimic) { 210. 		if (vis) miss(distant_name(otmp, mshot_xname), mtmp); 211. 		else if (verbose) pline("It is missed."); 212. 	    }  213.  	    if (!range) { /* Last position; object drops */ 214. 		(void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my); 215. 		return 1; 216. 	    }  217.  	} else if (otmp->oclass == POTION_CLASS) { 218. 	    if (ismimic) seemimic(mtmp); 219. 	    mtmp->msleeping = 0; 220. 	    if (vis) otmp->dknown = 1; 221. 	    potionhit(mtmp, otmp, FALSE); 222. 	    if (mon && !DEADMONSTER(mon) && !DEADMONSTER(mtmp) &&  223.  		    mtmp->movement >= NORMAL_SPEED && rn2(4)) { 224. 		/* retaliate */ 225. 		mtmp->movement -= NORMAL_SPEED; 226. 		mattackm(mtmp, mon); 227. 	    }  228.  	    return 1; 229. 	} else { 230. 	    damage = dmgval(otmp, mtmp); 231. # ifdef P_SPOON 232.             if (otmp->otyp == SPOON) { 233.             pline("The spoon flashes brightly as it hits %s.",  234.                     the(mon_nam(mtmp))); 235.             }  236.  # endif /* P_SPOON */ 237.  238.  	    if (otmp->otyp == ACID_VENOM && resists_acid(mtmp)) 239. 		damage = 0; 240. 	    if (ismimic) seemimic(mtmp); 241. 	    mtmp->msleeping = 0; 242. 	    if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage)); 243. 	    else if (verbose) pline("%s is hit%s", Monnam(mtmp), exclam(damage)); 244.  245.  	    if (otmp->opoisoned && is_poisonable(otmp)) { 246. 		if (resists_poison(mtmp)) { 247. 		    if (vis) pline_The("poison doesn't seem to affect %s.",  248.  				   mon_nam(mtmp)); 249. 		} else { 250. 		    if (rn2(30)) { 251. 			damage += rnd(6); 252. 		    } else { 253. 			if (vis) pline_The("poison was deadly..."); 254. 			damage = mtmp->mhp; 255. 		    }  256.  		}  257.  	    }  258.  	    if (objects[otmp->otyp].oc_material == SILVER &&  259.  		    hates_silver(mtmp->data)) { 260. 		if (vis) pline_The("silver sears %s flesh!",  261.  				s_suffix(mon_nam(mtmp))); 262. 		else if (verbose) pline("Its flesh is seared!"); 263. 	    }  264.  	    if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) { 265. 		if (resists_acid(mtmp)) { 266. 		    if (vis || verbose) 267. 			pline("%s is unaffected.", Monnam(mtmp)); 268. 		    damage = 0; 269. 		} else { 270. 		    if (vis) pline_The("acid burns %s!", mon_nam(mtmp)); 271. 		    else if (verbose) pline("It is burned!"); 272. 		}  273.  	    }  274.  	    mtmp->mhp -= damage; 275. 	    if (mtmp->mhp < 1) { 276. 		if (vis || verbose) 277. 		    pline("%s is %s!", Monnam(mtmp),  278.  			(nonliving(mtmp->data) || !canspotmon(mtmp))  279.  			? "destroyed" : "killed"); 280. 		/* don't blame hero for unknown rolling boulder trap */ 281. 		if (!flags.mon_moving &&  282.  		    (otmp->otyp != BOULDER || range >= 0 || !otmp->otrapped)) 283. 		    xkilled(mtmp,0); 284. 		else mondied(mtmp); 285. 	    }  286.   287.  	    if (can_blnd((struct monst*)0, mtmp, 288. 		    (uchar)(otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP), 289. 		    otmp)) { 290. 		if (vis && mtmp->mcansee) 291. 		    pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp))); 292. 		mtmp->mcansee = 0; 293. 		tmp = (int)mtmp->mblinded + rnd(25) + 20; 294. 		if (tmp > 127) tmp = 127; 295. 		mtmp->mblinded = tmp; 296. 	    }  297.   298.  	    if (mon && !DEADMONSTER(mon) && !DEADMONSTER(mtmp) &&  299.  		    mtmp->movement >= NORMAL_SPEED && rn2(4)) { 300. 		/* retaliate */ 301. 		mtmp->movement -= NORMAL_SPEED; 302. 		mattackm(mtmp, mon); 303. 	    }  304.   305.  	    objgone = drop_throw(mon, otmp, 1, bhitpos.x, bhitpos.y); 306. 	    if (!objgone && range == -1) {  /* special case */ 307. 		    obj_extract_self(otmp); /* free it for motion again */ 308. 		    return 0; 309. 	    }  310.  	    return 1; 311. 	}  312.  	return 0; 313. }  314.   315.  void 316. m_throw(mon, x, y, dx, dy, range, obj) 317. 	register struct monst *mon; 318. 	register int x,y,dx,dy,range;		/* direction and range */ 319. 	register struct obj *obj; 320. {  321.  	register struct monst *mtmp; 322. 	struct obj *singleobj, *mwep; 323. 	char sym = obj->oclass; 324. 	int hitu, blindinc = 0; 325.  326.  	bhitpos.x = x;  327. bhitpos.y = y; 328. 329. 	if (obj->quan == 1L) { 330. 	    /*  331.  	     * Remove object from minvent. This cannot be done later on; 332. 	     * what if the player dies before then, leaving the monster 333. 	     * with 0 daggers? (This caused the infamous 2^32-1 orcish 334.  	     * dagger bug). 335. 	     *  336.  	     * VENOM is not in minvent - it should already be OBJ_FREE. 337. 	     * The extract below does nothing. 338. 	     */  339.   340.  	    /* not possibly_unwield, which checks the object's */ 341. 	    /* location, not its existence */ 342. 	    if (MON_WEP(mon) == obj) { 343. 		    setmnotwielded(mon,obj); 344. 		    MON_NOWEP(mon); 345. 	    }  346.  	    obj_extract_self(obj); 347. 	    singleobj = obj; 348. 	    obj = (struct obj *) 0; 349. 	} else { 350. 	    singleobj = splitobj(obj, 1L); 351. 	    obj_extract_self(singleobj); 352. 	}  353.   354.  	singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */ 355.   356.  	if (mon) mwep = MON_WEP(mon); 357. 	else mwep = (struct obj *) 0; 358. 	  359.  	/* D: Special launcher effects */ 360. 	if (mwep && is_ammo(singleobj) && ammo_and_launcher(singleobj, mwep)) { 361. 	    if (mwep->oartifact == ART_PLAGUE && is_poisonable(singleobj)) 362. 			singleobj->opoisoned = 1; 363.  364.  	    /* D: Hellfire is handled in drop_throw */ 365. 	}  366.   367.  	if (singleobj->cursed && (dx || dy) && !rn2(7)) { 368. 	    if(canseemon(mon) && flags.verbose) { 369. 		if(is_ammo(singleobj)) 370. 		    pline("%s misfires!", Monnam(mon)); 371. 		else 372. 		    pline("%s as %s throws it!",  373.  			  Tobjnam(singleobj, "slip"), mon_nam(mon)); 374. 	    }  375.  	    dx = rn2(3)-1; 376. 	    dy = rn2(3)-1; 377. 	    /* check validity of new direction */ 378. 	    if (!dx && !dy) { 379. 		(void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y); 380. 		return; 381. 	    }  382.  	}  383.   384.  	/* pre-check for doors, walls and boundaries. 385. 	  Also need to pre-check for bars regardless of direction; 386. 	  the random chance for small objects hitting bars is  387. skipped when reaching them at point blank range */ 388. 	if (!isok(bhitpos.x+dx,bhitpos.y+dy)  389.  	    || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)  390.  	    || closed_door(bhitpos.x+dx, bhitpos.y+dy)  391.  	    || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS && 392. 	        hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) { 393. 	    (void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y); 394. 	    return; 395. 	}  396.   397.  	/* Note: drop_throw may destroy singleobj. Since obj must be destroyed 398. 	 * early to avoid the dagger bug, anyone who modifies this code should 399. 	 * be careful not to use either one after it's been freed. 400. 	 */  401.  	if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); 402. 	while(range-- > 0) { /* Actually the loop is always exited by break */ 403. 		bhitpos.x += dx; 404. 		bhitpos.y += dy; 405. 		if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 406. 		    if (ohitmon(mon, mtmp, singleobj, range, TRUE)) 407. 			break; 408. 		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 409. 		    if (multi) nomul(0); 410.  411.  		    if (singleobj->oclass == GEM_CLASS &&  412.  			    singleobj->otyp <= LAST_GEM+9 /* 9 glass colors */  413.  			    && is_unicorn(youmonst.data)) { 414. 			if (singleobj->otyp > LAST_GEM) { 415. 			    You("catch the %s.", xname(singleobj)); 416. 			    You("are not interested in %s junk.",  417.  				s_suffix(mon_nam(mon))); 418. 			    makeknown(singleobj->otyp); 419. 			    dropy(singleobj); 420. 			} else { 421. 			    You("accept %s gift in the spirit in which it was intended.",  422.  				s_suffix(mon_nam(mon))); 423. 			    (void)hold_another_object(singleobj,  424.  				"You catch, but drop, %s.", xname(singleobj),  425.  				"You catch:"); 426. 			}  427.  			break; 428. 		    }  429.  		    if (singleobj->oclass == POTION_CLASS) { 430. 			if (!Blind) singleobj->dknown = 1; 431. 			potionhit(&youmonst, singleobj, FALSE); 432. 			break; 433. 		    }  434.  		    switch(singleobj->otyp) { 435. 			int dam, hitv; 436. 			case EGG: 437. 			    if (!touch_petrifies(&mons[singleobj->corpsenm])) { 438. 				impossible("monster throwing egg type %d",  439.  					singleobj->corpsenm); 440. 				hitu = 0; 441. 				break; 442. 			    }  443.  			    /* fall through */ 444. 			case CREAM_PIE: 445. 			case BLINDING_VENOM: 446. 			    hitu = thitu(8, 0, singleobj, (char *)0); 447. 			    break; 448. 			default: 449. 			    dam = dmgval(singleobj, &youmonst); 450. 			    hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my); 451. 			    if (hitv < -4) hitv = -4; 452. 			    if (is_elf(mon->data) &&  453.  				objects[singleobj->otyp].oc_skill == P_BOW) { 454. 				hitv++; 455. 				if (MON_WEP(mon) &&  456.  				    MON_WEP(mon)->otyp == ELVEN_BOW) 457. 				    hitv++; 458. 				if(singleobj->otyp == ELVEN_ARROW) dam++; 459. 			    }  460.  			    if (bigmonst(youmonst.data)) hitv++; 461. 			    hitv += 8 + singleobj->spe; 462. 			    if (dam < 1) dam = 1; 463. 			    hitu = thitu(hitv, dam, singleobj, (char *)0); 464. 		    }  465.  		    if (hitu && singleobj->opoisoned &&  466.  			is_poisonable(singleobj)) { 467. 			char onmbuf[BUFSZ], knmbuf[BUFSZ]; 468.  469.  			Strcpy(onmbuf, xname(singleobj)); 470. 			Strcpy(knmbuf, killer_xname(singleobj)); 471. 			poisoned(onmbuf, A_STR, knmbuf, -10); 472. 		    }  473.  		    if(hitu &&  474.  		       can_blnd((struct monst*)0, &youmonst, 475. 				(uchar)(singleobj->otyp == BLINDING_VENOM ?  476.  					AT_SPIT : AT_WEAP), singleobj)) { 477. 			blindinc = rnd(25); 478. 			if(singleobj->otyp == CREAM_PIE) { 479. 			    if(!Blind) pline("Yecch!  You've been creamed."); 480. 			    else pline("There's %s sticky all over your %s.",  481.  				       something,  482.  				       body_part(FACE)); 483. 			} else if(singleobj->otyp == BLINDING_VENOM) { 484. 			    int num_eyes = eyecount(youmonst.data); 485. 			    /* venom in the eyes */ 486. 			    if(!Blind) pline_The("venom blinds you."); 487. 			    else Your("%s sting%s.",  488.  				      (num_eyes == 1) ? body_part(EYE) :  489.  						makeplural(body_part(EYE)),  490.  				      (num_eyes == 1) ? "s" : ""); 491. 			}  492.  		    }  493.  		    if (hitu && singleobj->otyp == EGG) { 494. 			if (!Stone_resistance  495.  			    && !(poly_when_stoned(youmonst.data) && 496. 				 polymon(PM_STONE_GOLEM))) { 497. 			    Stoned = 5; 498. 			    killer = (char *) 0; 499. 			}  500.  		    }  501.  		    stop_occupation; 502. 		    if (hitu || !range) { 503.                         (void) drop_throw(mon, singleobj, hitu, u.ux, u.uy); 504. 			break; 505. 		    }  506.  		}  507.  		if (!range	/* reached end of path */  508.  			/* missile hits edge of screen */  509.  			|| !isok(bhitpos.x+dx,bhitpos.y+dy)  510.  			/* missile hits the wall */  511.  			|| IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)  512.  			/* missile hit closed door */  513.  			|| closed_door(bhitpos.x+dx, bhitpos.y+dy)  514.  			/* missile might hit bars */  515.  			|| (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS && 516. 		        hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))  517.  #ifdef SINKS  518.  			/* Thrown objects "sink" */  519.  			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)  520.  #endif  521.  								) { 522. 		    if (singleobj) /* hits_bars might have destroyed it */ 523. 			(void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y); 524. 		    break; 525. 		}  526.  		tmp_at(bhitpos.x, bhitpos.y); 527. 		delay_output; 528. 	}  529.  	tmp_at(bhitpos.x, bhitpos.y); 530. 	delay_output; 531. 	tmp_at(DISP_END, 0); 532.  533.  	if (blindinc) { 534. 		u.ucreamed += blindinc; 535. 		make_blinded(Blinded + (long)blindinc, FALSE); 536. 		if (!Blind) Your(vision_clears); 537. 	}  538.  }  539.   540.  #endif /* OVL1 */ 541. #ifdef OVLB 542.  543.  /* Remove an item from the monster's inventory and destroy it. */ 544.  void 545. m_useup(mon, obj) 546. struct monst *mon; 547. struct obj *obj; 548. {  549.  	if (obj->quan > 1L) { 550. 		obj->quan--; 551. 		obj->owt = weight(obj); 552. 	} else { 553. 		obj_extract_self(obj); 554. 		possibly_unwield(mon, FALSE); 555. 		if (obj->owornmask) { 556. 		    mon->misc_worn_check &= ~(obj->owornmask); 557. 		    update_mon_intrinsics(mon, obj, FALSE, FALSE); 558. 		}  559.  		obfree(obj, (struct obj*) 0); 560. 	}  561.  }  562.   563.  #endif /* OVLB */ 564. #ifdef OVL1 565.  566.  /* monster attempts ranged weapon attack against player */ 567. void 568. thrwmu(mtmp) 569. struct monst *mtmp; 570. {  571.  	struct obj *otmp, *mwep; 572. 	xchar x, y;  573. schar skill; 574. 	int multishot; 575. 	const char *onm; 576. 	int chance; 577.  578.  	/* Rearranged beginning so monsters can use polearms not in a line */ 579. 	if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { 580. 	    mtmp->weapon_check = NEED_RANGED_WEAPON; 581. 	    /* mon_wield_item resets weapon_check as appropriate */ 582. 	    if(mon_wield_item(mtmp) != 0) return; 583. 	}  584.   585.  	/* Pick a weapon */ 586. 	otmp = select_rwep(mtmp); 587. 	if (!otmp) return; 588.  589.  	if ((MON_WEP(mtmp) == otmp) && is_pole(otmp)) { 590. 	    int dam, hitv; 591.  592.  	    if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM ||  593.  		    !couldsee(mtmp->mx, mtmp->my)) 594. 		return;	/* Out of range, or intervening wall */ 595.  596.  	    if (canseemon(mtmp)) { 597. 		onm = xname(otmp); 598. 		pline("%s thrusts %s.", Monnam(mtmp),  599.  		      obj_is_pname(otmp) ? the(onm) : an(onm)); 600. 	    }  601.   602.  	    dam = dmgval(otmp, &youmonst); 603. 	    hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my); 604. 	    if (hitv < -4) hitv = -4; 605. 	    if (bigmonst(youmonst.data)) hitv++; 606. 	    hitv += 8 + otmp->spe; 607. 	    if (dam < 1) dam = 1; 608.  609.  	    (void) thitu(hitv, dam, otmp, (char *)0); 610. 	    stop_occupation; 611. 	    return; 612. 	}  613.   614.  	x = mtmp->mx; 615. 	y = mtmp->my; 616. 	/* If you are coming toward the monster, the monster 617. 	 * should try to soften you up with missiles. If you are 618. 	 * going away, you are probably hurt or running. Give 619. 	 * chase, but if you are getting too far away, throw. 620. 	 */  621.  	/* WAC Catch this since rn2(0) is illegal */ 622. 	chance = (BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy) > 0) ? 623. 		BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy) : 1; 624. 	if (!lined_up(mtmp) || (URETREATING(x,y) && rn2(chance))) 625. 	    return; 626.  627.  	skill = objects[otmp->otyp].oc_skill; 628. 	mwep = MON_WEP(mtmp);		/* wielded weapon */ 629.  630.  	if (ammo_and_launcher(otmp, mwep) && objects[mwep->otyp].oc_range &&  631.  		dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) >  632.  		objects[mwep->otyp].oc_range * objects[mwep->otyp].oc_range) 633. 	    return; /* Out of range */ 634.  635.  	/* Multishot calculations */ 636. 	multishot = 1; 637. 	if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER || 638. 		skill == -P_DART || skill == -P_SHURIKEN) && !mtmp->mconf) { 639. 	    /* Assumes lords are skilled, princes are expert */ 640. 	    if (is_prince(mtmp->data)) multishot += 2; 641. 	    else if (is_lord(mtmp->data)) multishot++; 642.  643.  	    /*  Elven Craftsmanship makes for light,  quick bows */ 644. 	    if (otmp->otyp == ELVEN_ARROW && !otmp->cursed) 645. 		multishot++; 646. 	    if (mwep && mwep->otyp == ELVEN_BOW && !mwep->cursed) multishot++; 647. 	    /* 1/3 of object enchantment */ 648. 	    if (mwep && mwep->spe > 1) 649. 		multishot += rounddiv(mwep->spe, 3); 650. 	    /* Some randomness */ 651. 	    if (multishot > 1) 652. 		multishot = rnd(multishot); 653. #ifdef FIREARMS 654. 	    if (mwep && objects[mwep->otyp].oc_rof && is_launcher(mwep)) 655. 		multishot += objects[mwep->otyp].oc_rof; 656. #endif 657.  658.  	    switch (monsndx(mtmp->data)) { 659. 	    case PM_RANGER: 660. 		    multishot++; 661. 		    break; 662. 	    case PM_ROGUE: 663. 		    if (skill == P_DAGGER) multishot++; 664. 		    break; 665. 	    case PM_NINJA: 666. 	    case PM_SAMURAI: 667. 		    if (otmp->otyp == YA && mwep &&  668.  			mwep->otyp == YUMI) multishot++; 669. 		    break; 670. 	    default: 671. 		break; 672. 	    }  673.  	    /* racial bonus */ 674. 	    if ((is_elf(mtmp->data) && 675. 		    otmp->otyp == ELVEN_ARROW && 676. 		    mwep && mwep->otyp == ELVEN_BOW) ||  677.  		(is_orc(mtmp->data) && 678. 		    otmp->otyp == ORCISH_ARROW && 679. 		    mwep && mwep->otyp == ORCISH_BOW)) 680. 		multishot++; 681.  682.  	    if ((long)multishot > otmp->quan) multishot = (int)otmp->quan; 683. 	    if (multishot < 1) multishot = 1; 684. 	    /* else multishot = rnd(multishot); */ 685. 	}  686.   687.  	if (canseemon(mtmp)) { 688. 	    char onmbuf[BUFSZ]; 689.  690.  	    if (multishot > 1) { 691. 		/* "N arrows"; multishot > 1 implies otmp->quan > 1, so  692. xname's result will already be pluralized */ 693. 		Sprintf(onmbuf, "%d %s", multishot, xname(otmp)); 694. 		onm = onmbuf; 695. 	    } else { 696. 		/* "an arrow" */ 697. 		onm = singular(otmp, xname); 698. 		onm = obj_is_pname(otmp) ? the(onm) : an(onm); 699. 	    }  700.  	    m_shot.s = ammo_and_launcher(otmp,mwep) ? TRUE : FALSE; 701. 	    pline("%s %s %s!", Monnam(mtmp),  702.  #ifdef FIREARMS  703.  		  m_shot.s ? is_bullet(otmp) ? "fires" : "shoots" : "throws",  704.  		  onm); 705. #else 706. 		  m_shot.s ? "shoots" : "throws", onm); 707.  #endif  708.  	    m_shot.o = otmp->otyp;  709.  	} else {  710.  	    m_shot.o = STRANGE_OBJECT;	/* don't give multishot feedback */  711.  	}  712.   713.  	m_shot.n = multishot;  714.  	for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++)  715.  	    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 716. 		    distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);  717.  	m_shot.n = m_shot.i = 0;  718.  	m_shot.o = STRANGE_OBJECT;  719.  	m_shot.s = FALSE;  720.   721.  	nomul(0);  722.  }  723.   724.  #endif /* OVL1 */  725.  #ifdef OVLB  726.   727.  int  728.  spitmu(mtmp, mattk)		/* monster spits substance at you */  729.  register struct monst *mtmp;  730.  register struct attack *mattk;  731.  {  732.  	register struct obj *otmp;  733.   734.  	if(mtmp->mcan) {  735.   736.  	    if(flags.soundok)  737.  		pline("A dry rattle comes from %s throat.", 738. 		                      s_suffix(mon_nam(mtmp)));  739.  	    return 0;  740.  	}  741.  	if(lined_up(mtmp)) {  742.  		switch (mattk->adtyp) {  743.  		    case AD_BLND:  744.  		    case AD_DRST:  745.  			otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);  746.  			break;  747.  		    default:  748.  			impossible("bad attack type in spitmu");  749.  				/* fall through */  750.  		    case AD_ACID:  751.  			otmp = mksobj(ACID_VENOM, TRUE, FALSE);  752.  			break;  753.  		}  754.  		if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) {  755.  		    if (canseemon(mtmp))  756.  			pline("%s spits venom!", Monnam(mtmp));  757.  		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 758. 			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);  759.  		    nomul(0);  760.  		    return 0;  761.  		}  762.  	}  763.  	return 0;  764.  }  765.   766.  #endif /* OVLB */  767.  #ifdef OVL1  768.   769.  int  770.  breamu(mtmp, mattk)			/* monster breathes at you (ranged) */  771.  	register struct monst *mtmp;  772.  	register struct attack  *mattk;  773.  {  774.  	/* if new breath types are added, change AD_ACID to max type */  775.  	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;  776.   777.  	if(lined_up(mtmp)) {  778.   779.  	    if(mtmp->mcan) {  780.  		if(flags.soundok) {  781.  		    if(canseemon(mtmp))  782.  			pline("%s coughs.", Monnam(mtmp));  783.  		    else  784.  			You_hear("a cough.");  785.  		}  786.  		return(0);  787.  	    }  788.  	    if(!mtmp->mspec_used && rn2(3)) {  789.   790.  		if((typ >= AD_MAGM) && (typ <= AD_ACID)) { 791.  792.  		    if(canseemon(mtmp)) 793. 			pline("%s breathes %s!", Monnam(mtmp),  794.  			      breathwep[typ-1]); 795. 		    buzz((int) (-20 - (typ-1)), (int)mattk->damn,  796.  			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); 797. 		    nomul(0); 798. 		    /* breath runs out sometimes. Also, give monster some 799. 		     * cunning; don't breath if the player fell asleep. 800. 		     */  801.  		    if(!rn2(3)) 802. 			mtmp->mspec_used = 10+rn2(20); 803. 		    if(typ == AD_SLEE && !Sleep_resistance) 804. 			mtmp->mspec_used += rnd(20); 805. 		} else impossible("Breath weapon %d used", typ-1); 806. 	    }  807.  	}  808.  	return(1); 809. }  810.   811.   812.  /* WAC for doorbusting ONLY (at this point in time) No checks */ 813. boolean 814. breamspot(mtmp, mattk, ax, ay) 815. register struct monst *mtmp; 816. register struct attack  *mattk; 817. xchar ax, ay; 818. {  819.  	/* if new breath types are added, change AD_ACID to max type */ 820. 	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ; 821.  822.   823.  	if((typ >= AD_MAGM) && (typ <= AD_ACID)) { 824. 		if(canseemon(mtmp)) 825. 			pline("%s breathes %s!", Monnam(mtmp),  826.  				breathwep[typ-1]); 827. 		/* Do the door first - monster is ON TOP so call direct */ 828. 		zap_over_floor(mtmp->mx, mtmp->my, (int) (-20 - (typ-1)), NULL); 829. 		buzz((int) (-20 - (typ-1)), (int)mattk->damn,  830.  				mtmp->mx, mtmp->my, ax, ay); 831. 		nomul(0); 832. 		/* breath runs out sometimes. */ 833.  		if(!rn2(3)) 834. 			mtmp->mspec_used = 10+rn2(20); 835. 	} else impossible("Breath weapon %d used", typ-1); 836. 	return(TRUE); 837. }  838.   839.   840.  boolean 841. linedup(ax, ay, bx, by) 842. register xchar ax, ay, bx, by; 843. {  844.  	tbx = ax - bx;	/* These two values are set for use */ 845. 	tby = ay - by;	/* after successful return. */ 846.   847.  	/* sometimes displacement makes a monster think that you're at its 848. 	   own location; prevent it from throwing and zapping in that case */ 849. 	if (!tbx && !tby) return FALSE; 850.  851.  	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */  852.  	   && distmin(tbx, tby, 0, 0) < BOLT_LIM) { 853. 	    if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by))); 854. 	    else if(clear_path(ax,ay,bx,by)) return TRUE; 855. 	}  856.  	return FALSE; 857. }  858.   859.  boolean 860. lined_up(mtmp)		/* is mtmp in position to use ranged attack? */ 861.  	register struct monst *mtmp; 862. {  863.  	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); 864. }  865.   866.  #endif /* OVL1 */ 867. #ifdef OVL0 868.  869.  /* Check if a monster is carrying a particular item. 870.  */  871.  struct obj * 872. m_carrying(mtmp, type) 873. struct monst *mtmp; 874. int type; 875. {  876.  	register struct obj *otmp; 877.  878.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 879. 		if(otmp->otyp == type) 880. 			return(otmp); 881. 	return((struct obj *) 0); 882. }  883.   884.  /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */ 885. boolean 886. hits_bars(obj_p, x, y, always_hit, whodidit) 887. struct obj **obj_p;	/* *obj_p will be set to NULL if object breaks */ 888. int x, y;  889. int always_hit;	/* caller can force a hit for items which would fit through */ 890. int whodidit;	/* 1==hero, 0=other, -1==just check whether it'll pass thru */ 891. {  892.      struct obj *otmp = *obj_p; 893.     int obj_type = otmp->otyp; 894.     boolean hits = always_hit; 895.  896.      if (!hits) 897. 	switch (otmp->oclass) { 898. 	case WEAPON_CLASS: 899. 	    {  900.  		int oskill = objects[obj_type].oc_skill; 901.  902.  		hits = (oskill != -P_BOW  && oskill != -P_CROSSBOW &&  903.  			oskill != -P_DART && oskill != -P_SHURIKEN &&  904.  #ifdef FIREARMS  905.  			(oskill != -P_FIREARM || obj_type == ROCKET) &&  906.  #endif  907.  			oskill != P_SPEAR && oskill != P_JAVELIN &&  908.  			oskill != P_KNIFE);	/* but not dagger */ 909. 		break; 910. 	    }  911.  	case ARMOR_CLASS: 912. 		hits = (objects[obj_type].oc_armcat != ARM_GLOVES); 913. 		break; 914. 	case TOOL_CLASS: 915. 		hits = (obj_type != SKELETON_KEY &&  916.  			obj_type != LOCK_PICK &&  917.  #ifdef TOURIST  918.  			obj_type != CREDIT_CARD &&  919.  #endif  920.  			obj_type != TALLOW_CANDLE &&  921.  			obj_type != WAX_CANDLE &&  922.  			obj_type != LENSES &&  923.  			obj_type != TIN_WHISTLE &&  924.  			obj_type != MAGIC_WHISTLE); 925. 		break; 926. 	case ROCK_CLASS:	/* includes boulder */ 927. 		if (obj_type != STATUE ||  928.  			mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE; 929. 		break; 930. 	case FOOD_CLASS: 931. 		if (obj_type == CORPSE &&  932.  			mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE; 933. 		else 934. 		    hits = (obj_type == MEAT_STICK ||  935.  			    obj_type == HUGE_CHUNK_OF_MEAT); 936. 		break; 937. 	case SPBOOK_CLASS: 938. 	case WAND_CLASS: 939. 	case BALL_CLASS: 940. 	case CHAIN_CLASS: 941. 		hits = TRUE; 942. 		break; 943. 	default: 944. 		break; 945. 	}  946.   947.      if (hits && whodidit != -1) { 948. 	if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y)) 949. 	    *obj_p = otmp = 0;		/* object is now gone */ 950. 	    /* breakage makes its own noises */ 951. 	else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL) 952. 	    pline("Whang!"); 953. 	else if (otmp->oclass == COIN_CLASS ||  954.  		objects[obj_type].oc_material == GOLD ||  955.  		objects[obj_type].oc_material == SILVER) 956. 	    pline("Clink!"); 957. 	else 958. 	    pline("Clonk!"); 959.     }  960.   961.      return hits; 962. }  963.   964.  #endif /* OVL0 */ 965.  966.  /*mthrowu.c*/