abstract
| - Below is the full text to fight.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/fight.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)fight.c 1.4 87/08/08 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* fight.c - version 1.0.3 */ 4. 5. #include 6. #include "hack.h" 7. 8. extern struct permonst li_dog, dog, la_dog; 9. extern char *exclam(), *hcolor(), *xname(); 10. extern struct obj *mkobj_at(); 11. #ifdef KAA 12. extern boolean stoned; 13. extern boolean unweapon; 14. extern char *nomovemsg, *defmonnam(); 15. extern struct monst *mkmon_at(); 16. #endif 17. 18. static boolean far_noise; 19. static long noisetime; 20. 21. /* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */ 22. hitmm(magr,mdef) register struct monst *magr,*mdef; { 23. register struct permonst *pa = magr->data, *pd = mdef->data; 24. int hit; 25. schar tmp; 26. boolean vis; 27. if(!magr || !mdef) return(0); /* mike@genat */ 28. if(index("Eauy", pa->mlet)) return(0); 29. if(magr->mfroz) return(0); /* riv05!a3 */ 30. tmp = pd->ac + pa->mlevel; 31. if(mdef->mconf || mdef->mfroz || mdef->msleep){ 32. tmp += 4; 33. if(mdef->msleep) mdef->msleep = 0; 34. } 35. hit = (tmp > rnd(20)); 36. if(hit) mdef->msleep = 0; 37. vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); 38. if(vis){ 39. char buf[BUFSZ]; 40. if(mdef->mimic) seemimic(mdef); 41. if(magr->mimic) seemimic(magr); 42. (void) sprintf(buf,"%s %s", Monnam(magr), 43. hit ? "hits" : "misses"); 44. pline("%s %s.", buf, monnam(mdef)); 45. } else { 46. boolean farq = (dist(magr->mx, magr->my) > 15); 47. if(farq != far_noise || moves-noisetime > 10) { 48. far_noise = farq; 49. noisetime = moves; 50. pline("You hear some noises%s.", 51. farq ? " in the distance" : ""); 52. } 53. } 54. if(hit){ 55. if(magr->data->mlet == 'c' && !magr->cham) { 56. magr->mhpmax += 3; 57. if(vis) pline("%s is turned to stone!", Monnam(mdef)); 58. else if(mdef->mtame) 59. pline("You have a peculiarly sad feeling for a moment, then it passes."); 60. monstone(mdef); 61. hit = 2; 62. } else 63. if((mdef->mhp -= d(pa->damn,pa->damd)) < 1) { 64. magr->mhpmax += 1 + rn2(pd->mlevel+1); 65. if(magr->mtame && magr->mhpmax > 8*pa->mlevel){ 66. if(pa == &li_dog) magr->data = pa = &dog; 67. else if(pa == &dog) magr->data = pa = &la_dog; 68. } 69. if(vis) pline("%s is killed!", Monnam(mdef)); 70. else if(mdef->mtame) 71. pline("You have a sad feeling for a moment, then it passes."); 72. mondied(mdef); 73. hit = 2; 74. } 75. /* fixes a bug where max monster hp could overflow. */ 76. if(magr->mhpmax <= 0) magr->mhpmax = 127; 77. } 78. #ifdef KAA 79. if(hit == 1 && magr->data->mlet == 'Q') { 80. rloc(mdef); 81. if(vis && !cansee(mdef->mx,mdef->my)) 82. pline("%s suddenly disappears!",Monnam(mdef)); 83. } 84. #endif 85. return(hit); 86. } 87. 88. /* drop (perhaps) a cadaver and remove monster */ 89. mondied(mdef) register struct monst *mdef; { 90. register struct permonst *pd = mdef->data; 91. #ifdef KOPS 92. if(letter(pd->mlet) && rn2(3) && pd->mlet != 'K'){ 93. #else 94. if(letter(pd->mlet) && rn2(3)){ 95. #endif 96. if (pd->mlet == '1') panic("mondied: making obj '1'"); 97. (void) mkobj_at(pd->mlet,mdef->mx,mdef->my); 98. if(cansee(mdef->mx,mdef->my)){ 99. unpmon(mdef); 100. atl(mdef->mx,mdef->my,fobj->olet); 101. } 102. stackobj(fobj); 103. } 104. mondead(mdef); 105. } 106. 107. /* drop a rock and remove monster */ 108. monstone(mdef) register struct monst *mdef; { 109. extern char mlarge[]; 110. if(index(mlarge, mdef->data->mlet)) 111. mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my); 112. else 113. mksobj_at(ROCK, mdef->mx, mdef->my); 114. if(cansee(mdef->mx, mdef->my)){ 115. unpmon(mdef); 116. atl(mdef->mx,mdef->my,fobj->olet); 117. } 118. mondead(mdef); 119. } 120. 121. 122. fightm(mtmp) register struct monst *mtmp; { 123. register struct monst *mon; 124. for(mon = fmon; mon; mon = mon->nmon) if(mon != mtmp) { 125. if(DIST(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3) 126. if(rn2(4)) 127. return(hitmm(mtmp,mon)); 128. } 129. return(-1); 130. } 131. 132. /* u is hit by sth, but not a monster */ 133. thitu(tlev,dam,name) 134. register tlev,dam; 135. register char *name; 136. { 137. char buf[BUFSZ]; 138. setan(name,buf); 139. if(u.uac + tlev <= rnd(20)) { 140. if(Blind) pline("It misses."); 141. else pline("You are almost hit by %s!", buf); 142. return(0); 143. } else { 144. if(Blind) pline("You are hit!"); 145. else pline("You are hit by %s!", buf); 146. losehp(dam,name); 147. return(1); 148. } 149. } 150. 151. #ifdef KAA 152. char mlarge[] = "bCDdegIlmnoPSsTUwY',&9"; 153. #else 154. char mlarge[] = "bCDdegIlmnoPSsTUwY',&"; 155. #endif 156. 157. boolean 158. hmon(mon,obj,thrown) /* return TRUE if mon still alive */ 159. register struct monst *mon; 160. register struct obj *obj; 161. register thrown; 162. { 163. register tmp; 164. boolean hittxt = FALSE; 165. 166. #ifdef KAA 167. stoned = FALSE; /* this refers to the thing hit, not you */ 168. #endif 169. if(!obj){ 170. #ifdef KAA 171. /* Note that c, y, and F can never wield weapons anyway */ 172. if (u.usym == 'c' && mon->data->mlet != 'c') { 173. pline("You turn %s to stone!", monnam(mon)); 174. stoned = TRUE; 175. xkilled(mon,0); 176. return(FALSE); 177. } else if (u.usym == 'y' && mon->data->mlet != 'y') { 178. pline("%s is blinded by your flash of light!",Monnam(mon)); 179. if (!mon->mblinded) { 180. mon->mblinded += rn2(25); 181. mon->mcansee = 0; 182. } 183. rehumanize(); 184. return(TRUE); 185. } else if (u.usym == 'F') { 186. pline("You explode!"); 187. if (!index("gFY",mon->data->mlet)) { 188. pline("%s gets blasted!", Monnam(mon)); 189. mon->mhp -= d(6,6); 190. rehumanize(); 191. if (mon->mhp <= 0) { 192. killed(mon); 193. return(FALSE); 194. } else return(TRUE); 195. } else { 196. pline("The blast doesn't seem to affect %s.", monnam(mon)); 197. rehumanize(); 198. return(TRUE); 199. } 200. } else if (index("P,'", u.usym) && u.uhunger < 1500 201. && !u.uswallow && mon->data->mlet != 'c') { 202. static char msgbuf[BUFSZ]; 203. pline("You swallow %s whole!", monnam(mon)); 204. u.uhunger += 20*mon->mhpmax; 205. newuhs(FALSE); 206. xkilled(mon,2); 207. if (tmp = mon->mhpmax/5) { 208. nomul(-tmp); 209. (void)sprintf(msgbuf, "You finished digesting %s.", 210. monnam(mon)); 211. nomovemsg = msgbuf; 212. } 213. return(FALSE); 214. } else if (u.usym != '@') { 215. if (u.usym == '&' && !rn2(5)) { 216. struct monst *dtmp; 217. pline("Some hell-p has arrived!"); 218. if((dtmp = mkmon_at('&',u.ux,u.uy))) 219. (void)tamedog(dtmp,(struct obj *)0); 220. } 221. tmp = d(mons[u.umonnum].damn, mons[u.umonnum].damd); 222. } else 223. #endif 224. tmp = rnd(2); /* attack with bare hands */ 225. #ifdef KAA 226. if (mon->data->mlet == 'c' && !uarmg && u.usym != 'c'){ 227. #else 228. if(mon->data->mlet == 'c' && !uarmg){ 229. #endif 230. pline("You hit the cockatrice with your bare hands."); 231. pline("You turn to stone ..."); 232. done_in_by(mon); 233. } 234. } else if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) { 235. if(obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG)) 236. tmp = rnd(2); 237. else { 238. if(index(mlarge, mon->data->mlet)) { 239. tmp = rnd(objects[obj->otyp].wldam); 240. switch (obj->otyp) { 241. case SLING_BULLET: 242. case CROSSBOW_BOLT: 243. case MORNING_STAR: 244. case PARTISAN: 245. case BROAD_SWORD: tmp += 1; break; 246. 247. case FLAIL: 248. case RANSEUR: 249. case VOULGE: tmp += rnd(4); break; 250. 251. case HALBERD: 252. case SPETUM: tmp += rnd(6); break; 253. 254. case BARDICHE: 255. case TRIDENT: tmp += d(2,4); break; 256. 257. case TWO_HANDED_SWORD: 258. case KATANA: tmp += d(2,6); break; 259. } 260. } else { 261. tmp = rnd(objects[obj->otyp].wsdam); 262. switch (obj->otyp) { 263. case SLING_BULLET: 264. case CROSSBOW_BOLT: 265. case MACE: 266. case FLAIL: 267. case SPETUM: 268. case TRIDENT: tmp += 1; break; 269. 270. case BARDICHE: 271. case BILL_GUISARME: 272. case GUISARME: 273. case LUCERN_HAMMER: 274. case MORNING_STAR: 275. case RANSEUR: 276. case BROAD_SWORD: 277. case VOULGE: tmp += rnd(4); break; 278. } 279. } 280. tmp += obj->spe; 281. #ifdef KAA 282. if(obj->olet == WEAPON_SYM && obj->dknown && index("VWZ &", 283. mon->data->mlet)) tmp += rn2(4); 284. #endif 285. if(!thrown && obj == uwep && obj->otyp == BOOMERANG 286. && !rn2(3)){ 287. pline("As you hit %s, the boomerang breaks into splinters.", 288. monnam(mon)); 289. freeinv(obj); 290. setworn((struct obj *) 0, obj->owornmask); 291. obfree(obj, (struct obj *) 0); 292. tmp++; 293. } 294. } 295. if(mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD && 296. !strcmp(ONAME(obj), "Orcrist")) 297. tmp += rnd(10); 298. } else switch(obj->otyp) { 299. case HEAVY_IRON_BALL: 300. tmp = rnd(25); break; 301. case ENORMOUS_ROCK: 302. tmp = rnd(20); break; 303. case EXPENSIVE_CAMERA: 304. pline("You succeed in destroying your camera. Congratulations!"); 305. freeinv(obj); 306. if(obj->owornmask) 307. setworn((struct obj *) 0, obj->owornmask); 308. obfree(obj, (struct obj *) 0); 309. return(TRUE); 310. case DEAD_COCKATRICE: 311. pline("You hit %s with the cockatrice corpse.", 312. monnam(mon)); 313. if(mon->data->mlet == 'c') { 314. tmp = 1; 315. hittxt = TRUE; 316. #ifdef KAA 317. stoned = TRUE; 318. xkilled(mon,0); 319. #endif 320. break; 321. } 322. pline("%s is turned to stone!", Monnam(mon)); 323. killed(mon); 324. return(FALSE); 325. case CLOVE_OF_GARLIC: /* no effect against demons */ 326. if(index(UNDEAD, mon->data->mlet)) 327. mon->mflee = 1; 328. tmp = 1; 329. break; 330. default: 331. /* non-weapons can damage because of their weight */ 332. /* (but not too much) */ 333. tmp = obj->owt/10; 334. if(tmp < 1) tmp = 1; 335. else tmp = rnd(tmp); 336. if(tmp > 6) tmp = 6; 337. } 338. 339. /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */ 340. 341. tmp += u.udaminc + dbon(); 342. if(u.uswallow) { 343. if((tmp -= u.uswldtim) <= 0) { 344. pline("Your arms are no longer able to hit."); 345. return(TRUE); 346. } 347. } 348. if(tmp < 1) tmp = 1; 349. mon->mhp -= tmp; 350. if(mon->mhp < 1) { 351. killed(mon); 352. return(FALSE); 353. } 354. if(mon->mtame && (!mon->mflee || mon->mfleetim)) { 355. mon->mflee = 1; /* Rick Richardson */ 356. mon->mfleetim += 10*rnd(tmp); 357. } 358. 359. if(!hittxt) { 360. if(thrown) 361. /* this assumes that we cannot throw plural things */ 362. hit( xname(obj) /* or: objects[obj->otyp].oc_name */, 363. mon, exclam(tmp) ); 364. else if(Blind) 365. pline("You hit it."); 366. else 367. pline("You hit %s%s", monnam(mon), exclam(tmp)); 368. } 369. 370. if(u.umconf && !thrown) { 371. if(!Blind) { 372. pline("Your hands stop glowing %s.", 373. Hallucination ? hcolor() : "blue"); 374. } 375. if (!resist(mon, '+', 0, NOTELL)) mon->mconf = 1; 376. if(!mon->mfroz && !mon->msleep && !Blind && mon->mconf) 377. pline("%s appears confused.",Monnam(mon)); 378. u.umconf = 0; 379. } 380. if(!thrown && rn2(2) && index("VW",u.usym) && 381. !index("VW",mon->data->mlet)){ 382. int tmp=d(2,6); 383. pline("%s suddenly seems weaker!",Monnam(mon)); 384. mon->mhpmax -= tmp; 385. if ((mon->mhp -= tmp) <= 0) { 386. pline("%s dies!",Monnam(mon)); 387. xkilled(mon,0); 388. return(FALSE); 389. } 390. } 391. return(TRUE); /* mon still alive */ 392. } 393. 394. /* try to attack; return FALSE if monster evaded */ 395. /* u.dx and u.dy must be set */ 396. attack(mtmp) 397. register struct monst *mtmp; 398. { 399. schar tmp; 400. boolean malive = TRUE; 401. register struct permonst *mdat; 402. mdat = mtmp->data; 403. 404. #ifdef KAA 405. if(unweapon) { 406. unweapon=FALSE; 407. if(uwep) 408. pline("You begin bashing monsters with your %s.", 409. aobjnam(uwep,(char *)0)); 410. } 411. #endif 412. u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */ 413. 414. if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep && 415. !mtmp->mconf && mtmp->mcansee && !rn2(7) && 416. (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ 417. mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) 418. return(FALSE); 419. #ifdef SAFE_ATTACK 420. /* This section of code provides protection against accidentally 421. * hitting peaceful (like '@') and tame (like 'd') monsters. 422. * There is protection only if you're not blind, confused or 423. * invisible. 424. */ 425. /* changes by wwp 5/16/85 */ 426. if (!Blind && !Confusion && !Hallucination 427. && mdat->mlet == 'd' && mtmp->mtame) { 428. mtmp->mflee = 1; 429. mtmp->mfleetim = rnd(6); 430. pline("You stop to avoid hitting your dog"); 431. return(TRUE); 432. } 433. if (flags.confirm && (mtmp->mpeaceful || mtmp->mtame) && ! Confusion 434. && !Hallucination && !Invisible) 435. 436. if (Blind ? Telepat : (!mtmp->minvis || See_invisible)) { 437. pline("Really attack?"); 438. (void) fflush(stdout); 439. if (readchar() != 'y') { 440. flags.move = 0; 441. return(TRUE); 442. } 443. } 444. #endif /* SAFE_ATTACK /**/ 445. 446. if(mtmp->mimic){ 447. if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; 448. if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == DOOR_SYM) 449. { 450. if (okdoor(u.ux+u.dx, u.uy+u.dy)) 451. pline("The door actually was %s.", defmonnam(mtmp)); 452. else 453. pline("That spellbook was %s.", defmonnam(mtmp)); 454. } 455. else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == GOLD_SYM) 456. pline("The chest was %s!", defmonnam(mtmp)); 457. else 458. pline("Wait! That's %s!",defmonnam(mtmp)); 459. wakeup(mtmp); /* clears mtmp->mimic */ 460. return(TRUE); 461. } 462. 463. wakeup(mtmp); 464. 465. if(mtmp->mhide && mtmp->mundetected){ 466. register struct obj *obj; 467. 468. mtmp->mundetected = 0; 469. if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind) 470. pline("Wait! There's %s hiding under %s!", 471. defmonnam(mtmp), doname(obj)); 472. return(TRUE); 473. } 474. #ifdef KAA 475. tmp = u.uluck + (u.mtimedone ? mons[u.umonnum].mlevel : u.ulevel) + 476. mdat->ac + abon(); 477. if (u.usym=='y' || u.usym=='F') tmp=100; 478. if (index("uEa",u.usym)) return(TRUE); 479. #endif 480. if(uwep) { 481. #ifdef KAA /* Blessed weapons used against undead or demons */ 482. if(uwep->olet == WEAPON_SYM && uwep->dknown && index("VWZ &", 483. mtmp->data->mlet)) tmp += 2; 484. #endif 485. if(uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE) 486. tmp += uwep->spe; 487. if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1; 488. else if(uwep->otyp == KATANA) tmp += 1; 489. else if(uwep->otyp == DAGGER || 490. uwep->otyp == SHURIKEN) tmp += 2; 491. else if(uwep->otyp == CRYSKNIFE) tmp += 3; 492. else if(uwep->otyp == SPEAR && 493. index("XDne", mdat->mlet)) tmp += 2; 494. } 495. if(mtmp->msleep) { 496. mtmp->msleep = 0; 497. tmp += 2; 498. } 499. if(mtmp->mfroz) { 500. tmp += 4; 501. if(!rn2(10)) mtmp->mfroz = 0; 502. } 503. if(mtmp->mflee) tmp += 2; 504. if(u.utrap) tmp -= 3; 505. 506. /* with a lot of luggage, your agility diminishes */ 507. tmp -= (inv_weight() + 40)/20; 508. 509. if(tmp <= rnd(20) && !u.uswallow){ 510. if(Blind) pline("You miss it."); 511. else pline("You miss %s.",monnam(mtmp)); 512. } else { 513. /* we hit the monster; be careful: it might die! */ 514. 515. if((malive = hmon(mtmp,uwep,0)) == TRUE) { 516. /* monster still alive */ 517. if(!rn2(25) && mtmp->mhp < mtmp->mhpmax/2) { 518. mtmp->mflee = 1; 519. if(!rn2(3)) mtmp->mfleetim = rnd(100); 520. if(u.ustuck == mtmp && !u.uswallow) 521. u.ustuck = 0; 522. } 523. #ifndef NOWORM 524. if(mtmp->wormno) 525. cutworm(mtmp, u.ux+u.dx, u.uy+u.dy, 526. uwep ? uwep->otyp : 0); 527. #endif 528. } 529. if(mdat->mlet == 'a') { 530. if(rn2(2)) { 531. if (Blind) pline("You are splashed!"); 532. else pline("You are splashed by %s's acid!",monnam(mtmp)); 533. if (u.usym != 'a') { 534. losehp_m(rnd(6), mtmp); 535. if(!rn2(30)) corrode_armor(); 536. } 537. } 538. if(!rn2(6)) corrode_weapon(); 539. } 540. } 541. #ifdef KAA 542. if (malive) if (u.usym=='N' && mtmp->minvent) { 543. struct obj *otmp, *addinv(); 544. otmp = mtmp->minvent; 545. mtmp->minvent = otmp->nobj; 546. otmp = addinv(otmp); 547. pline("You steal:"); 548. prinv(otmp); 549. } else if (u.usym=='L' && mtmp->mgold) { 550. u.ugold += mtmp->mgold; 551. mtmp->mgold = 0; 552. pline("Your purse feels heavier."); 553. } else if (u.usym=='Q') rloc(mtmp); 554. #endif 555. if(malive && mdat->mlet == 'E' && canseemon(mtmp) 556. && !mtmp->mcan && rn2(3)) { 557. if(mtmp->mcansee) { 558. pline("You are frozen by %s's gaze!",monnam(mtmp)); 559. nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200); 560. } else { 561. pline("%s cannot defend itself.", Amonnam(mtmp,"blinded")); 562. if(!rn2(500)) if((int)u.uluck > LUCKMIN) u.uluck--; 563. } 564. } 565. return(TRUE); 566. }
|