abstract
| - Below is the full text to mhitm.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/mhitm.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)mhitm.c 3.2 96/04/08 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "artifact.h" 7. #include "edog.h" 8. 9. #ifdef OVLB 10. 11. static NEARDATA boolean vis, far_noise; 12. static NEARDATA long noisetime; 13. static NEARDATA struct obj *otmp; 14. 15. static const char brief_feeling[] = 16. "have a %s feeling for a moment, then it passes."; 17. 18. static void FDECL(mrustm, (struct monst *, struct monst *, struct obj *)); 19. static int FDECL(hitmm, (struct monst *,struct monst *,struct attack *)); 20. static int FDECL(gazemm, (struct monst *,struct monst *,struct attack *)); 21. static int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *)); 22. static int FDECL(explmm, (struct monst *,struct monst *,struct attack *)); 23. static int FDECL(mdamagem, (struct monst *,struct monst *,struct attack *)); 24. static void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *)); 25. static void FDECL(noises,(struct monst *,struct attack *)); 26. static void FDECL(missmm,(struct monst *,struct monst *,struct attack *)); 27. static int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int)); 28. 29. /* Needed for the special case of monsters wielding vorpal blades (rare). 30. * If we use this a lot it should probably be a parameter to mdamagem() 31. * instead of a global variable. 32. */ 33. static int dieroll; 34. 35. static void 36. noises(magr, mattk) 37. register struct monst *magr; 38. register struct attack *mattk; 39. { 40. boolean farq = (distu(magr->mx, magr->my) > 15); 41. 42. if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) { 43. far_noise = farq; 44. noisetime = moves; 45. You_hear("%s%s.", 46. (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises", 47. farq ? " in the distance" : ""); 48. } 49. } 50. 51. static 52. void 53. missmm(magr, mdef, mattk) 54. register struct monst *magr, *mdef; 55. struct attack *mattk; 56. { 57. const char *fmt; 58. char buf[BUFSZ]; 59. 60. if (vis) { 61. if (mdef->m_ap_type) seemimic(mdef); 62. if (magr->m_ap_type) seemimic(magr); 63. fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan) ? 64. "%s pretends to be friendly to" : "%s misses"; 65. Sprintf(buf, fmt, Monnam(magr)); 66. pline("%s %s.", buf, mon_nam(mdef)); 67. } else noises(magr, mattk); 68. } 69. 70. /* 71. * fightm() -- fight some other monster 72. * 73. * Returns: 74. * 0 - Monster did nothing. 75. * 1 - If the monster made an attack. The monster might have died. 76. * 77. * There is an exception to the above. If mtmp has the hero swallowed, 78. * then we report that the monster did nothing so it will continue to 79. * digest the hero. 80. */ 81. int 82. fightm(mtmp) /* have monsters fight each other */ 83. register struct monst *mtmp; 84. { 85. register struct monst *mon, *nmon; 86. int result, has_u_swallowed; 87. #ifdef LINT 88. nmon = 0; 89. #endif 90. /* perhaps the monster will resist Conflict */ 91. if(resist(mtmp, RING_CLASS, 0, 0)) 92. return(0); 93. 94. if(u.ustuck == mtmp) { 95. /* perhaps we're holding it... */ 96. if(itsstuck(mtmp)) 97. return(0); 98. } 99. has_u_swallowed = (u.uswallow && (mtmp == u.ustuck)); 100. 101. for(mon = fmon; mon; mon = nmon) { 102. nmon = mon->nmon; 103. if(nmon == mtmp) nmon = mtmp->nmon; 104. if(mon != mtmp) { 105. if(monnear(mtmp,mon->mx,mon->my)) { 106. if(!u.uswallow && (mtmp == u.ustuck)) { 107. if(!rn2(4)) { 108. pline("%s releases you!", Monnam(mtmp)); 109. u.ustuck = 0; 110. } else 111. break; 112. } 113. 114. /* mtmp can be killed */ 115. bhitpos.x = mon->mx; 116. bhitpos.y = mon->my; 117. result = mattackm(mtmp,mon); 118. 119. if (result & MM_AGR_DIED) return 1; /* mtmp died */ 120. /* 121. * If mtmp has the hero swallowed, lie and say there 122. * was no attack (this allows mtmp to digest the hero). 123. */ 124. if (has_u_swallowed) return 0; 125. 126. return ((result & MM_HIT) ? 1 : 0); 127. } 128. } 129. } 130. return 0; 131. } 132. 133. /* 134. * mattackm() -- a monster attacks another monster. 135. * 136. * This function returns a result bitfield: 137. * 138. * --------- agressor died 139. * / ------- defender died 140. * / / ----- defender was hit 141. * / / / 142. * x x x 143. * 144. * 0x4 MM_AGR_DIED 145. * 0x2 MM_DEF_DIED 146. * 0x1 MM_HIT 147. * 0x0 MM_MISS 148. * 149. * Each successive attack has a lower probability of hitting. Some rely on the 150. * success of previous attacks. ** this doen't seem to be implemented -dl ** 151. * 152. * In the case of exploding monsters, the monster dies as well. 153. */ 154. int 155. mattackm(magr, mdef) 156. register struct monst *magr,*mdef; 157. { 158. int i, /* loop counter */ 159. tmp, /* amour class difference */ 160. strike, /* hit this attack */ 161. attk, /* attack attempted this time */ 162. struck = 0, /* hit at least once */ 163. res[NATTK]; /* results of all attacks */ 164. struct attack *mattk; 165. struct permonst *pa, *pd; 166. 167. if (!magr || !mdef) return(MM_MISS); /* mike@genat */ 168. if (!magr->mcanmove) return(MM_MISS); /* riv05!a3 */ 169. pa = magr->data; pd = mdef->data; 170. 171. /* Grid bugs cannot attack at an angle. */ 172. if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx 173. && magr->my != mdef->my) 174. return(MM_MISS); 175. 176. /* Calculate the armour class differential. */ 177. tmp = find_mac(mdef) + magr->m_lev; 178. if (mdef->mconf || !mdef->mcanmove || mdef->msleep){ 179. tmp += 4; 180. if (mdef->msleep) mdef->msleep = 0; 181. } 182. 183. /* undetect monsters become un-hidden if they are attacked */ 184. if (mdef->mundetected) { 185. mdef->mundetected = 0; 186. newsym(mdef->mx, mdef->my); 187. if(canseemon(mdef) && !sensemon(mdef)) 188. pline("Suddenly, you notice %s.", a_monnam(mdef)); 189. } 190. 191. /* Elves hate orcs. */ 192. if (is_elf(pa) && is_orc(pd)) tmp++; 193. 194. 195. /* Set up the visibility of action */ 196. vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); 197. 198. /* Set flag indicating monster has moved this turn. Necessary since a 199. * monster might get an attack out of sequence (i.e. before its move) in 200. * some cases, in which case this still counts as its move for the round 201. * and it shouldn't move again. 202. */ 203. magr->mlstmv = monstermoves; 204. 205. /* Now perform all attacks for the monster. */ 206. for (i = 0; i < NATTK; i++) { 207. res[i] = MM_MISS; 208. mattk = &(pa->mattk[i]); 209. otmp = (struct obj *)0; 210. attk = 1; 211. switch (mattk->aatyp) { 212. case AT_WEAP: /* "hand to hand" attacks */ 213. if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) { 214. magr->weapon_check = NEED_HTH_WEAPON; 215. if (mon_wield_item(magr) != 0) return 0; 216. } 217. possibly_unwield(magr); 218. otmp = MON_WEP(magr); 219. 220. if (otmp) { 221. if (vis) mswingsm(magr, mdef, otmp); 222. tmp += hitval(otmp, mdef); 223. } 224. /* fall through */ 225. case AT_CLAW: 226. case AT_KICK: 227. case AT_BITE: 228. case AT_STNG: 229. case AT_TUCH: 230. case AT_BUTT: 231. case AT_TENT: 232. dieroll = rnd(20 + i); 233. strike = (tmp > dieroll); 234. if (strike) 235. res[i] = hitmm(magr, mdef, mattk); 236. else 237. missmm(magr, mdef, mattk); 238. break; 239. 240. case AT_HUGS: /* automatic if prev two attacks succeed */ 241. strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT); 242. if (strike) 243. res[i] = hitmm(magr, mdef, mattk); 244. 245. break; 246. 247. case AT_GAZE: 248. strike = 0; /* will not wake up a sleeper */ 249. res[i] = gazemm(magr, mdef, mattk); 250. break; 251. 252. case AT_EXPL: 253. strike = 1; /* automatic hit */ 254. res[i] = explmm(magr, mdef, mattk); 255. break; 256. 257. case AT_ENGL: 258. /* Engulfing attacks are directed at the hero if 259. * possible. -dlc 260. */ 261. if (u.uswallow && magr == u.ustuck) 262. strike = 0; 263. else { 264. if ((strike = (tmp > rnd(20+i)))) 265. res[i] = gulpmm(magr, mdef, mattk); 266. else 267. missmm(magr, mdef, mattk); 268. } 269. break; 270. 271. default: /* no attack */ 272. strike = 0; 273. attk = 0; 274. break; 275. } 276. 277. if (attk && !(res[i] & MM_AGR_DIED)) 278. res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED); 279. 280. if (res[i] & MM_DEF_DIED) return res[i]; 281. 282. /* 283. * Wake up the defender. NOTE: this must follow the check 284. * to see if the defender died. We don't want to modify 285. * unallocated monsters! 286. */ 287. if (strike) mdef->msleep = 0; 288. 289. if (res[i] & MM_AGR_DIED) return res[i]; 290. /* return if aggressor can no longer attack */ 291. if (!magr->mcanmove || magr->msleep) return res[i]; 292. if (res[i] & MM_HIT) struck = 1; /* at least one hit */ 293. } 294. 295. return(struck ? MM_HIT : MM_MISS); 296. } 297. 298. /* Returns the result of mdamagem(). */ 299. static int 300. hitmm(magr, mdef, mattk) 301. register struct monst *magr,*mdef; 302. struct attack *mattk; 303. { 304. if(vis){ 305. int compat; 306. char buf[BUFSZ]; 307. 308. if(mdef->m_ap_type) seemimic(mdef); 309. if(magr->m_ap_type) seemimic(magr); 310. if((compat = could_seduce(magr,mdef,mattk)) && !magr->mcan) { 311. Sprintf(buf, "%s %s", Monnam(magr), 312. mdef->mcansee ? "smiles at" : "talks to"); 313. pline("%s %s %s.", buf, mon_nam(mdef), 314. compat == 2 ? 315. "engagingly" : "seductively"); 316. } else { 317. char magr_name[BUFSZ]; 318. 319. Strcpy(magr_name, Monnam(magr)); 320. switch (mattk->aatyp) { 321. case AT_BITE: 322. Sprintf(buf,"%s bites", magr_name); 323. break; 324. case AT_STNG: 325. Sprintf(buf,"%s stings", magr_name); 326. break; 327. case AT_BUTT: 328. Sprintf(buf,"%s butts", magr_name); 329. break; 330. case AT_TUCH: 331. Sprintf(buf,"%s touches", magr_name); 332. break; 333. case AT_TENT: 334. Sprintf(buf, "%s tentacles suck", 335. s_suffix(magr_name)); 336. break; 337. case AT_HUGS: 338. if (magr != u.ustuck) { 339. Sprintf(buf,"%s squeezes", magr_name); 340. break; 341. } 342. default: 343. Sprintf(buf,"%s hits", magr_name); 344. } 345. } 346. pline("%s %s.", buf, mon_nam(mdef)); 347. } else noises(magr, mattk); 348. return(mdamagem(magr, mdef, mattk)); 349. } 350. 351. /* Returns the same values as mdamagem(). */ 352. static int 353. gazemm(magr, mdef, mattk) 354. register struct monst *magr, *mdef; 355. struct attack *mattk; 356. { 357. char buf[BUFSZ]; 358. 359. if(vis) { 360. Sprintf(buf,"%s gazes at", Monnam(magr)); 361. pline("%s %s...", buf, mon_nam(mdef)); 362. } 363. 364. if (!mdef->mcansee || mdef->msleep) { 365. if(vis) pline("but nothing happens."); 366. return(MM_MISS); 367. } 368. 369. return(mdamagem(magr, mdef, mattk)); 370. } 371. 372. /* Returns the same values as mattackm(). */ 373. static int 374. gulpmm(magr, mdef, mattk) 375. register struct monst *magr, *mdef; 376. register struct attack *mattk; 377. { 378. xchar ax, ay, dx, dy; 379. int status; 380. char buf[BUFSZ]; 381. struct obj *obj; 382. 383. if (mdef->data->msize >= MZ_HUGE) return MM_MISS; 384. 385. if (vis) { 386. Sprintf(buf,"%s swallows", Monnam(magr)); 387. pline("%s %s.", buf, mon_nam(mdef)); 388. } 389. for (obj = mdef->minvent; obj; obj = obj->nobj) 390. (void) snuff_lit(obj); 391. 392. /* 393. * All of this maniuplation is needed to keep the display correct. 394. * There is a flush at the next pline(). 395. */ 396. ax = magr->mx; 397. ay = magr->my; 398. dx = mdef->mx; 399. dy = mdef->my; 400. /* 401. * Leave the defender in the monster chain at it's current position, 402. * but don't leave it on the screen. Move the agressor to the def- 403. * ender's position. 404. */ 405. remove_monster(ax, ay); 406. place_monster(magr, dx, dy); 407. newsym(ax,ay); /* erase old position */ 408. newsym(dx,dy); /* update new position */ 409. 410. status = mdamagem(magr, mdef, mattk); 411. 412. if ((status & MM_AGR_DIED) && (status & MM_DEF_DIED)) { 413. ; /* both died -- do nothing */ 414. } 415. else if (status & MM_DEF_DIED) { /* defender died */ 416. /* 417. * Note: remove_monster() was called in relmon(), wiping out 418. * magr from level.monsters[mdef->mx][mdef->my]. We need to 419. * put it back and display it. -kd 420. */ 421. place_monster(magr, dx, dy); 422. newsym(dx, dy); 423. } 424. else if (status & MM_AGR_DIED) { /* agressor died */ 425. place_monster(mdef, dx, dy); 426. newsym(dx, dy); 427. } 428. else { /* both alive, put them back */ 429. if (cansee(dx, dy)) 430. pline("%s is regurgitated!", Monnam(mdef)); 431. 432. place_monster(magr, ax, ay); 433. place_monster(mdef, dx, dy); 434. newsym(ax, ay); 435. newsym(dx, dy); 436. } 437. 438. return status; 439. } 440. 441. static int 442. explmm(magr, mdef, mattk) 443. register struct monst *magr, *mdef; 444. register struct attack *mattk; 445. { 446. int result; 447. 448. if(cansee(magr->mx, magr->my)) 449. pline("%s explodes!", Monnam(magr)); 450. else noises(magr, mattk); 451. 452. result = mdamagem(magr, mdef, mattk); 453. 454. /* Kill off agressor if it didn't die. */ 455. if (!(result & MM_AGR_DIED)) { 456. mondead(magr); 457. if (magr->mhp > 0) return result; /* life saved */ 458. result |= MM_AGR_DIED; 459. } 460. if (magr->mtame) /* give this one even if it was visible */ 461. You(brief_feeling, "melancholy"); 462. 463. return result; 464. } 465. 466. /* 467. * See comment at top of mattackm(), for return values. 468. */ 469. static int 470. mdamagem(magr, mdef, mattk) 471. register struct monst *magr, *mdef; 472. register struct attack *mattk; 473. { 474. struct permonst *pa = magr->data, *pd = mdef->data; 475. int tmp = d((int)mattk->damn,(int)mattk->damd); 476. char buf[BUFSZ]; 477. 478. if (pd == &mons[PM_COCKATRICE] && !resists_ston(magr) && 479. (mattk->aatyp != AT_WEAP || !otmp) && 480. (mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL) && 481. !(magr->misc_worn_check & W_ARMG)) { 482. if (poly_when_stoned(pa)) { 483. mon_to_stone(magr); 484. return MM_HIT; /* no damage during the polymorph */ 485. } 486. if (vis) pline("%s turns to stone!", Monnam(magr)); 487. monstone(magr); 488. if (magr->mhp > 0) return 0; 489. else if (magr->mtame && !vis) 490. You(brief_feeling, "peculiarly sad"); 491. return MM_AGR_DIED; 492. } 493. 494. switch(mattk->adtyp) { 495. case AD_DGST: 496. /* eating a Rider or its corpse is fatal */ 497. if (is_rider(mdef->data)) { 498. if (vis) 499. pline("%s %s!", Monnam(magr), 500. mdef->data == &mons[PM_FAMINE] ? 501. "belches feebly, shrivels up and dies" : 502. mdef->data == &mons[PM_PESTILENCE] ? 503. "coughs spasmodically and collapses" : 504. "vomits violently and drops dead"); 505. mondied(magr); 506. if (magr->mhp > 0) return 0; /* lifesaved */ 507. else if (magr->mtame && !vis) 508. You(brief_feeling, "queasy"); 509. return MM_AGR_DIED; 510. } 511. if(flags.verbose && flags.soundok) verbalize("Burrrrp!"); 512. tmp = mdef->mhp; 513. break; 514. case AD_STUN: 515. if (magr->mcan) break; 516. if(vis) pline("%s staggers for a moment.", Monnam(mdef)); 517. mdef->mstun = 1; 518. /* fall through */ 519. case AD_WERE: 520. case AD_HEAL: 521. case AD_LEGS: 522. case AD_PHYS: 523. if (mattk->aatyp == AT_KICK && thick_skinned(pd)) 524. tmp = 0; 525. else if(mattk->aatyp == AT_WEAP) { 526. if(otmp) { 527. if (otmp->otyp == CORPSE && 528. otmp->corpsenm == PM_COCKATRICE) 529. goto do_stone_goto_label; 530. tmp += dmgval(otmp, mdef); 531. if (otmp->oartifact) { 532. (void)artifact_hit(magr,mdef, otmp, &tmp, dieroll); 533. if (mdef->mhp <= 0) 534. return (MM_DEF_DIED | 535. (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); 536. } 537. if (tmp) 538. mrustm(magr, mdef, otmp); 539. } 540. } 541. break; 542. case AD_FIRE: 543. if (magr->mcan) { 544. tmp = 0; 545. break; 546. } 547. if (vis) 548. pline("%s is %s!", Monnam(mdef), 549. mattk->aatyp == AT_HUGS ? 550. "being roasted" : "on fire"); 551. tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE); 552. tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE); 553. if (resists_fire(mdef)) { 554. if (vis) 555. pline_The("fire doesn't seem to burn %s!", 556. mon_nam(mdef)); 557. shieldeff(mdef->mx, mdef->my); 558. golemeffects(mdef, AD_FIRE, tmp); 559. tmp = 0; 560. } 561. /* only potions damage resistant players in destroy_item */ 562. tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE); 563. break; 564. case AD_COLD: 565. if (magr->mcan) { 566. tmp = 0; 567. break; 568. } 569. if (vis) pline("%s is covered in frost!", Monnam(mdef)); 570. if (resists_cold(mdef)) { 571. if (vis) 572. pline_The("frost doesn't seem to chill %s!", 573. mon_nam(mdef)); 574. shieldeff(mdef->mx, mdef->my); 575. golemeffects(mdef, AD_COLD, tmp); 576. tmp = 0; 577. } 578. tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD); 579. break; 580. case AD_ELEC: 581. if (magr->mcan) { 582. tmp = 0; 583. break; 584. } 585. if (vis) pline("%s gets zapped!", Monnam(mdef)); 586. tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC); 587. if (resists_elec(mdef)) { 588. if (vis) pline_The("zap doesn't shock %s!", mon_nam(mdef)); 589. shieldeff(mdef->mx, mdef->my); 590. golemeffects(mdef, AD_ELEC, tmp); 591. tmp = 0; 592. } 593. /* only rings damage resistant players in destroy_item */ 594. tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC); 595. break; 596. case AD_ACID: 597. if (magr->mcan) { 598. tmp = 0; 599. break; 600. } 601. if (resists_acid(mdef)) { 602. if (vis) 603. pline("%s is covered in acid, but it seems harmless.", 604. Monnam(mdef)); 605. tmp = 0; 606. } else if (vis) { 607. pline("%s is covered in acid!", Monnam(mdef)); 608. pline("It burns %s!", mon_nam(mdef)); 609. } 610. break; 611. case AD_RUST: 612. if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) { 613. if (vis) pline("%s falls to pieces!", Monnam(mdef)); 614. mondied(mdef); 615. if (mdef->mhp > 0) return 0; 616. else if (mdef->mtame && !vis) 617. pline("May %s rust in peace.", mon_nam(mdef)); 618. return (MM_DEF_DIED | (grow_up(magr,mdef) ? 619. 0 : MM_AGR_DIED)); 620. } 621. tmp = 0; 622. break; 623. case AD_DCAY: 624. if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] || 625. pd == &mons[PM_LEATHER_GOLEM])) { 626. if (vis) pline("%s falls to pieces!", Monnam(mdef)); 627. mondied(mdef); 628. if (mdef->mhp > 0) return 0; 629. else if (mdef->mtame && !vis) 630. pline("May %s rot in peace.", mon_nam(mdef)); 631. return (MM_DEF_DIED | (grow_up(magr,mdef) ? 632. 0 : MM_AGR_DIED)); 633. } 634. tmp = 0; 635. break; 636. case AD_STON: 637. do_stone_goto_label: 638. /* may die from the acid if it eats a stone-curing corpse */ 639. if (munstone(mdef, FALSE)) goto label2; 640. if (poly_when_stoned(pd)) { 641. mon_to_stone(mdef); 642. tmp = 0; 643. break; 644. } 645. if (!resists_ston(mdef)) { 646. if (vis) pline("%s turns to stone!", Monnam(mdef)); 647. monstone(mdef); 648. label2: if (mdef->mhp > 0) return 0; 649. else if (mdef->mtame && !vis) 650. You(brief_feeling, "peculiarly sad"); 651. return (MM_DEF_DIED | (grow_up(magr,mdef) ? 652. 0 : MM_AGR_DIED)); 653. } 654. tmp = (mattk->adtyp == AD_STON ? 0 : 1); 655. break; 656. case AD_TLPT: 657. if (!magr->mcan && tmp < mdef->mhp && !tele_restrict(mdef)) { 658. char mdef_Monnam[BUFSZ]; 659. /* save the name before monster teleports, otherwise 660. we'll get "it" in the suddenly disappears message */ 661. if (vis) Strcpy(mdef_Monnam, Monnam(mdef)); 662. rloc(mdef); 663. if (vis && !cansee(mdef->mx, mdef->my)) 664. pline("%s suddenly disappears!", mdef_Monnam); 665. } 666. break; 667. case AD_SLEE: 668. if (!magr->mcan && !mdef->msleep && 669. sleep_monst(mdef, rnd(10), -1)) { 670. if (vis) { 671. Strcpy(buf, Monnam(mdef)); 672. pline("%s is put to sleep by %s.", buf, mon_nam(magr)); 673. } 674. slept_monst(mdef); 675. } 676. break; 677. case AD_PLYS: 678. if(!magr->mcan && mdef->mcanmove) { 679. if (vis) { 680. Strcpy(buf, Monnam(mdef)); 681. pline("%s is frozen by %s.", buf, mon_nam(magr)); 682. } 683. mdef->mcanmove = 0; 684. mdef->mfrozen = rnd(10); 685. } 686. break; 687. case AD_SLOW: 688. if(!magr->mcan && vis && mdef->mspeed != MSLOW) { 689. if (vis) pline("%s slows down.", Monnam(mdef)); 690. if (mdef->mspeed == MFAST) mdef->mspeed = 0; 691. else mdef->mspeed = MSLOW; 692. } 693. break; 694. case AD_CONF: 695. /* Since confusing another monster doesn't have a real time 696. * limit, setting spec_used would not really be right (though 697. * we still should check for it). 698. */ 699. if (!magr->mcan && !mdef->mconf && !magr->mspec_used) { 700. if (vis) pline("%s looks confused.", Monnam(mdef)); 701. mdef->mconf = 1; 702. } 703. break; 704. case AD_BLND: 705. if (!magr->mcan && haseyes(pd)) { 706. register unsigned rnd_tmp; 707. 708. if (vis && mdef->mcansee) 709. pline("%s is blinded.", Monnam(mdef)); 710. rnd_tmp = d((int)mattk->damn, (int)mattk->damd); 711. if ((rnd_tmp += mdef->mblinded) > 127) rnd_tmp = 127; 712. mdef->mblinded = rnd_tmp; 713. mdef->mcansee = 0; 714. } 715. tmp = 0; 716. break; 717. case AD_HALU: 718. if (!magr->mcan && haseyes(pd) && mdef->mcansee) { 719. if (vis) pline("%s looks %sconfused.", 720. Monnam(mdef), mdef->mconf ? "more " : ""); 721. mdef->mconf = 1; 722. } 723. tmp = 0; 724. break; 725. case AD_CURS: 726. if (!night() && (pa == &mons[PM_GREMLIN])) break; 727. if (!magr->mcan && !rn2(10)) { 728. mdef->mcan = 1; /* cancelled regardless of lifesave */ 729. if (is_were(pd) && pd->mlet != S_HUMAN) 730. were_change(mdef); 731. if (pd == &mons[PM_CLAY_GOLEM]) { 732. if (vis) { 733. pline("Some writing vanishes from %s head!", 734. s_suffix(mon_nam(mdef))); 735. pline("%s is destroyed!", Monnam(mdef)); 736. } 737. mondied(mdef); 738. if (mdef->mhp > 0) return 0; 739. else if (mdef->mtame && !vis) 740. You(brief_feeling, "strangely sad"); 741. return (MM_DEF_DIED | (grow_up(magr,mdef) ? 742. 0 : MM_AGR_DIED)); 743. } 744. if (flags.soundok) { 745. if (!vis) You_hear("laughter."); 746. else pline("%s chuckles.", Monnam(magr)); 747. } 748. } 749. break; 750. case AD_SGLD: 751. tmp = 0; 752. if (magr->mcan || !mdef->mgold) break; 753. /* technically incorrect; no check for stealing gold from 754. * between mdef's feet... 755. */ 756. magr->mgold += mdef->mgold; 757. mdef->mgold = 0; 758. if (vis) { 759. Strcpy(buf, Monnam(magr)); 760. pline("%s steals some gold from %s.", buf, 761. mon_nam(mdef)); 762. } 763. break; 764. case AD_DRLI: 765. if (rn2(2) && !resists_drli(mdef)) { 766. tmp = d(2,6); 767. if (vis) 768. pline("%s suddenly seems weaker!", Monnam(mdef)); 769. mdef->mhpmax -= tmp; 770. if (mdef->m_lev == 0) 771. tmp = mdef->mhp; 772. else mdef->m_lev--; 773. /* Automatic kill if drained past level 0 */ 774. } 775. break; 776. #ifdef SEDUCE 777. case AD_SSEX: 778. #endif 779. case AD_SITM: /* for now these are the same */ 780. case AD_SEDU: 781. if (!magr->mcan && mdef->minvent) { 782. char onambuf[BUFSZ]; 783. 784. otmp = mdef->minvent; 785. obj_extract_self(otmp); 786. if (otmp->owornmask) { 787. mdef->misc_worn_check &= ~otmp->owornmask; 788. otmp->owornmask = 0L; 789. update_mon_intrinsics(mdef, otmp, FALSE); 790. } 791. /* add_to_minv() might free otmp [if it merges] */ 792. if (vis) 793. Strcpy(onambuf, doname(otmp)); 794. add_to_minv(magr, otmp); 795. if (vis) { 796. Strcpy(buf, Monnam(magr)); 797. pline("%s steals %s from %s!", buf, 798. onambuf, mon_nam(mdef)); 799. } 800. possibly_unwield(mdef); 801. mselftouch(mdef, (const char *)0, FALSE); 802. if (mdef->mhp <= 0) 803. return (MM_DEF_DIED | (grow_up(magr,mdef) ? 804. 0 : MM_AGR_DIED)); 805. } 806. tmp = 0; 807. break; 808. case AD_DRST: 809. case AD_DRDX: 810. case AD_DRCO: 811. if (!magr->mcan && !rn2(8)) { 812. if (vis) 813. pline("%s %s was poisoned!", s_suffix(Monnam(magr)), 814. mpoisons_subj(magr, mattk)); 815. if (resists_poison(mdef)) { 816. if (vis) 817. pline_The("poison doesn't seem to affect %s.", 818. mon_nam(mdef)); 819. } else { 820. if (rn2(10)) tmp += rn1(10,6); 821. else { 822. if (vis) pline_The("poison was deadly..."); 823. tmp = mdef->mhp; 824. } 825. } 826. } 827. break; 828. case AD_DRIN: 829. if (!has_head(pd)) { 830. if (vis) pline("%s doesn't seem harmed.", Monnam(mdef)); 831. tmp = 0; 832. break; 833. } 834. if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) { 835. if (vis) { 836. Strcpy(buf, s_suffix(Monnam(mdef))); 837. pline("%s helmet blocks %s attack to his head.", 838. buf, s_suffix(mon_nam(magr))); 839. } 840. break; 841. } 842. if (vis) pline("%s brain is eaten!", s_suffix(Monnam(mdef))); 843. if (mindless(pd)) { 844. if (vis) pline("%s doesn't notice.", Monnam(mdef)); 845. break; 846. } 847. tmp += rnd(10); /* fakery, since monsters lack INT scores */ 848. if (magr->mtame && !magr->isminion) { 849. EDOG(magr)->hungrytime += rnd(60); 850. magr->mconf = 0; 851. } 852. if (tmp >= mdef->mhp && vis) 853. pline("%s last thought fades away...", 854. s_suffix(Monnam(mdef))); 855. break; 856. case AD_STCK: 857. case AD_WRAP: /* monsters cannot grab one another, it's too hard */ 858. break; 859. default: tmp = 0; 860. break; 861. } 862. if(!tmp) return(MM_MISS); 863. 864. if((mdef->mhp -= tmp) < 1) { 865. if (m_at(mdef->mx, mdef->my) == magr) { /* see gulpmm() */ 866. remove_monster(mdef->mx, mdef->my); 867. place_monster(mdef, mdef->mx, mdef->my); 868. } 869. monkilled(mdef, "", (int)mattk->adtyp); 870. if (mdef->mhp > 0) return 0; /* mdef lifesaved */ 871. return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); 872. } 873. return(MM_HIT); 874. } 875. 876. #endif /* OVLB */ 877. 878. 879. #ifdef OVL0 880. 881. int 882. noattacks(ptr) /* returns 1 if monster doesn't attack */ 883. struct permonst *ptr; 884. { 885. int i; 886. 887. for(i = 0; i < NATTK; i++) 888. if(ptr->mattk[i].aatyp) return(0); 889. 890. return(1); 891. } 892. 893. /* `mon' is hit by a sleep attack; return 1 if it's affected, 0 otherwise */ 894. int 895. sleep_monst(mon, amt, how) 896. struct monst *mon; 897. int amt, how; 898. { 899. if (resists_sleep(mon) || 900. (how >= 0 && resist(mon, (char)how, 0, NOTELL))) { 901. shieldeff(mon->mx, mon->my); 902. } else if (mon->mcanmove) { 903. amt += (int) mon->mfrozen; 904. mon->mcanmove = 0; 905. mon->mfrozen = min(amt, 127); 906. return 1; 907. } 908. return 0; 909. } 910. 911. /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */ 912. void 913. slept_monst(mon) 914. struct monst *mon; 915. { 916. if ((mon->msleep || !mon->mcanmove) && mon == u.ustuck && 917. !sticks(uasmon) && !u.uswallow) { 918. pline("%s grip relaxes.", s_suffix(Monnam(mon))); 919. unstuck(mon); 920. } 921. } 922. 923. #endif /* OVL0 */ 924. #ifdef OVLB 925. 926. static void 927. mrustm(magr, mdef, obj) 928. register struct monst *magr, *mdef; 929. register struct obj *obj; 930. { 931. if (!magr || !mdef || !obj) return; /* just in case */ 932. if (mdef->data == &mons[PM_RUST_MONSTER] && !mdef->mcan && 933. is_rustprone(obj) && obj->oeroded < MAX_ERODE) { 934. if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) { 935. if (cansee(mdef->mx, mdef->my) && flags.verbose) 936. pline("%s weapon is not affected.", 937. s_suffix(Monnam(magr))); 938. if (obj->greased && !rn2(2)) obj->greased = 0; 939. } else { 940. if (cansee(mdef->mx, mdef->my)) { 941. pline("%s %s%s!", s_suffix(Monnam(magr)), 942. aobjnam(obj, "rust"), 943. obj->oeroded ? " further" : ""); 944. } 945. obj->oeroded++; 946. } 947. } 948. } 949. 950. static void 951. mswingsm(magr, mdef, otemp) 952. register struct monst *magr, *mdef; 953. register struct obj *otemp; 954. { 955. char buf[BUFSZ]; 956. Strcpy(buf, mon_nam(mdef)); 957. if (!flags.verbose || Blind) return; 958. pline("%s %s %s %s at %s.", Monnam(magr), 959. (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings", 960. his[pronoun_gender(magr)], xname(otemp), buf); 961. } 962. 963. /* 964. * Passive responses by defenders. Does not replicate responses already 965. * handled above. Returns same values as mattackm. 966. */ 967. static int 968. passivemm(magr,mdef,mhit,mdead) 969. register struct monst *magr, *mdef; 970. boolean mhit; 971. int mdead; 972. { 973. register struct permonst *mddat = mdef->data; 974. register struct permonst *madat = magr->data; 975. char buf[BUFSZ]; 976. int i, tmp; 977. 978. for(i = 0; ; i++) { 979. if(i >= NATTK) return (mdead | mhit); /* no passive attacks */ 980. if(mddat->mattk[i].aatyp == AT_NONE) break; 981. } 982. if (mddat->mattk[i].damn) 983. tmp = d((int)mddat->mattk[i].damn, 984. (int)mddat->mattk[i].damd); 985. else if(mddat->mattk[i].damd) 986. tmp = d((int)mddat->mlevel+1, (int)mddat->mattk[i].damd); 987. else 988. tmp = 0; 989. 990. /* These affect the enemy even if defender killed */ 991. switch(mddat->mattk[i].adtyp) { 992. case AD_ACID: 993. if (mhit && !rn2(2)) { 994. Strcpy(buf, Monnam(magr)); 995. if(canseemon(magr)) 996. pline("%s is splashed by %s acid!", 997. buf, s_suffix(mon_nam(mdef))); 998. if (resists_acid(magr)) { 999. if(canseemon(magr)) 1000. pline("%s is not affected.", Monnam(magr)); 1001. tmp = 0; 1002. } 1003. } else tmp = 0; 1004. goto assess_dmg; 1005. default: 1006. break; 1007. } 1008. if (mdead || mdef->mcan) return (mdead|mhit); 1009. 1010. /* These affect the enemy only if defender is still alive */ 1011. if (rn2(3)) switch(mddat->mattk[i].adtyp) { 1012. case AD_PLYS: /* Floating eye */ 1013. if (tmp > 127) tmp = 127; 1014. if (mddat == &mons[PM_FLOATING_EYE]) { 1015. if (!rn2(4)) tmp = 127; 1016. if (magr->mcansee && haseyes(madat) && mdef->mcansee && 1017. (perceives(madat) || !mdef->minvis)) { 1018. Sprintf(buf, "%s gaze is reflected by %%s %%s.", 1019. s_suffix(mon_nam(mdef))); 1020. if (mon_reflects(magr, 1021. canseemon(magr) ? buf : (char *)0)) 1022. return(mdead|mhit); 1023. Strcpy(buf, Monnam(magr)); 1024. if(canseemon(magr)) 1025. pline("%s is frozen by %s gaze!", 1026. buf, s_suffix(mon_nam(mdef))); 1027. magr->mcanmove = 0; 1028. magr->mfrozen = tmp; 1029. return (mdead|mhit); 1030. } 1031. } else { /* gelatinous cube */ 1032. Strcpy(buf, Monnam(magr)); 1033. if(canseemon(magr)) 1034. pline("%s is frozen by %s.", buf, mon_nam(mdef)); 1035. magr->mcanmove = 0; 1036. magr->mfrozen = tmp; 1037. return (mdead|mhit); 1038. } 1039. return 1; 1040. case AD_COLD: 1041. if (resists_cold(magr)) { 1042. if (canseemon(magr)) { 1043. pline("%s is mildly chilly.", Monnam(magr)); 1044. golemeffects(magr, AD_COLD, tmp); 1045. } 1046. tmp = 0; 1047. break; 1048. } 1049. if(canseemon(magr)) 1050. pline("%s is suddenly very cold!", Monnam(magr)); 1051. mdef->mhp += tmp / 2; 1052. if (mdef->mhpmax < mdef->mhp) mdef->mhpmax = mdef->mhp; 1053. if (mdef->mhpmax > ((int) (mdef->m_lev+1) * 8)) { 1054. register struct monst *mtmp; 1055. 1056. if ((mtmp = clone_mon(mdef)) != 0) { 1057. mtmp->mhpmax = mdef->mhpmax /= 2; 1058. if(canseemon(magr)) { 1059. Strcpy(buf, Monnam(mdef)); 1060. pline("%s multiplies from %s heat!", 1061. buf, s_suffix(mon_nam(magr))); 1062. } 1063. } 1064. } 1065. break; 1066. case AD_STUN: 1067. if (!magr->mstun) { 1068. magr->mstun = 1; 1069. if (canseemon(magr)) 1070. pline("%s staggers...", Monnam(magr)); 1071. } 1072. tmp = 0; 1073. break; 1074. case AD_FIRE: 1075. if (resists_fire(magr)) { 1076. if (canseemon(magr)) { 1077. pline("%s is mildly warmed.", Monnam(magr)); 1078. golemeffects(magr, AD_FIRE, tmp); 1079. } 1080. tmp = 0; 1081. break; 1082. } 1083. if(canseemon(magr)) 1084. pline("%s is suddenly very hot!", Monnam(magr)); 1085. break; 1086. case AD_ELEC: 1087. if (resists_elec(magr)) { 1088. if (canseemon(magr)) { 1089. pline("%s is mildly tingled.", Monnam(magr)); 1090. golemeffects(magr, AD_ELEC, tmp); 1091. } 1092. tmp = 0; 1093. break; 1094. } 1095. if(canseemon(magr)) 1096. pline("%s is jolted with electricity!", Monnam(magr)); 1097. break; 1098. default: tmp = 0; 1099. break; 1100. } 1101. else tmp = 0; 1102. 1103. assess_dmg: 1104. if((magr->mhp -= tmp) <= 0) { 1105. monkilled(magr, "", (int)mddat->mattk[i].adtyp); 1106. return (mdead | mhit | MM_AGR_DIED); 1107. } 1108. return (mdead | mhit); 1109. } 1110. 1111. #endif /* OVLB */ 1112. 1113. /*mhitm.c*/
|