Source:NetHack 3.4.0/mthrowu.c
Jump to navigation
Jump to search
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)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 <obj>" 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 <obj>" 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*/