Source:NetHack 3.4.0/mthrowu.c

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

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

1.   /*	SCCS Id: @(#)mthrowu.c	3.4	2001/12/10	*/ 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 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.   STATIC_DCL 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.   STATIC_OVL 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.  	char onmbuf[BUFSZ], knmbuf[BUFSZ]; 45.   46.   	if (!name) { 47.  	    struct obj otmp; 48.  	    unsigned save_ocknown; 49.   50.   	    if (!obj) panic("thitu: name & obj both null?"); 51.  	    name = strcpy(onmbuf,  52.   			 (obj->quan > 1L) ? doname(obj) : mshot_xname(obj)); 53.  	    /* killer name should be more specific; however, exact info 54.  	       like blessed/cursed and rustproof make things too verbose */ 55.  	    otmp = *obj; 56.  	    save_ocknown = objects[otmp.otyp].oc_name_known; 57.  	    otmp.known = otmp.dknown = 1; 58.  	    otmp.bknown = otmp.rknown = otmp.greased = 0; 59.  	    /* "killed by poisoned " would be misleading 60.  	       since poison is not the cause of death */ 61.  	    otmp.opoisoned = 0; 62.  	    objects[otmp.otyp].oc_name_known = 1; 63.  	    knm = strcpy(knmbuf,  64.   			 (otmp.quan > 1L) ? doname(&otmp) : xname(&otmp)); 65.  	    objects[otmp.otyp].oc_name_known = save_ocknown; 66.  	} else { 67.  	    knm = name; 68.  	}  69.   	onm = (obj && obj_is_pname(obj)) ? the(name) : 70.  			    (obj && obj->quan > 1L) ? name : an(name); 71.  	is_acid = (obj && obj->otyp == ACID_VENOM); 72.   73.   	if(u.uac + tlev <= rnd(20)) { 74.  		if(Blind || !flags.verbose) pline("It misses."); 75.  		else You("are almost hit by %s.", onm); 76.  		return(0); 77.  	} else { 78.  		if(Blind || !flags.verbose) You("are hit!"); 79.  		else You("are hit by %s%s", onm, exclam(dam)); 80.   81.   		if (obj && objects[obj->otyp].oc_material == SILVER  82.   				&& hates_silver(youmonst.data)) { 83.  			dam += rnd(20); 84.  			pline_The("silver sears your flesh!"); 85.  			exercise(A_CON, FALSE); 86.  		}  87.   		if (is_acid && Acid_resistance) 88.  			pline("It doesn't seem to hurt you."); 89.  		else { 90.  			if (is_acid) pline("It burns!"); 91.  			if (Half_physical_damage) dam = (dam+1) / 2; 92.  			losehp(dam, knm, (obj && obj_is_pname(obj)) ?  93.   			       KILLED_BY : KILLED_BY_AN); 94.  			exercise(A_STR, FALSE); 95.  		}  96.   		return(1); 97.  	}  98.   }  99.    100.  /* Be sure this corresponds with what happens to player-thrown objects in  101. * dothrow.c (for consistency). --KAA 102.  * Returns 0 if object still exists (not destroyed). 103.  */  104.   105.  STATIC_OVL int 106. drop_throw(obj, ohit, x, y)  107. register struct obj *obj; 108. boolean ohit; 109. int x,y; 110. {  111.  	int retvalu = 1; 112. 	int create; 113. 	struct monst *mtmp; 114. 	struct trap *t; 115.  116.  	if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS ||  117.  		    (ohit && obj->otyp == EGG)) 118. 		create = 0; 119. 	else if (ohit && (is_multigen(obj) || obj->otyp == ROCK)) 120. 		create = !rn2(3); 121. 	else create = 1; 122.  123.  	if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && 124. 			(t = t_at(x, y)) && ((t->ttyp == PIT) ||  125.  			(t->ttyp == SPIKED_PIT)))) { 126. 		int objgone = 0; 127.  128.  		if (down_gate(x, y) != -1) 129. 			objgone = ship_object(obj, x, y, FALSE); 130. 		if (!objgone) { 131. 			if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */ 132. 			    place_object(obj, x, y); 133. 			    if (!mtmp && x == u.ux && y == u.uy) 134. 				mtmp = &youmonst; 135. 			    if (mtmp && ohit) 136. 				passive_obj(mtmp, obj, (struct attack *)0); 137. 			    stackobj(obj); 138. 			    retvalu = 0; 139. 			}  140.  		}  141.  	} else obfree(obj, (struct obj*) 0); 142. 	return retvalu; 143. }  144.   145.  #endif /* OVLB */ 146. #ifdef OVL1 147.  148.  /* an object launched by someone/thing other than player attacks a monster; 149.    return 1 if the object has stopped moving (hit or its range used up) */ 150. int 151. ohitmon(mtmp, otmp, range, verbose) 152. struct monst *mtmp;	/* accidental target */ 153. struct obj *otmp;	/* missile; might be destroyed by drop_throw */ 154. int range;		/* how much farther will object travel if it misses */ 155. 			/* Use -1 to signify to keep going even after hit, */ 156. 			/* unless its gone (used for rolling_boulder_traps) */ 157. boolean verbose;  /* give message(s) even when you can't see what happened */ 158. {  159.  	int damage, tmp; 160. 	boolean vis, ismimic; 161. 	int objgone = 1; 162.  163.  	ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER; 164. 	vis = cansee(bhitpos.x, bhitpos.y); 165.  166.  	tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); 167. 	if (tmp < rnd(20)) { 168. 	    if (!ismimic) { 169. 		if (vis) miss(distant_name(otmp, mshot_xname), mtmp); 170. 		else if (verbose) pline("It is missed."); 171. 	    }  172.  	    if (!range) { /* Last position; object drops */ 173. 		(void) drop_throw(otmp, 0, mtmp->mx, mtmp->my); 174. 		return 1; 175. 	    }  176.  	} else if (otmp->oclass == POTION_CLASS) { 177. 	    if (ismimic) seemimic(mtmp); 178. 	    mtmp->msleeping = 0; 179. 	    if (vis) otmp->dknown = 1; 180. 	    potionhit(mtmp, otmp, FALSE); 181. 	    return 1; 182. 	} else { 183. 	    damage = dmgval(otmp, mtmp); 184. 	    if (otmp->otyp == ACID_VENOM && resists_acid(mtmp)) 185. 		damage = 0; 186. 	    if (ismimic) seemimic(mtmp); 187. 	    mtmp->msleeping = 0; 188. 	    if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage)); 189. 	    else if (verbose) pline("It is hit%s", exclam(damage)); 190.  191.  	    if (otmp->opoisoned) { 192. 		if (resists_poison(mtmp)) { 193. 		    if (vis) pline_The("poison doesn't seem to affect %s.",  194.  				   mon_nam(mtmp)); 195. 		} else { 196. 		    if (rn2(30)) { 197. 			damage += rnd(6); 198. 		    } else { 199. 			if (vis) pline_The("poison was deadly..."); 200. 			damage = mtmp->mhp; 201. 		    }  202.  		}  203.  	    }  204.  	    if (objects[otmp->otyp].oc_material == SILVER &&  205.  		    hates_silver(mtmp->data)) { 206. 		if (vis) pline_The("silver sears %s flesh!",  207.  				s_suffix(mon_nam(mtmp))); 208. 		else if (verbose) pline("Its flesh is seared!"); 209. 	    }  210.  	    if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) { 211. 		if (resists_acid(mtmp)) { 212. 		    if (vis || verbose) 213. 			pline("%s is unaffected.", Monnam(mtmp)); 214. 		    damage = 0; 215. 		} else { 216. 		    if (vis) pline_The("acid burns %s!", mon_nam(mtmp)); 217. 		    else if (verbose) pline("It is burned!"); 218. 		}  219.  	    }  220.  	    mtmp->mhp -= damage; 221. 	    if (mtmp->mhp < 1) { 222. 		if (vis || verbose) 223. 		    pline("%s is %s!", Monnam(mtmp),  224.  			(nonliving(mtmp->data) || !vis)  225.  			? "destroyed" : "killed"); 226. 		if (!flags.mon_moving) xkilled(mtmp,0); 227. 		else mondied(mtmp); 228. 	    }  229.   230.  	    if (can_blnd((struct monst*)0, mtmp, 231. 		    (uchar)(otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP), 232. 		    otmp)) { 233. 		if (vis && mtmp->mcansee) 234. 		    pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp))); 235. 		mtmp->mcansee = 0; 236. 		tmp = (int)mtmp->mblinded + rnd(25) + 20; 237. 		if (tmp > 127) tmp = 127; 238. 		mtmp->mblinded = tmp; 239. 	    }  240.   241.  	    objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y); 242. 	    if (!objgone && range == -1) {  /* special case */ 243. 		    obj_extract_self(otmp); /* free it for motion again */ 244. 		    return 0; 245. 	    }  246.  	    return 1; 247. 	}  248.  	return 0; 249. }  250.   251.  void 252. m_throw(mon, x, y, dx, dy, range, obj) 253. 	register struct monst *mon; 254. 	register int x,y,dx,dy,range;		/* direction and range */ 255. 	register struct obj *obj; 256. {  257.  	register struct monst *mtmp; 258. 	struct obj *singleobj; 259. 	char sym = obj->oclass; 260. 	int hitu, blindinc = 0; 261.  262.  	bhitpos.x = x;  263. bhitpos.y = y; 264. 265. 	if (obj->quan == 1L) { 266. 	    /*  267.  	     * Remove object from minvent. This cannot be done later on; 268. 	     * what if the player dies before then, leaving the monster 269. 	     * with 0 daggers? (This caused the infamous 2^32-1 orcish 270.  	     * dagger bug). 271. 	     *  272.  	     * VENOM is not in minvent - it should already be OBJ_FREE. 273. 	     * The extract below does nothing. 274. 	     */  275.   276.  	    /* not possibly_unwield, which checks the object's */ 277. 	    /* location, not its existence */ 278. 	    if (MON_WEP(mon) == obj) { 279. 		    setmnotwielded(mon,obj); 280. 		    MON_NOWEP(mon); 281. 	    }  282.  	    obj_extract_self(obj); 283. 	    singleobj = obj; 284. 	    obj = (struct obj *) 0; 285. 	} else { 286. 	    singleobj = splitobj(obj, 1L); 287. 	    obj_extract_self(singleobj); 288. 	}  289.   290.  	singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */ 291.   292.  	if (singleobj->cursed && (dx || dy) && !rn2(7)) { 293. 	    if(canseemon(mon) && flags.verbose) { 294. 		if(is_ammo(singleobj)) 295. 		    pline("%s misfires!", Monnam(mon)); 296. 		else 297. 		    pline("%s as %s throws it!",  298.  			  Tobjnam(singleobj, "slip"), mon_nam(mon)); 299. 	    }  300.  	    dx = rn2(3)-1; 301. 	    dy = rn2(3)-1; 302. 	    /* pre-check validity of new direction */ 303. 	    if((!dx && !dy)  304.  	       || !isok(bhitpos.x+dx,bhitpos.y+dy)  305.  	       /* missile hits the wall */  306.  	       || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)) { 307. 		(void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 308. 		return; 309. 	    }  310.  	}  311.   312.  	/* Note: drop_throw may destroy singleobj. Since obj must be destroyed 313. 	 * early to avoid the dagger bug, anyone who modifies this code should 314. 	 * be careful not to use either one after it's been freed. 315. 	 */  316.  	if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); 317. 	while(range-- > 0) { /* Actually the loop is always exited by break */ 318. 		bhitpos.x += dx; 319. 		bhitpos.y += dy; 320. 		if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 321. 		    if (ohitmon(mtmp, singleobj, range, TRUE)) 322. 			break; 323. 		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 324. 		    if (multi) nomul(0); 325.  326.  		    if (singleobj->oclass == GEM_CLASS &&  327.  			    singleobj->otyp <= LAST_GEM+9 /* 9 glass colors */  328.  			    && is_unicorn(youmonst.data)) { 329. 			if (singleobj->otyp > LAST_GEM) { 330. 			    You("catch the %s.", xname(singleobj)); 331. 			    You("are not interested in %s junk.",  332.  				s_suffix(mon_nam(mon))); 333. 			    makeknown(singleobj->otyp); 334. 			    dropy(singleobj); 335. 			} else { 336. 			    You("accept %s gift in the spirit in which it was intended.",  337.  				s_suffix(mon_nam(mon))); 338. 			    (void)hold_another_object(singleobj,  339.  				"You catch, but drop, %s.", xname(singleobj),  340.  				"You catch:"); 341. 			}  342.  			break; 343. 		    }  344.  		    if (singleobj->oclass == POTION_CLASS) { 345. 			if (!Blind) singleobj->dknown = 1; 346. 			potionhit(&youmonst, singleobj, FALSE); 347. 			break; 348. 		    }  349.  		    switch(singleobj->otyp) { 350. 			int dam, hitv; 351. 			case EGG: 352. 			    if (!touch_petrifies(&mons[singleobj->corpsenm])) { 353. 				impossible("monster throwing egg type %d",  354.  					singleobj->corpsenm); 355. 				hitu = 0; 356. 				break; 357. 			    }  358.  			    /* fall through */ 359. 			case CREAM_PIE: 360. 			case BLINDING_VENOM: 361. 			    hitu = thitu(8, 0, singleobj, (char *)0); 362. 			    break; 363. 			default: 364. 			    dam = dmgval(singleobj, &youmonst); 365. 			    hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my); 366. 			    if (hitv < -4) hitv = -4; 367. 			    if (is_elf(mon->data) &&  368.  				objects[singleobj->otyp].oc_skill == P_BOW) { 369. 				hitv++; 370. 				if (MON_WEP(mon) &&  371.  				    MON_WEP(mon)->otyp == ELVEN_BOW) 372. 				    hitv++; 373. 				if(singleobj->otyp == ELVEN_ARROW) dam++; 374. 			    }  375.  			    if (bigmonst(youmonst.data)) hitv++; 376. 			    hitv += 8 + singleobj->spe; 377. 			    if (dam < 1) dam = 1; 378. 			    hitu = thitu(hitv, dam, singleobj, (char *)0); 379. 		    }  380.  		    if (hitu && singleobj->opoisoned) { 381. 			char onmbuf[BUFSZ], knmbuf[BUFSZ]; 382. 			struct obj otmp; 383. 			unsigned save_ocknown; 384.  385.  			/* [see thitu's handling of `name'] */ 386. 			Strcpy(onmbuf, xname(singleobj)); 387. 			otmp = *singleobj; 388. 			save_ocknown = objects[otmp.otyp].oc_name_known; 389. 			otmp.known = otmp.dknown = 1; 390. 			otmp.bknown = otmp.rknown = otmp.greased = 0; 391. 			/* "poisoned by poisoned " would be redundant */ 392. 			otmp.opoisoned = 0; 393. 			objects[otmp.otyp].oc_name_known = 1; 394. 			Strcpy(knmbuf, xname(&otmp)); 395. 			poisoned(onmbuf, A_STR, knmbuf, 10); 396. 			objects[otmp.otyp].oc_name_known = save_ocknown; 397. 		    }  398.  		    if(hitu &&  399.  		       can_blnd((struct monst*)0, &youmonst, 400. 				(uchar)(singleobj->otyp == BLINDING_VENOM ?  401.  					AT_SPIT : AT_WEAP), singleobj)) { 402. 			blindinc = rnd(25); 403. 			if(singleobj->otyp == CREAM_PIE) { 404. 			    if(!Blind) pline("Yecch!  You've been creamed."); 405. 			    else pline("There's %s sticky all over your %s.",  406.  				       something,  407.  				       body_part(FACE)); 408. 			} else if(singleobj->otyp == BLINDING_VENOM) { 409. 			    int num_eyes = eyecount(youmonst.data); 410. 			    /* venom in the eyes */ 411. 			    if(!Blind) pline_The("venom blinds you."); 412. 			    else Your("%s sting%s.",  413.  				      (num_eyes == 1) ? body_part(EYE) :  414.  						makeplural(body_part(EYE)),  415.  				      (num_eyes == 1) ? "s" : ""); 416. 			}  417.  		    }  418.  		    if (hitu && singleobj->otyp == EGG) { 419. 			if (!Stone_resistance  420.  			    && !(poly_when_stoned(youmonst.data) && 421. 				 polymon(PM_STONE_GOLEM))) { 422. 			    Stoned = 5; 423. 			    killer = (char *) 0; 424. 			}  425.  		    }  426.  		    stop_occupation; 427. 		    if (hitu || !range) { 428. 			(void) drop_throw(singleobj, hitu, u.ux, u.uy); 429. 			break; 430. 		    }  431.  		} else if (!range	/* reached end of path */  432.  			/* missile hits edge of screen */  433.  			|| !isok(bhitpos.x+dx,bhitpos.y+dy)  434.  			/* missile hits the wall */  435.  			|| IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)  436.  #ifdef SINKS  437.  			/* Thrown objects "sink" */  438.  			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)  439.  #endif  440.  								) { 441. 		    (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 442. 		    break; 443. 		}  444.  		tmp_at(bhitpos.x, bhitpos.y); 445. 		delay_output; 446. 	}  447.  	tmp_at(bhitpos.x, bhitpos.y); 448. 	delay_output; 449. 	tmp_at(DISP_END, 0); 450.  451.  	if (blindinc) { 452. 		u.ucreamed += blindinc; 453. 		make_blinded(Blinded + (long)blindinc, FALSE); 454. 		if (!Blind) Your(vision_clears); 455. 	}  456.  }  457.   458.  #endif /* OVL1 */ 459. #ifdef OVLB 460.  461.  /* Remove an item from the monster's inventory and destroy it. */ 462.  void 463. m_useup(mon, obj) 464. struct monst *mon; 465. struct obj *obj; 466. {  467.  	if (obj->quan > 1L) { 468. 		obj->quan--; 469. 		obj->owt = weight(obj); 470. 	} else { 471. 		obj_extract_self(obj); 472. 		possibly_unwield(mon); 473. 		if (obj->owornmask) { 474. 		    mon->misc_worn_check &= ~obj->owornmask; 475. 		    update_mon_intrinsics(mon, obj, FALSE); 476. 		}  477.  		obfree(obj, (struct obj*) 0); 478. 	}  479.  }  480.   481.  #endif /* OVLB */ 482. #ifdef OVL1 483.  484.  /* monster attempts ranged weapon attack against player */ 485. void 486. thrwmu(mtmp) 487. struct monst *mtmp; 488. {  489.  	struct obj *otmp, *mwep; 490. 	xchar x, y;  491. schar skill; 492. 	int multishot; 493. 	const char *onm; 494.  495.  	/* Rearranged beginning so monsters can use polearms not in a line */ 496. 	if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { 497. 	    mtmp->weapon_check = NEED_RANGED_WEAPON; 498. 	    /* mon_wield_item resets weapon_check as appropriate */ 499. 	    if(mon_wield_item(mtmp) != 0) return; 500. 	}  501.   502.  	/* Pick a weapon */ 503. 	otmp = select_rwep(mtmp); 504. 	if (!otmp) return; 505.  506.  	if (is_pole(otmp)) { 507. 	    int dam, hitv; 508.  509.  	    if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM ||  510.  		    !couldsee(mtmp->mx, mtmp->my)) 511. 		return;	/* Out of range, or intervening wall */ 512.  513.  	    if (canseemon(mtmp)) { 514. 		onm = xname(otmp); 515. 		pline("%s thrusts %s.", Monnam(mtmp),  516.  		      obj_is_pname(otmp) ? the(onm) : an(onm)); 517. 	    }  518.   519.  	    dam = dmgval(otmp, &youmonst); 520. 	    hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my); 521. 	    if (hitv < -4) hitv = -4; 522. 	    if (bigmonst(youmonst.data)) hitv++; 523. 	    hitv += 8 + otmp->spe; 524. 	    if (dam < 1) dam = 1; 525.  526.  	    (void) thitu(hitv, dam, otmp, (char *)0); 527. 	    stop_occupation; 528. 	    return; 529. 	}  530.   531.  	x = mtmp->mx; 532. 	y = mtmp->my; 533. 	/* If you are coming toward the monster, the monster 534. 	 * should try to soften you up with missiles. If you are 535. 	 * going away, you are probably hurt or running. Give 536. 	 * chase, but if you are getting too far away, throw. 537. 	 */  538.  	if (!lined_up(mtmp) ||  539.  		(URETREATING(x,y) && 540. 			rn2(BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy)))) 541. 	    return; 542.  543.  	skill = objects[otmp->otyp].oc_skill; 544. 	mwep = MON_WEP(mtmp);		/* wielded weapon */ 545.  546.  	/* Multishot calculations */ 547. 	multishot = 1; 548. 	if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER || 549. 		skill == -P_DART || skill == -P_SHURIKEN) && !mtmp->mconf) { 550. 	    /* Assumes lords are skilled, princes are expert */ 551. 	    if (is_prince(mtmp->data)) multishot += 2; 552. 	    else if (is_lord(mtmp->data)) multishot++; 553.  554.  	    switch (monsndx(mtmp->data)) { 555. 	    case PM_RANGER: 556. 		    multishot++; 557. 		    break; 558. 	    case PM_ROGUE: 559. 		    if (skill == P_DAGGER) multishot++; 560. 		    break; 561. 	    case PM_NINJA: 562. 	    case PM_SAMURAI: 563. 		    if (otmp->otyp == YA && mwep &&  564.  			mwep->otyp == YUMI) multishot++; 565. 		    break; 566. 	    default: 567. 		break; 568. 	    }  569.  	    /* racial bonus */ 570. 	    if ((is_elf(mtmp->data) && 571. 		    otmp->otyp == ELVEN_ARROW && 572. 		    mwep && mwep->otyp == ELVEN_BOW) ||  573.  		(is_orc(mtmp->data) && 574. 		    otmp->otyp == ORCISH_ARROW && 575. 		    mwep && mwep->otyp == ORCISH_BOW)) 576. 		multishot++; 577.  578.  	    if ((long)multishot > otmp->quan) multishot = (int)otmp->quan; 579. 	    if (multishot < 1) multishot = 1; 580. 	    else multishot = rnd(multishot); 581. 	}  582.   583.  	if (canseemon(mtmp)) { 584. 	    char onmbuf[BUFSZ]; 585.  586.  	    if (multishot > 1) { 587. 		/* "N arrows"; multishot > 1 implies otmp->quan > 1, so  588. xname's result will already be pluralized */ 589. 		Sprintf(onmbuf, "%d %s", multishot, xname(otmp)); 590. 		onm = onmbuf; 591. 	    } else { 592. 		/* "an arrow" */ 593. 		onm = singular(otmp, xname); 594. 		onm = obj_is_pname(otmp) ? the(onm) : an(onm); 595. 	    }  596.  	    m_shot.s = ammo_and_launcher(otmp,mwep) ? TRUE : FALSE; 597. 	    pline("%s %s %s!", Monnam(mtmp),  598.  		  m_shot.s ? "shoots" : "throws", onm); 599. 	    m_shot.o = otmp->otyp; 600. 	} else { 601. 	    m_shot.o = STRANGE_OBJECT;	/* don't give multishot feedback */ 602. 	}  603.   604.  	m_shot.n = multishot; 605. 	for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) 606. 	    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),  607.  		    distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp); 608. 	m_shot.n = m_shot.i = 0; 609. 	m_shot.o = STRANGE_OBJECT; 610. 	m_shot.s = FALSE; 611.  612.  	nomul(0); 613. }  614.   615.  #endif /* OVL1 */ 616. #ifdef OVLB 617.  618.  int 619. spitmu(mtmp, mattk)		/* monster spits substance at you */ 620. register struct monst *mtmp; 621. register struct attack *mattk; 622. {  623.  	register struct obj *otmp; 624.  625.  	if(mtmp->mcan) { 626.  627.  	    if(flags.soundok) 628. 		pline("A dry rattle comes from %s throat.",  629.  		                      s_suffix(mon_nam(mtmp))); 630. 	    return 0; 631. 	}  632.  	if(lined_up(mtmp)) { 633. 		switch (mattk->adtyp) { 634. 		    case AD_BLND: 635. 		    case AD_DRST: 636. 			otmp = mksobj(BLINDING_VENOM, TRUE, FALSE); 637. 			break; 638. 		    default: 639. 			impossible("bad attack type in spitmu"); 640. 				/* fall through */ 641. 		    case AD_ACID: 642. 			otmp = mksobj(ACID_VENOM, TRUE, FALSE); 643. 			break; 644. 		}  645.  		if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) { 646. 		    if (canseemon(mtmp)) 647. 			pline("%s spits venom!", Monnam(mtmp)); 648. 		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),  649.  			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp); 650. 		    nomul(0); 651. 		    return 0; 652. 		}  653.  	}  654.  	return 0; 655. }  656.   657.  #endif /* OVLB */ 658. #ifdef OVL1 659.  660.  int 661. breamu(mtmp, mattk)			/* monster breathes at you (ranged) */ 662. 	register struct monst *mtmp; 663. 	register struct attack  *mattk; 664. {  665.  	/* if new breath types are added, change AD_ACID to max type */ 666. 	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ; 667.  668.  	if(lined_up(mtmp)) { 669.  670.  	    if(mtmp->mcan) { 671. 		if(flags.soundok) { 672. 		    if(canseemon(mtmp)) 673. 			pline("%s coughs.", Monnam(mtmp)); 674. 		    else 675. 			You_hear("a cough."); 676. 		}  677.  		return(0); 678. 	    }  679.  	    if(!mtmp->mspec_used && rn2(3)) { 680.  681.  		if((typ >= AD_MAGM) && (typ <= AD_ACID)) { 682.  683.  		    if(canseemon(mtmp)) 684. 			pline("%s breathes %s!", Monnam(mtmp),  685.  			      breathwep[typ-1]); 686. 		    buzz((int) (-20 - (typ-1)), (int)mattk->damn,  687.  			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); 688. 		    nomul(0); 689. 		    /* breath runs out sometimes. Also, give monster some 690. 		     * cunning; don't breath if the player fell asleep. 691. 		     */  692.  		    if(!rn2(3)) 693. 			mtmp->mspec_used = 10+rn2(20); 694. 		    if(typ == AD_SLEE && !Sleep_resistance) 695. 			mtmp->mspec_used += rnd(20); 696. 		} else impossible("Breath weapon %d used", typ-1); 697. 	    }  698.  	}  699.  	return(1); 700. }  701.   702.  boolean 703. linedup(ax, ay, bx, by) 704. register xchar ax, ay, bx, by; 705. {  706.  	tbx = ax - bx;	/* These two values are set for use */ 707. 	tby = ay - by;	/* after successful return. */ 708.   709.  	/* sometimes displacement makes a monster think that you're at its 710. 	   own location; prevent it from throwing and zapping in that case */ 711. 	if (!tbx && !tby) return FALSE; 712.  713.  	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */  714.  	   && distmin(tbx, tby, 0, 0) < BOLT_LIM) { 715. 	    if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by))); 716. 	    else if(clear_path(ax,ay,bx,by)) return TRUE; 717. 	}  718.  	return FALSE; 719. }  720.   721.  boolean 722. lined_up(mtmp)		/* is mtmp in position to use ranged attack? */ 723.  	register struct monst *mtmp; 724. {  725.  	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); 726. }  727.   728.  #endif /* OVL1 */ 729. #ifdef OVL0 730.  731.  /* Check if a monster is carrying a particular item. 732.  */  733.  struct obj * 734. m_carrying(mtmp, type) 735. struct monst *mtmp; 736. int type; 737. {  738.  	register struct obj *otmp; 739.  740.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 741. 		if(otmp->otyp == type) 742. 			return(otmp); 743. 	return((struct obj *) 0); 744. }  745.   746.  #endif /* OVL0 */ 747.  748.  /*mthrowu.c*/