abstract
| - Below is the full text to mthrowu.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2 96/03/15 */ 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. #ifndef OVLB 12. 13. STATIC_DCL const char *breathwep[]; 14. 15. #else /* OVLB */ 16. 17. /* 18. * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h. 19. */ 20. STATIC_OVL NEARDATA const char *breathwep[] = { 21. "fragments", 22. "fire", 23. "frost", 24. "sleep gas", 25. "a disintegration blast", 26. "lightning", 27. "poison gas", 28. "acid", 29. "strange breath #8", 30. "strange breath #9" 31. }; 32. 33. int 34. thitu(tlev, dam, obj, name) /* u is hit by sth, but not a monster */ 35. register int tlev, dam; 36. struct obj *obj; 37. register const char *name; 38. { 39. const char *onm = (obj && obj_is_pname(obj)) ? the(name) : an(name); 40. boolean is_acid = (obj && obj->otyp == ACID_VENOM); 41. 42. if(u.uac + tlev <= rnd(20)) { 43. if(Blind || !flags.verbose) pline("It misses."); 44. else You("are almost hit by %s!", onm); 45. return(0); 46. } else { 47. if(Blind || !flags.verbose) You("are hit!"); 48. else You("are hit by %s!", onm); 49. 50. if (obj && objects[obj->otyp].oc_material == SILVER 51. && hates_silver(uasmon)) { 52. dam += rnd(20); 53. pline_The("silver sears your flesh!"); 54. exercise(A_CON, FALSE); 55. } 56. if (is_acid && resists_acid(&youmonst)) 57. pline("It doesn't seem to hurt you."); 58. else { 59. if (is_acid) pline("It burns!"); 60. if (Half_physical_damage) dam = (dam+1) / 2; 61. losehp(dam, name, (obj && obj_is_pname(obj)) ? 62. KILLED_BY : KILLED_BY_AN); 63. exercise(A_STR, FALSE); 64. } 65. return(1); 66. } 67. } 68. 69. /* Be sure this corresponds with what happens to player-thrown objects in 70. * dothrow.c (for consistency). --KAA 71. * Returns 0 if object still exists (not destroyed). 72. */ 73. 74. STATIC_OVL int 75. drop_throw(obj, ohit, x, y) 76. register struct obj *obj; 77. boolean ohit; 78. int x,y; 79. { 80. int retvalu = 1; 81. int create; 82. struct monst *mtmp; 83. struct trap *t; 84. 85. if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS || 86. (ohit && obj->otyp == EGG)) 87. create = 0; 88. else if (ohit && 89. ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) || 90. obj->otyp == ROCK)) 91. create = !rn2(3); 92. else create = 1; 93. 94. if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && 95. (t = t_at(x, y)) && ((t->ttyp == PIT) || 96. (t->ttyp == SPIKED_PIT)))) { 97. int objgone = 0; 98. 99. if (down_gate(x, y) != -1) 100. objgone = ship_object(obj, x, y, FALSE); 101. if (!objgone) { 102. if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */ 103. place_object(obj, x, y); 104. stackobj(obj); 105. retvalu = 0; 106. } 107. } 108. } else obfree(obj, (struct obj*) 0); 109. return retvalu; 110. } 111. 112. #endif /* OVLB */ 113. #ifdef OVL1 114. 115. /* an object launched by someone/thing other than player attacks a monster; 116. return 1 if the object has stopped moving (hit or its range used up) */ 117. int 118. ohitmon(mtmp, otmp, range, verbose) 119. struct monst *mtmp; /* accidental target */ 120. struct obj *otmp; /* missile; might be destroyed by drop_throw */ 121. int range; /* how much farther will object travel if it misses */ 122. /* Use -1 to signify to keep going even after hit, */ 123. /* unless its gone (used for rolling_boulder_traps) */ 124. boolean verbose; /* give message(s) even when you can't see what happened */ 125. { 126. int damage, tmp; 127. boolean vis, ismimic; 128. int objgone = 1; 129. 130. ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER; 131. vis = cansee(bhitpos.x, bhitpos.y); 132. 133. tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); 134. if (tmp < rnd(20)) { 135. if (!ismimic) { 136. if (vis) miss(distant_name(otmp, xname), mtmp); 137. else if (verbose) pline("It is missed."); 138. } 139. if (!range) { /* Last position; object drops */ 140. (void) drop_throw(otmp, 0, mtmp->mx, mtmp->my); 141. return 1; 142. } 143. } else if (otmp->oclass == POTION_CLASS) { 144. if (ismimic) seemimic(mtmp); 145. mtmp->msleep = 0; 146. if (vis) otmp->dknown = 1; 147. potionhit(mtmp, otmp); 148. return 1; 149. } else { 150. damage = dmgval(otmp, mtmp); 151. if (damage < 1) damage = 1; 152. if (otmp->otyp == ACID_VENOM && resists_acid(mtmp)) 153. damage = 0; 154. if (ismimic) seemimic(mtmp); 155. mtmp->msleep = 0; 156. if (vis) hit(distant_name(otmp,xname), mtmp, exclam(damage)); 157. else if (verbose) pline("It is hit%s", exclam(damage)); 158. 159. if (otmp->opoisoned) { 160. if (resists_poison(mtmp)) { 161. if (vis) pline_The("poison doesn't seem to affect %s.", 162. mon_nam(mtmp)); 163. } else { 164. if (rn2(30)) { 165. damage += rnd(6); 166. } else { 167. if (vis) pline_The("poison was deadly..."); 168. damage = mtmp->mhp; 169. } 170. } 171. } 172. if (objects[otmp->otyp].oc_material == SILVER && 173. hates_silver(mtmp->data)) { 174. if (vis) pline_The("silver sears %s flesh!", 175. s_suffix(mon_nam(mtmp))); 176. else if (verbose) pline("Its flesh is seared!"); 177. } 178. if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) { 179. if (resists_acid(mtmp)) { 180. if (vis || verbose) 181. pline("%s is unaffected.", Monnam(mtmp)); 182. damage = 0; 183. } else { 184. if (vis) pline_The("acid burns %s!", mon_nam(mtmp)); 185. else if (verbose) pline("It is burned!"); 186. } 187. } 188. mtmp->mhp -= damage; 189. if (mtmp->mhp < 1) { 190. if (vis || verbose) 191. pline("%s is %s!", Monnam(mtmp), 192. (nonliving(mtmp->data) || !vis) 193. ? "destroyed" : "killed"); 194. mondied(mtmp); 195. } 196. 197. if ((otmp->otyp == CREAM_PIE || otmp->otyp == BLINDING_VENOM) && 198. haseyes(mtmp->data)) { 199. if (vis) pline("%s is blinded by %s.", 200. Monnam(mtmp), the(xname(otmp))); 201. mtmp->mcansee = 0; 202. tmp = (int)mtmp->mblinded + rnd(25) + 20; 203. if (tmp > 127) tmp = 127; 204. mtmp->mblinded = tmp; 205. } 206. 207. objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y); 208. if (!objgone && range == -1) { /* special case */ 209. obj_extract_self(otmp); /* free it for motion again */ 210. return 0; 211. } 212. return 1; 213. } 214. return 0; 215. } 216. 217. void 218. m_throw(mon, x, y, dx, dy, range, obj) 219. register struct monst *mon; 220. register int x,y,dx,dy,range; /* direction and range */ 221. register struct obj *obj; 222. { 223. register struct monst *mtmp; 224. struct obj *singleobj; 225. char sym = obj->oclass; 226. int hitu, blindinc = 0; 227. 228. bhitpos.x = x; 229. bhitpos.y = y; 230. 231. if (obj->quan == 1L) { 232. /* 233. * Remove object from minvent. This cannot be done later on; 234. * what if the player dies before then, leaving the monster 235. * with 0 daggers? (This caused the infamous 2^32-1 orcish 236. * dagger bug). 237. * 238. * VENOM is not in minvent - it should already be OBJ_FREE. 239. * The extract below does nothing. 240. */ 241. 242. /* not possibly_unwield, which checks the object's */ 243. /* location, not its existence */ 244. if (MON_WEP(mon) == obj) { 245. obj->owornmask &= ~W_WEP; 246. MON_NOWEP(mon); 247. } 248. obj_extract_self(obj); 249. singleobj = obj; 250. obj = (struct obj *) 0; 251. } else { 252. singleobj = splitobj(obj, obj->quan - 1L); 253. obj_extract_self(singleobj); 254. } 255. 256. singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */ 257. 258. if (singleobj->cursed && (dx || dy) && !rn2(7)) { 259. if(canseemon(mon) && flags.verbose) { 260. if((singleobj->oclass == WEAPON_CLASS || 261. singleobj->oclass == GEM_CLASS) 262. && objects[singleobj->otyp].w_propellor) 263. pline("%s misfires!", Monnam(mon)); 264. else 265. pline("%s slips as %s throws it!", 266. The(xname(singleobj)), mon_nam(mon)); 267. } 268. dx = rn2(3)-1; 269. dy = rn2(3)-1; 270. /* pre-check validity of new direction */ 271. if((!dx && !dy) 272. || !isok(bhitpos.x+dx,bhitpos.y+dy) 273. /* missile hits the wall */ 274. || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)) { 275. (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 276. return; 277. } 278. } 279. 280. /* Note: drop_throw may destroy singleobj. Since obj must be destroyed 281. * early to avoid the dagger bug, anyone who modifies this code should 282. * be careful not to use either one after it's been freed. 283. */ 284. if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); 285. while(range-- > 0) { /* Actually the loop is always exited by break */ 286. bhitpos.x += dx; 287. bhitpos.y += dy; 288. if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 289. if (ohitmon(mtmp, singleobj, range, TRUE)) 290. break; 291. } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 292. if (multi) nomul(0); 293. 294. if (singleobj->oclass == POTION_CLASS) { 295. if (!Blind) singleobj->dknown = 1; 296. potionhit(&youmonst, singleobj); 297. break; 298. } 299. switch(singleobj->otyp) { 300. int dam, hitv; 301. case CREAM_PIE: 302. case BLINDING_VENOM: 303. hitu = thitu(8, 0, singleobj, xname(singleobj)); 304. break; 305. default: 306. dam = dmgval(singleobj, &youmonst); 307. hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my); 308. if (hitv < -4) hitv = -4; 309. if (is_elf(mon->data) && 310. objects[singleobj->otyp].w_propellor 311. == WP_BOW) { 312. hitv++; 313. if (MON_WEP(mon) && 314. MON_WEP(mon)->otyp == ELVEN_BOW) 315. hitv++; 316. if(singleobj->otyp == ELVEN_ARROW) dam++; 317. } 318. if (bigmonst(uasmon)) hitv++; 319. hitv += 8+singleobj->spe; 320. 321. if (dam < 1) dam = 1; 322. hitu = thitu(hitv, dam, 323. singleobj, xname(singleobj)); 324. } 325. if (hitu && singleobj->opoisoned) { 326. char *singlename = xname(singleobj); 327. poisoned(singlename, A_STR, singlename, 10); 328. } 329. if(hitu && (singleobj->otyp == CREAM_PIE || 330. singleobj->otyp == BLINDING_VENOM)) { 331. blindinc = rnd(25); 332. if(singleobj->otyp == CREAM_PIE) { 333. if(!Blind) pline("Yecch! You've been creamed."); 334. else pline("There's %s sticky all over your %s.", 335. something, 336. body_part(FACE)); 337. } else { /* venom in the eyes */ 338. if(Blindfolded) /* nothing */ ; 339. else if(!Blind) pline_The("venom blinds you."); 340. else Your("%s sting.", 341. makeplural(body_part(EYE))); 342. } 343. } 344. stop_occupation(); 345. if (hitu || !range) { 346. (void) drop_throw(singleobj, hitu, u.ux, u.uy); 347. break; 348. } 349. } else if (!range /* reached end of path */ 350. /* missile hits edge of screen */ 351. || !isok(bhitpos.x+dx,bhitpos.y+dy) 352. /* missile hits the wall */ 353. || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ) 354. #ifdef SINKS 355. /* Thrown objects "sink" */ 356. || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) 357. #endif 358. ) { 359. (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 360. break; 361. } 362. tmp_at(bhitpos.x, bhitpos.y); 363. delay_output(); 364. } 365. tmp_at(bhitpos.x, bhitpos.y); 366. delay_output(); 367. tmp_at(DISP_END, 0); 368. /* blindfold keeps substances out of your eyes */ 369. if (blindinc && !Blindfolded) { 370. u.ucreamed += blindinc; 371. make_blinded(Blinded + blindinc,FALSE); 372. } 373. } 374. 375. #endif /* OVL1 */ 376. #ifdef OVLB 377. 378. /* Remove an item from the monster's inventory and destroy it. */ 379. void 380. m_useup(mon, obj) 381. struct monst *mon; 382. struct obj *obj; 383. { 384. if (obj->quan > 1L) { 385. obj->quan--; 386. } else { 387. obj_extract_self(obj); 388. possibly_unwield(mon); 389. if (obj->owornmask) { 390. mon->misc_worn_check &= ~obj->owornmask; 391. update_mon_intrinsics(mon, obj, FALSE); 392. } 393. dealloc_obj(obj); 394. } 395. } 396. 397. #endif /* OVLB */ 398. #ifdef OVL1 399. 400. void 401. thrwmu(mtmp) /* monster throws item at you */ 402. register struct monst *mtmp; 403. { 404. struct obj *otmp; 405. register xchar x, y; 406. 407. if(lined_up(mtmp)) { 408. if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { 409. mtmp->weapon_check = NEED_RANGED_WEAPON; 410. /* mon_wield_item resets weapon_check as appropriate */ 411. if(mon_wield_item(mtmp) != 0) return; 412. } 413. otmp = select_rwep(mtmp); 414. if (otmp) { 415. /* If you are coming toward the monster, the monster 416. * should try to soften you up with missiles. If you are 417. * going away, you are probably hurt or running. Give 418. * chase, but if you are getting too far away, throw. 419. */ 420. x = mtmp->mx; 421. y = mtmp->my; 422. if(!URETREATING(x,y) || 423. !rn2(BOLT_LIM-distmin(x,y,mtmp->mux,mtmp->muy))) 424. { 425. const char *verb = "throws"; 426. 427. if (otmp->otyp == ARROW 428. || otmp->otyp == ELVEN_ARROW 429. || otmp->otyp == ORCISH_ARROW 430. || otmp->otyp == CROSSBOW_BOLT) verb = "shoots"; 431. if (canseemon(mtmp)) { 432. pline("%s %s %s!", Monnam(mtmp), verb, 433. obj_is_pname(otmp) ? 434. the(singular(otmp, xname)) : 435. an(singular(otmp, xname))); 436. } 437. m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 438. distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp); 439. nomul(0); 440. return; 441. } 442. } 443. } 444. } 445. 446. #endif /* OVL1 */ 447. #ifdef OVLB 448. 449. int 450. spitmu(mtmp, mattk) /* monster spits substance at you */ 451. register struct monst *mtmp; 452. register struct attack *mattk; 453. { 454. register struct obj *otmp; 455. 456. if(mtmp->mcan) { 457. 458. if(flags.soundok) 459. pline("A dry rattle comes from %s throat", 460. s_suffix(mon_nam(mtmp))); 461. return 0; 462. } 463. if(lined_up(mtmp)) { 464. switch (mattk->adtyp) { 465. case AD_BLND: 466. case AD_DRST: 467. otmp = mksobj(BLINDING_VENOM, TRUE, FALSE); 468. break; 469. default: 470. impossible("bad attack type in spitmu"); 471. /* fall through */ 472. case AD_ACID: 473. otmp = mksobj(ACID_VENOM, TRUE, FALSE); 474. break; 475. } 476. if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) { 477. if (canseemon(mtmp)) 478. pline("%s spits venom!", Monnam(mtmp)); 479. m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 480. distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp); 481. nomul(0); 482. return 0; 483. } 484. } 485. return 0; 486. } 487. 488. #endif /* OVLB */ 489. #ifdef OVL1 490. 491. int 492. breamu(mtmp, mattk) /* monster breathes at you (ranged) */ 493. register struct monst *mtmp; 494. register struct attack *mattk; 495. { 496. /* if new breath types are added, change AD_ACID to max type */ 497. int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ; 498. 499. if(lined_up(mtmp)) { 500. 501. if(mtmp->mcan) { 502. if(flags.soundok) { 503. if(canseemon(mtmp)) 504. pline("%s coughs.", Monnam(mtmp)); 505. else 506. You_hear("a cough."); 507. } 508. return(0); 509. } 510. if(!mtmp->mspec_used && rn2(3)) { 511. 512. if((typ >= AD_MAGM) && (typ <= AD_ACID)) { 513. 514. if(canseemon(mtmp)) 515. pline("%s breathes %s!", Monnam(mtmp), 516. breathwep[typ-1]); 517. buzz((int) (-20 - (typ-1)), (int)mattk->damn, 518. mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); 519. nomul(0); 520. /* breath runs out sometimes. Also, give monster some 521. * cunning; don't breath if the player fell asleep. 522. */ 523. if(!rn2(3)) 524. mtmp->mspec_used = 10+rn2(20); 525. if(typ == AD_SLEE && !Sleep_resistance) 526. mtmp->mspec_used += rnd(20); 527. } else impossible("Breath weapon %d used", typ-1); 528. } 529. } 530. return(1); 531. } 532. 533. boolean 534. linedup(ax, ay, bx, by) 535. register xchar ax, ay, bx, by; 536. { 537. tbx = ax - bx; /* These two values are set for use */ 538. tby = ay - by; /* after successful return. */ 539. 540. /* sometimes displacement makes a monster think that you're at its 541. own location; prevent it from throwing and zapping in that case */ 542. if (!tbx && !tby) return FALSE; 543. 544. if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */ 545. && distmin(tbx, tby, 0, 0) < BOLT_LIM) { 546. if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by))); 547. else if(clear_path(ax,ay,bx,by)) return TRUE; 548. } 549. return FALSE; 550. } 551. 552. boolean 553. lined_up(mtmp) /* is mtmp in position to use ranged attack? */ 554. register struct monst *mtmp; 555. { 556. return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); 557. } 558. 559. #endif /* OVL1 */ 560. #ifdef OVL0 561. 562. /* Check if a monster is carrying a particular item. 563. */ 564. struct obj * 565. m_carrying(mtmp, type) 566. struct monst *mtmp; 567. int type; 568. { 569. register struct obj *otmp; 570. 571. for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 572. if(otmp->otyp == type) 573. return(otmp); 574. return((struct obj *) 0); 575. } 576. 577. #endif /* OVL0 */ 578. 579. /*mthrowu.c*/
|