Source:NetHack 3.0.0/dothrow.c
Jump to navigation
Jump to search
Below is the full text to dothrow.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/dothrow.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)dothrow.c 3.0 88/10/22 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. /* Contains code for 't' (throw) */ 6. 7. #include "hack.h" 8. 9. static void gem_accept P((struct monst *, struct obj *)); 10. static int throw_gold P((struct obj *)); 11. static const char toss_objs[] = { '0', GOLD_SYM, '#', WEAPON_SYM, 0 }; 12. #ifdef WORM 13. extern boolean notonhead; 14. #endif 15. 16. int 17. dothrow() { 18. register struct obj *obj; 19. 20. obj = getobj(toss_objs, "throw"); 21. /* it is also possible to throw food */ 22. /* (or jewels, or iron balls... ) */ 23. 24. if(!obj || !getdir(1)) { /* ask "in what direction?" */ 25. if(obj && obj->olet == GOLD_SYM) u.ugold += OGOLD(obj); 26. return(0); 27. } 28. 29. if(obj->olet == GOLD_SYM) return(throw_gold(obj)); 30. 31. if(!canletgo(obj,"throw")) 32. return(0); 33. if(obj->otyp == BOULDER 34. #ifdef POLYSELF 35. && !throws_rocks(uasmon) 36. #endif 37. ) { 38. pline("It's too heavy."); 39. return(1); 40. } 41. if(!u.dx && !u.dy && !u.dz) { 42. You("cannot throw an object at yourself."); 43. return(0); 44. } 45. u_wipe_engr(2); 46. 47. if(obj == uwep) { 48. if(welded(obj)) { 49. weldmsg(obj, FALSE); 50. return(1); 51. } 52. if(obj->quan > 1) 53. setuwep(splitobj(obj, 1)); 54. else { 55. setuwep((struct obj *)0); 56. if (uwep) return(1); /* unwielded, died, rewielded */ 57. } 58. } 59. else if(obj->quan > 1) 60. (void) splitobj(obj, 1); 61. freeinv(obj); 62. return(throwit(obj)); 63. } 64. 65. static void 66. hitfloor(obj) 67. register struct obj *obj; 68. { 69. #ifdef ALTARS 70. if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj); 71. else 72. #endif 73. pline("%s hits the floor.", Doname2(obj)); 74. if (breaks(obj, TRUE)) return; 75. else if(obj->olet == POTION_SYM) { 76. pline("The flask breaks, and you smell a peculiar odor..."); 77. potionbreathe(obj); 78. obfree(obj, (struct obj *)0); 79. } else 80. dropy(obj); 81. } 82. 83. int 84. throwit(obj) 85. register struct obj *obj; 86. { 87. register struct monst *mon; 88. register int range; 89. 90. if(u.uswallow) { 91. mon = u.ustuck; 92. bhitpos.x = mon->mx; 93. bhitpos.y = mon->my; 94. } else if(u.dz) { 95. if(u.dz < 0) { 96. pline("%s hits the ceiling, then falls back on top of your %s.", 97. Doname2(obj), /* note: obj->quan == 1 */ 98. body_part(HEAD)); 99. if(obj->olet == POTION_SYM) 100. potionhit(&youmonst, obj); 101. else { 102. if(uarmh) pline("Fortunately, you are wearing a helmet!"); 103. losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object"); 104. if (!breaks(obj, TRUE)) dropy(obj); 105. } 106. } else hitfloor(obj); 107. return(1); 108. 109. } else if(obj->otyp == BOOMERANG) { 110. mon = boomhit(u.dx, u.dy); 111. if(mon == &youmonst) { /* the thing was caught */ 112. (void) addinv(obj); 113. return(1); 114. } 115. } else { 116. if(obj->otyp == PICK_AXE && shkcatch(obj)) 117. return(1); 118. 119. range = (int)((ACURR(A_STR) > 18 ? 20 : ACURR(A_STR))/2 - obj->owt/4); 120. if (obj == uball) { 121. if (u.ustuck) range = 1; 122. else if (range >= 5) range = 5; 123. } 124. if (range < 1) range = 1; 125. 126. if ((obj->olet == WEAPON_SYM || obj->olet == GEM_SYM) && 127. uwep && 128. objects[obj->otyp].w_propellor == 129. -objects[uwep->otyp].w_propellor) 130. range++; 131. #ifdef POLYSELF 132. if (obj->otyp == BOULDER) range = 20; 133. #endif 134. 135. mon = bhit(u.dx, u.dy, range, obj->olet, 136. (int (*)()) 0, (int (*)()) 0, obj); 137. } 138. if(mon) { 139. /* awake monster if sleeping */ 140. wakeup(mon); 141. #ifdef WORM 142. if(bhitpos.x != mon->mx || bhitpos.y != mon->my) 143. notonhead = TRUE; 144. #endif 145. if(thitmonst(mon, obj)) return(1); 146. } 147. if(!u.uswallow) { 148. char let = obj->olet; 149. 150. /* the code following might become part of dropy() */ 151. if (breaks(obj, TRUE)) { 152. tmp_at(-1, let); 153. tmp_at(-3, (int)AT_OBJ); 154. tmp_at(bhitpos.x, bhitpos.y); 155. tmp_at(-1, -1); 156. return(1); 157. } 158. if(flooreffects(obj,bhitpos.x,bhitpos.y)) return(1); 159. #ifdef WORM 160. if(obj->otyp == CRYSKNIFE) 161. obj->otyp = WORM_TOOTH; 162. #endif 163. obj->ox = bhitpos.x; 164. obj->oy = bhitpos.y; 165. obj->nobj = fobj; 166. fobj = obj; 167. levl[bhitpos.x][bhitpos.y].omask = 1; 168. if(obj->unpaid && costly_spot(bhitpos.x, bhitpos.y)) 169. subfrombill(obj); 170. stackobj(obj); 171. if(obj == uball && 172. (bhitpos.x != u.ux || bhitpos.y != u.uy)){ 173. if(u.utrap){ 174. if(u.utraptype == TT_PIT) 175. pline("The ball pulls you out of the pit!"); 176. else if(u.utraptype == TT_WEB) { 177. pline("The ball pulls you out of the web!"); 178. pline("The web is destroyed!"); 179. deltrap(t_at(u.ux,u.uy)); 180. } else { 181. register long side = 182. rn2(3) ? LEFT_SIDE : RIGHT_SIDE; 183. pline("The ball pulls you out of the bear trap."); 184. Your("%s %s is severely damaged.", 185. (side == LEFT_SIDE) ? "left" : "right", 186. body_part(LEG)); 187. set_wounded_legs(side, 500+rn2(1000)); 188. losehp(2, "thrown ball"); 189. } 190. u.utrap = 0; 191. } 192. unsee(); 193. u.ux = bhitpos.x - u.dx; 194. u.uy = bhitpos.y - u.dy; 195. movobj(uchain,u.ux,u.uy); 196. setsee(); 197. spoteffects(); 198. } 199. if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); 200. } else 201. mpickobj(u.ustuck,obj); 202. return(1); 203. } 204. 205. int 206. thitmonst(mon, obj) 207. register struct monst *mon; 208. register struct obj *obj; 209. { 210. register int tmp; /* Base chance to hit */ 211. 212. /* Differences from melee weapons: 213. * 214. * Dex still gives a bonus, but strength does not. 215. * Polymorphed players lacking attacks may still throw. 216. * There's a base -2 to hit. 217. * No bonuses for fleeing or stunned targets (they don't dodge 218. * melee blows as readily, but dodging arrows is hard anyway). 219. * Not affected by traps, etc... 220. * Certain items which don't in themselves do damage ignore tmp. 221. */ 222. tmp = -2 + Luck + mon->data->ac; 223. #ifdef POLYSELF 224. if (u.umonnum >= 0) tmp += uasmon->mlevel; 225. else 226. #endif 227. tmp += u.ulevel; 228. if(ACURR(A_DEX) < 4) tmp -= 3; 229. else if(ACURR(A_DEX) < 6) tmp -= 2; 230. else if(ACURR(A_DEX) < 8) tmp -= 1; 231. else if(ACURR(A_DEX) > 15) tmp += (ACURR(A_DEX) - 15); 232. 233. if(mon->msleep) { 234. mon->msleep = 0; 235. tmp += 2; 236. } 237. if(mon->mfroz) { 238. tmp += 4; 239. if(!rn2(10)) mon->mfroz = 0; 240. } 241. if (is_orc(mon->data) && pl_character[0]=='E') tmp++; 242. if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */ 243. 244. if(obj->olet == GEM_SYM && mon->data->mlet == S_UNICORN) { 245. if (mon->mtame) 246. kludge("%s catches and drops the %s.", 247. Monnam(mon), xname(obj)); 248. else { 249. kludge("%s catches the %s.", Monnam(mon), xname(obj)); 250. gem_accept(mon, obj); 251. } 252. return(1); 253. } 254. if(obj->olet == WEAPON_SYM || obj->otyp == ROCK || obj->olet == GEM_SYM) { 255. if(obj->otyp < DART || obj->otyp == ROCK || obj->olet == GEM_SYM) { 256. if (!uwep || 257. objects[obj->otyp].w_propellor != 258. -objects[uwep->otyp].w_propellor) 259. tmp -= 4; 260. else tmp += uwep->spe; 261. } else if(obj->otyp == BOOMERANG) tmp += 4; 262. tmp += obj->spe; 263. if(tmp >= rnd(20)) { 264. if(hmon(mon,obj,1) == TRUE){ 265. /* mon still alive */ 266. #ifdef WORM 267. cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp); 268. #endif 269. } else mon = 0; 270. /* projectiles thrown disappear sometimes */ 271. if((obj->otyp < BOOMERANG || obj->olet == GEM_SYM) 272. && rn2(3)) { 273. /* check bill; free */ 274. obfree(obj, (struct obj *)0); 275. return(1); 276. } 277. } else miss(xname(obj), mon); 278. } else if(obj->otyp == HEAVY_IRON_BALL) { 279. if(obj != uball) tmp += 2; 280. if(tmp >= rnd(20)) { 281. if(hmon(mon,obj,1) == FALSE) 282. mon = 0; /* he died */ 283. } else miss(xname(obj), mon); 284. } else if (obj->otyp == BOULDER) { 285. tmp += 6; /* Likely to hit! */ 286. if(tmp >= rnd(20)) { 287. if(hmon(mon,obj,1) == FALSE) 288. mon = 0; /* he died */ 289. } else miss(xname(obj), mon); 290. } else if((obj->otyp == CREAM_PIE 291. #ifdef POLYSELF 292. || obj->otyp == BLINDING_VENOM 293. #endif 294. ) && ACURR(A_DEX) >= rnd(10)) { 295. (void) hmon(mon,obj,1); /* can't die from it */ 296. #ifdef POLYSELF 297. } else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) { 298. if(hmon(mon,obj,1) == FALSE) 299. mon = 0; 300. #endif 301. } else if(obj->olet == POTION_SYM && ACURR(A_DEX) >= rnd(15)) { 302. potionhit(mon, obj); 303. return(1); 304. } else { 305. pline("The %s misses %s.", xname(obj), 306. cansee(bhitpos.x,bhitpos.y) ? mon_nam(mon) : "it"); 307. if(obj->olet == FOOD_SYM && 308. (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE)) 309. if(tamedog(mon,obj)) return(1); 310. } 311. return(0); 312. } 313. 314. static void 315. gem_accept(mon, obj) 316. register struct monst *mon; 317. register struct obj *obj; 318. { 319. char buf[BUFSZ]; 320. static const char nogood[] = " is not interested in your junk."; 321. static const char maybeluck[] = " hesitatingly accepts your gift."; 322. static const char addluck[] = " graciously accepts your gift."; 323. 324. Strcpy(buf,Monnam(mon)); 325. 326. mon->mpeaceful = 1; 327. if(obj->dknown && objects[obj->otyp].oc_name_known) { 328. if(objects[obj->otyp].g_val > 0) { 329. if(mon->data == &mons[ 330. ((u.ualigntyp== U_CHAOTIC) ? PM_BLACK_UNICORN : 331. (u.ualigntyp == U_LAWFUL) ? PM_WHITE_UNICORN 332. : PM_GREY_UNICORN)]) { 333. Strcat(buf, addluck); 334. change_luck(5); 335. } else { 336. Strcat(buf, maybeluck); 337. change_luck(rn2(7)-3); 338. } 339. } else { 340. Strcat(buf,nogood); 341. goto nopick; 342. } 343. } else { /* value unknown to @ */ 344. change_luck(1); 345. Strcat(buf,addluck); 346. } 347. mpickobj(mon, obj); 348. nopick: 349. if(!Blind) pline(buf); 350. rloc(mon); 351. } 352. 353. /* returns 0 if object doesn't break */ 354. /* returns 1 if object broke */ 355. int 356. breaks(obj, loose) 357. register struct obj *obj; 358. register boolean loose; /* if not loose, obj is in fobj chain */ 359. { 360. switch(obj->otyp) { 361. #ifdef MEDUSA 362. case MIRROR: 363. change_luck(-2); /* and fall through */ 364. #endif 365. case EXPENSIVE_CAMERA: 366. case CRYSTAL_BALL: 367. if(!Blind) 368. pline("%s shatters into a thousand pieces!", 369. Doname2(obj)); 370. else You("hear something shatter!"); 371. break; 372. case EGG: 373. pline("Splat!"); 374. break; 375. case CREAM_PIE: 376. pline("What a mess!"); 377. break; 378. case ACID_VENOM: 379. case BLINDING_VENOM: 380. pline("Splash!"); 381. break; 382. default: 383. return 0; 384. } 385. 386. if(loose) { 387. unpobj(obj); 388. obfree(obj, (struct obj *)0); 389. } else { 390. addtobill(obj, FALSE); 391. delobj(obj); 392. } 393. return(1); 394. } 395. 396. static boolean 397. martial() 398. { 399. return((pl_character[0] == 'S' || pl_character[0] == 'P')); 400. } 401. 402. static int 403. throw_gold(obj) 404. struct obj *obj; 405. { 406. int range = 0, odx, ody; 407. long zorks = OGOLD(obj); 408. register struct monst *mon; 409. 410. free((genericptr_t) obj); 411. if(zorks < 0) { 412. /* watch negative overflows a la drop() */ 413. u.ugold += zorks; 414. pline("The LRS would be very interested to know you have that much."); 415. return(0); 416. } 417. 418. if(u.uswallow) { 419. pline("The gold disappears in the %s's entrails.", 420. mon_nam(u.ustuck)); 421. u.ustuck->mgold += zorks; 422. return(1); 423. } 424. 425. if(u.dz) { 426. if(u.dz < 0) { 427. pline("The gold hits the ceiling, then falls back on top of your %s.", 428. body_part(HEAD)); 429. /* some self damage? */ 430. if(uarmh) pline("Fortunately, you are wearing a helmet!"); 431. } else pline("The gold hits the floor."); 432. bhitpos.x = u.ux; /* a msg is needed here */ 433. bhitpos.y = u.uy; 434. goto skip; 435. } 436. 437. range = rnd((int)ACURR(A_STR)); 438. if(martial()) range = range + rnd(3); 439. 440. /* see if the gold has a place to move into */ 441. odx = u.ux + u.dx; 442. ody = u.uy + u.dy; 443. if(bad_kick_throw_pos(odx,ody)) { 444. bhitpos.x = u.ux; 445. bhitpos.y = u.uy; 446. } else { 447. if (mon = ghit(u.dx, u.dy, range)) 448. if (ghitm(mon, zorks)) /* was it caught? */ 449. zorks = 0; 450. } 451. skip: 452. if (zorks) /* perhaps it was caught */ 453. mkgold(zorks, bhitpos.x, bhitpos.y); 454. if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); 455. return(1); 456. }