abstract
| - Below is the full text to mhitm.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0 88/11/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. #ifdef NAMED_ITEMS 7. # include "artifact.h" 8. #endif 9. 10. static boolean vis, far_noise; 11. static long noisetime; 12. static struct obj *otmp; 13. 14. static void mrustm P((struct monst *, struct monst *, struct obj *)); 15. static int hitmm P((struct monst *,struct monst *,struct attack *)); 16. static int gazemm P((struct monst *,struct monst *,struct attack *)); 17. static int gulpmm P((struct monst *,struct monst *,struct attack *)); 18. static int explmm P((struct monst *,struct attack *)); 19. static int mdamagem P((struct monst *,struct monst *,struct attack *)); 20. static void mswingsm P((struct monst *, struct monst *, struct obj *)); 21. 22. static boolean 23. m_incompat(magr, mdef) 24. /* This must work like in mhitu.c. Specifically, if it's a shopkeeper 25. * polymorphed into a monster of a specific gender, the specific gender 26. * overrides. Thus, do not use is_female(), since then a female shopkeeper 27. * polymorphed into an incubus, or any shopkeeper turned into something 28. * genderless, would be treated improperly. 29. * This nonsense could be avoided if every monster had a gender field... 30. */ 31. register struct monst *magr, *mdef; 32. { 33. return(gender(magr) != 1-gender(mdef)); 34. } 35. 36. static void 37. noises(magr, mattk) 38. register struct monst *magr; 39. register struct attack *mattk; 40. { 41. boolean farq = (dist(magr->mx, magr->my) > 15); 42. 43. if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) { 44. far_noise = farq; 45. noisetime = moves; 46. You("hear %s%s.", 47. (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises", 48. farq ? " in the distance" : ""); 49. } 50. } 51. 52. static 53. void 54. missmm(magr, mdef, mattk) 55. register struct monst *magr, *mdef; 56. struct attack *mattk; 57. { 58. char buf[BUFSZ]; 59. 60. if(vis) { 61. if(mdef->mimic) seemimic(mdef); 62. if(magr->mimic) seemimic(magr); 63. if (sp_melee(magr) && !magr->mcan && 64. (is_nymph(magr) || !m_incompat(magr,mdef))) { 65. Sprintf(buf, "%s pretends to be friendly to", 66. Monnam(magr)); 67. } else 68. Sprintf(buf,"%s misses", Monnam(magr)); 69. pline("%s %s.", buf, mon_nam(mdef)); 70. } else noises(magr, mattk); 71. } 72. 73. int 74. fightm(mtmp) /* have monsters fight each other */ 75. register struct monst *mtmp; 76. { 77. register struct monst *mon; 78. /* TODO: this loop needs to be restructured, as we don't know if 79. * either "mon" or "mon->nmon" will exist after the attack. 80. */ 81. for(mon = fmon; mon; mon = mon->nmon) 82. if(mon != mtmp) { 83. if(dist2(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3) 84. return(mattackm(mtmp,mon)); 85. } 86. return(-1); 87. } 88. 89. /* 90. * mattackm returns -1 (magr died), 0 (miss), 1 (mdef hit), or 2 (mdef killed) 91. * 92. * Each successive attack has a lower probability of hitting. Some 93. * rely on the success of previous attacks. 94. * 95. * In the case of exploding monsters, the monster dies as well. 96. */ 97. int 98. mattackm(magr, mdef) 99. register struct monst *magr,*mdef; 100. { 101. int i, tmp, nsum, sum[NATTK]; 102. struct attack *mattk; 103. struct permonst *pa, *pd; 104. schar strike; 105. 106. if(!magr || !mdef) return(0); /* mike@genat */ 107. pa = magr->data; pd = mdef->data; 108. if(magr->mfroz) return(0); /* riv05!a3 */ 109. 110. /* Calculate the armour class differential. */ 111. 112. tmp = pd->ac + magr->m_lev; 113. if(mdef->mconf || mdef->mfroz || mdef->msleep){ 114. tmp += 4; 115. if(mdef->msleep) mdef->msleep = 0; 116. } 117. 118. if (is_elf(magr->data) && is_orc(mdef->data)) tmp++; 119. 120. /* Set up visibility of action */ 121. vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); 122. 123. /* Set flag indicating monster has moved this turn. Necessary since a 124. * monster might get an attack out of sequence (i.e. before its move) in 125. * some cases, in which case this still counts as its move for the round 126. * and it shouldn't move again. 127. */ 128. magr->mlstmv = moves; 129. 130. /* Now perform all attacks for the monster. */ 131. 132. for(i=0; i 133. for(i = nsum = 0; i < NATTK; nsum |= sum[i++]) { 134. mattk = &(pa->mattk[i]); 135. otmp = (struct obj *)0; 136. switch(mattk->aatyp) { 137. 138. case AT_WEAP: /* "hand to hand" attacks */ 139. otmp = select_hwep(magr); 140. if(otmp) { 141. if (vis) mswingsm(magr, mdef, otmp); 142. tmp += hitval(otmp, pd); 143. } 144. case AT_CLAW: 145. case AT_KICK: 146. case AT_BITE: 147. case AT_STNG: 148. case AT_TUCH: 149. case AT_BUTT: 150. if((strike = (tmp > rnd(20+i)))) { 151. sum[i] = hitmm(magr, mdef, mattk); 152. if(sum[i] == -1) return(-1); 153. } else missmm(magr, mdef, mattk); 154. break; 155. 156. case AT_HUGS: /* automatic if prev two attacks succeed */ 157. strike = 1; 158. if(sum[i-1] && sum[i-2]) { 159. sum[i] = hitmm(magr, mdef, mattk); 160. if(sum[i] == -1) return(-1); 161. } 162. break; 163. 164. case AT_GAZE: /* will not wake up a sleeper */ 165. strike = 0; 166. sum[i] = gazemm(magr, mdef, mattk); 167. break; 168. 169. case AT_EXPL: /* automatic hit if next to */ 170. strike = -1; 171. sum[i] = explmm(magr, mattk); 172. break; 173. 174. case AT_ENGL: 175. if((strike = (tmp > rnd(20+i)))) 176. sum[i]= gulpmm(magr, mdef, mattk); 177. else missmm(magr, mdef, mattk); 178. break; 179. 180. default: /* no attack */ 181. strike = 0; 182. break; 183. } 184. if(sum[i] == 2) return(2); /* defender dead */ 185. if(strike) mdef->msleep = 0; 186. if(strike == -1) return(-1); /* attacker dead */ 187. nsum |= sum[i]; 188. } 189. return(nsum); 190. } 191. 192. /* hitmm returns 0 (miss), 1 (hit), 2 (kill), or -1 (magr died) */ 193. static int 194. hitmm(magr, mdef, mattk) 195. register struct monst *magr,*mdef; 196. struct attack *mattk; 197. { 198. 199. if(vis){ 200. char buf[BUFSZ]; 201. if(mdef->mimic) seemimic(mdef); 202. if(magr->mimic) seemimic(magr); 203. if(sp_melee(magr) && !magr->mcan) { 204. if(!is_nymph(magr) && m_incompat(magr,mdef)) 205. goto strike; 206. Sprintf(buf, "%s %s", Monnam(magr), 207. mdef->mblinded ? "talks to" : "smiles at"); 208. pline("%s %s %s.", buf, mon_nam(mdef), 209. m_incompat(magr,mdef) ? 210. "engagingly" : "seductively"); 211. } else { 212. strike: 213. switch (mattk->aatyp) { 214. case AT_BITE: 215. Sprintf(buf,"%s bites", Monnam(magr)); 216. break; 217. case AT_STNG: 218. Sprintf(buf,"%s stings", Monnam(magr)); 219. break; 220. case AT_BUTT: 221. Sprintf(buf,"%s butts", Monnam(magr)); 222. break; 223. case AT_TUCH: 224. Sprintf(buf,"%s touches", Monnam(magr)); 225. break; 226. case AT_HUGS: 227. if (magr != u.ustuck) { 228. Sprintf(buf,"%s squeezes", Monnam(magr)); 229. break; 230. } 231. default: 232. Sprintf(buf,"%s hits", Monnam(magr)); 233. } 234. } 235. pline("%s %s.", buf, mon_nam(mdef)); 236. } else noises(magr, mattk); 237. return(mdamagem(magr, mdef, mattk)); 238. } 239. 240. static int 241. gazemm(magr, mdef, mattk) 242. register struct monst *magr, *mdef; 243. struct attack *mattk; 244. { 245. char buf[BUFSZ]; 246. 247. if(vis) { 248. Sprintf(buf,"%s gazes at", Monnam(magr)); 249. pline("%s %s.", buf, mon_nam(mdef)); 250. } 251. 252. if (mdef->mblinded || mdef->msleep) { 253. 254. if(vis) pline("but nothing happens."); 255. return(0); 256. } 257. 258. return(mdamagem(magr, mdef, mattk)); 259. } 260. 261. static int 262. gulpmm(magr, mdef, mattk) 263. register struct monst *magr, *mdef; 264. register struct attack *mattk; 265. { 266. int mx, my, tmp; 267. char buf[BUFSZ]; 268. 269. if(vis) { 270. Sprintf(buf,"%s swallows", Monnam(magr)); 271. pline("%s %s.", buf, mon_nam(mdef)); 272. } 273. 274. mx = magr->mx; 275. my = magr->my; 276. /* move over top of the defender */ 277. if(cansee(mdef->mx, mdef->my)) unpmon(mdef); 278. if(cansee(magr->mx, magr->my)) unpmon(magr); 279. magr->mx = mdef->mx; 280. magr->my = mdef->my; 281. if(cansee(magr->mx, magr->my)) pmon(magr); 282. if((tmp = mdamagem(magr, mdef, mattk)) == 2) { 283. levl[mx][my].mmask = 0; 284. return(2); /* defender died */ 285. } else { /* defender survived */ 286. if(cansee(magr->mx, magr->my)) unpmon(magr); 287. magr->mx = mx; 288. magr->my = my; 289. /* move off of defender */ 290. if(cansee(magr->mx, magr->my)) pmon(magr); 291. if(cansee(mdef->mx, mdef->my)) pmon(mdef); 292. return(tmp); 293. } 294. } 295. 296. static int 297. explmm(magr, mattk) 298. register struct monst *magr; 299. register struct attack *mattk; 300. { 301. register struct monst *mon; 302. 303. if(cansee(magr->mx, magr->my)) 304. pline("%s explodes!", Monnam(magr)); 305. else noises(magr, mattk); 306. 307. for(mon = fmon; mon; mon = mon->nmon) 308. if(mon != magr) { 309. if(dist2(mon->mx, mon->my, magr->mx, magr->my) < 3) 310. (void) mdamagem(magr, mon, mattk); 311. } 312. 313. if(dist2(magr->mx, magr->my, u.ux, u.uy) < 3) 314. (void) mdamageu(magr, d((int)mattk->damn, (int)mattk->damd)); 315. 316. mondied(magr); 317. return(2); 318. } 319. 320. static int 321. mdamagem(magr, mdef, mattk) 322. register struct monst *magr, *mdef; 323. register struct attack *mattk; 324. { 325. struct permonst *ptr, *pd = mdef->data; 326. int tmp = d((int)mattk->damn,(int)mattk->damd); 327. char buf[BUFSZ]; 328. 329. switch(mattk->adtyp) { 330. case AD_DGST: 331. if(flags.verbose && flags.soundok) pline("\"Burrrrp!\""); 332. tmp = mdef->mhp; 333. break; 334. case AD_STUN: 335. if (magr->mcan) break; 336. if(vis) pline("%s staggers for a moment.", Monnam(mdef)); 337. mdef->mstun = 1; 338. case AD_PHYS: 339. if (mattk->aatyp == AT_KICK && thick_skinned(mdef->data)) 340. tmp = 0; 341. else if(mattk->aatyp == AT_WEAP) { 342. if(otmp) { 343. tmp += dmgval(otmp, pd); 344. #ifdef NAMED_ITEMS 345. if(spec_ability(otmp, SPFX_DRLI) && 346. !resists_drli(mdef->data)) { 347. int dam = rnd(8); 348. 349. tmp += dam; 350. if(vis) 351. pline("The %s blade drains the life from %s!", 352. Hallucination ? hcolor() : black, 353. mon_nam(mdef)); 354. mdef->mhpmax -= dam; 355. if (mdef->m_lev == 0) 356. tmp = mdef->mhp; 357. else mdef->m_lev--; 358. } 359. #endif 360. mrustm(magr, mdef, otmp); 361. } 362. } 363. break; 364. case AD_FIRE: 365. if (magr->mcan) { 366. tmp = 0; 367. break; 368. } 369. #ifdef GOLEMS 370. golemeffects(mdef, AD_FIRE, tmp); 371. #endif /* GOLEMS */ 372. if(resists_fire(pd)) { 373. shieldeff(mdef->mx, mdef->my); 374. tmp = 0; 375. } else { 376. tmp += destroy_mitem(mdef, SCROLL_SYM, AD_FIRE); 377. tmp += destroy_mitem(mdef, POTION_SYM, AD_FIRE); 378. #ifdef SPELLS 379. tmp += destroy_mitem(mdef, SPBOOK_SYM, AD_FIRE); 380. #endif 381. } 382. break; 383. case AD_COLD: 384. if (magr->mcan) { 385. tmp = 0; 386. break; 387. } 388. #ifdef GOLEMS 389. golemeffects(mdef, AD_COLD, tmp); 390. #endif /* GOLEMS */ 391. if(resists_cold(pd)) { 392. shieldeff(mdef->mx, mdef->my); 393. tmp = 0; 394. } else tmp += destroy_mitem(mdef, POTION_SYM, AD_COLD); 395. break; 396. case AD_ELEC: 397. if (magr->mcan) { 398. tmp = 0; 399. break; 400. } 401. #ifdef GOLEMS 402. golemeffects(mdef, AD_ELEC, tmp); 403. #endif /* GOLEMS */ 404. if(resists_elec(pd)) { 405. shieldeff(mdef->mx, mdef->my); 406. tmp = 0; 407. } 408. break; 409. case AD_ACID: 410. if (magr->mcan) { 411. tmp = 0; 412. break; 413. } 414. if(resists_acid(pd)) tmp = 0; 415. break; 416. case AD_RUST: 417. #ifdef GOLEMS 418. if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) { 419. if (vis) pline("%s falls to pieces!", Monnam(mdef)); 420. else if(mdef->mtame) 421. pline("May %s rust in peace.", mon_nam(mdef)); 422. mondied(mdef); 423. magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); 424. ptr = grow_up(magr); 425. if(!ptr) return(-1); 426. return(2); 427. } 428. #endif /* GOLEMS */ 429. tmp = 0; 430. break; 431. case AD_DCAY: 432. #ifdef GOLEMS 433. if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] || 434. pd == &mons[PM_LEATHER_GOLEM])) { 435. if (vis) pline("%s falls to pieces!", Monnam(mdef)); 436. else if(mdef->mtame) 437. pline("May %s rot in peace.", mon_nam(mdef)); 438. mondied(mdef); 439. magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); 440. ptr = grow_up(magr); 441. if(!ptr) return(-1); 442. return(2); 443. } 444. #endif /* GOLEMS */ 445. tmp = 0; 446. break; 447. case AD_STON: 448. if(!resists_ston(pd)) { 449. magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); 450. if(vis) pline("%s turns to stone!", Monnam(mdef)); 451. else if(mdef->mtame) 452. You("have a peculiarly sad feeling for a moment, then it passes."); 453. monstone(mdef); 454. ptr = grow_up(magr); 455. if(!ptr) return(-1); 456. return(2); 457. } 458. tmp = 0; /* no damage if this fails */ 459. break; 460. case AD_TLPT: 461. if(!magr->mcan && tmp >= mdef->mhp) { 462. rloc(mdef); 463. if(vis && !cansee(mdef->mx, mdef->my)) 464. pline("%s suddenly disappears!", Monnam(mdef)); 465. } 466. break; 467. case AD_SLEE: 468. if(!resists_sleep(pd) && !magr->mcan && vis && !mdef->msleep) { 469. pline("%s falls asleep.", Monnam(mdef)); 470. mdef->msleep = 1; 471. } 472. break; 473. case AD_PLYS: 474. if(!magr->mcan && vis && !mdef->mfroz) { 475. pline("%s stops moving.", Monnam(mdef)); 476. mdef->mfroz = 1; 477. } 478. break; 479. case AD_SLOW: 480. if(!magr->mcan && vis && mdef->mspeed != MSLOW) { 481. pline("%s slows down.", Monnam(mdef)); 482. if (mdef->mspeed == MFAST) mdef->mspeed = 0; 483. else mdef->mspeed = MSLOW; 484. } 485. break; 486. case AD_CONF: 487. /* Since confusing another monster doesn't have a real time 488. * limit, setting spec_used would not really be right (though 489. * we still should check for it). 490. */ 491. if(!magr->mcan && vis && !mdef->mconf && !magr->mspec_used) { 492. pline("%s looks confused.", Monnam(mdef)); 493. mdef->mconf = 1; 494. } 495. break; 496. case AD_BLND: 497. if(!magr->mcan && haseyes(pd)) { 498. 499. if(vis && !mdef->mblinded) 500. pline("%s is blinded.", Monnam(mdef)); 501. { 502. register unsigned rnd_tmp; 503. rnd_tmp = d((int)mattk->damn, (int)mattk->damd); 504. mdef->mcansee = 0; 505. if((mdef->mblinded + rnd_tmp) > 127) 506. mdef->mblinded = 127; 507. else mdef->mblinded += rnd_tmp; 508. } 509. } 510. tmp = 0; 511. break; 512. case AD_CURS: 513. if(!night() && (magr->data == &mons[PM_GREMLIN])) break; 514. if(!magr->mcan && !rn2(10)) { 515. if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN) 516. were_change(mdef); 517. #ifdef GOLEMS 518. if (mdef->data == &mons[PM_CLAY_GOLEM]) { 519. if (vis) { 520. pline("Some writing vanishes from %s's head!", 521. mon_nam(mdef)); 522. pline("%s dies!", Monnam(mdef)); 523. } 524. else if (mdef->mtame) 525. You("have a strangely sad feeling for a moment, then it passes."); 526. mondied(mdef); 527. magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); 528. ptr = grow_up(magr); 529. if(!ptr) return(-1); 530. return(2); 531. } 532. #endif /* GOLEMS */ 533. mdef->mcan = 1; 534. if (flags.soundok) { 535. if (!vis) You("hear laughter."); 536. else pline("%s chuckles.", Monnam(magr)); 537. } 538. } 539. break; 540. case AD_SGLD: 541. tmp = 0; 542. if (magr->mcan || !mdef->mgold) break; 543. /* technically incorrect; no check for stealing gold from 544. * between mdef's feet... 545. */ 546. magr->mgold += mdef->mgold; 547. mdef->mgold = 0; 548. if (vis) { 549. Strcpy(buf, Monnam(magr)); 550. pline("%s steals some gold from %s.", buf, 551. mon_nam(mdef)); 552. } 553. break; 554. case AD_DRLI: 555. if(rn2(2) && !resists_drli(mdef->data)) { 556. tmp = d(2,6); 557. if (vis) 558. kludge("%s suddenly seems weaker!", Monnam(mdef)); 559. mdef->mhpmax -= tmp; 560. if (mdef->m_lev == 0) 561. tmp = mdef->mhp; 562. else mdef->m_lev--; 563. /* Automatic kill if drained past level 0 */ 564. } 565. break; 566. #ifdef SEDUCE 567. case AD_SSEX: 568. #endif 569. case AD_SITM: /* for now these are the same */ 570. case AD_SEDU: 571. if (!magr->mcan && mdef->minvent) { 572. otmp = mdef->minvent; 573. mdef->minvent = otmp->nobj; 574. otmp->nobj = magr->minvent; 575. magr->minvent = otmp; 576. if (vis) { 577. Strcpy(buf, Monnam(magr)); 578. pline("%s steals %s from %s!", buf, 579. doname(otmp), mon_nam(mdef)); 580. } 581. } 582. tmp = 0; 583. break; 584. case AD_DRST: 585. case AD_DRDX: 586. case AD_DRCO: 587. if (!magr->mcan && !rn2(8)) { 588. if (vis) 589. pline("%s's %s was poisoned!", Monnam(magr), 590. mattk->aatyp==AT_BITE ? "bite" : "sting"); 591. if (resists_poison(mdef->data)) { 592. if (vis) 593. pline("The poison doesn't seem to affect %s.", 594. mon_nam(mdef)); 595. } else { 596. if (rn2(10)) tmp += rn1(10,6); 597. else { 598. if (vis) pline("The poison was deadly..."); 599. tmp = mdef->mhp; 600. } 601. } 602. } 603. break; 604. case AD_STCK: 605. case AD_WRAP: /* monsters cannot grab one another, it's too hard */ 606. break; 607. default: tmp = 0; 608. break; 609. } 610. if(!tmp) return(1); 611. 612. if((mdef->mhp -= tmp) < 1) { 613. magr->mhpmax += 1 + rn2((int)mdef->m_lev+1); 614. if(vis) pline("%s is killed!", Monnam(mdef)); 615. else if(mdef->mtame) 616. You("have a sad feeling for a moment, then it passes."); 617. mondied(mdef); 618. ptr = grow_up(magr); 619. if(!ptr) return(-1); 620. return(2); 621. } 622. /* fixes a bug where max monster hp could overflow. */ 623. if(magr->mhpmax <= 0 || magr->mhpmax > MHPMAX) magr->mhpmax = MHPMAX; 624. 625. return(1); 626. } 627. 628. int 629. noattacks(ptr) /* returns 1 if monster doesn't attack */ 630. struct permonst *ptr; 631. { 632. int i; 633. 634. for(i = 0; i < NATTK; i++) 635. if(ptr->mattk[i].aatyp) return(0); 636. 637. return(1); 638. } 639. 640. static void 641. mrustm(magr, mdef, obj) 642. register struct monst *magr, *mdef; 643. register struct obj *obj; 644. { 645. if (!magr || !mdef || !obj) return; /* just in case */ 646. if (mdef->data == &mons[PM_RUST_MONSTER] && 647. objects[obj->otyp].oc_material == METAL && 648. !obj->rustfree && obj->spe > -2) { 649. if(obj->blessed && rn2(3)) { 650. if (cansee(mdef->mx, mdef->my)) 651. pline("%s's weapon is not affected.", Monnam(magr)); 652. } else { 653. if (cansee(mdef->mx, mdef->my)) 654. pline("%s's %s!", Monnam(magr), 655. aobjnam(obj, "corrode")); 656. obj->spe--; 657. } 658. } 659. } 660. 661. static void 662. mswingsm(magr, mdef, otemp) 663. register struct monst *magr, *mdef; 664. register struct obj *otemp; 665. { 666. char buf[BUFSZ]; 667. Strcpy(buf, mon_nam(mdef)); 668. if (!flags.verbose || Blind || otemp->olet != WEAPON_SYM) return; 669. pline("%s %s %s %s at %s.", Monnam(magr), 670. (otemp->otyp == SPEAR || 671. otemp->otyp == LANCE || 672. otemp->otyp == GLAIVE || 673. otemp->otyp == TRIDENT) ? "thrusts" : "swings", 674. is_female(magr) ? "her" : 675. is_human(magr->data) ? "his" : "its", 676. xname(otemp), buf); 677. }
|