abstract
| - 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*/
|