Source:NetHack 3.0.0/mthrowu.c
Revision as of 05:05, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/mthrowu.c moved to Source:NetHack 3.0.0/mthrowu.c: Robot: moved page)
Below is the full text to mthrowu.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/mthrowu.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: @(#)mthrowu.c 3.0 88/04/13 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 int movedist(); 8. 9. #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y)) 10. 11. boolean lined_up(); 12. 13. schar tbx = 0, tby = 0; /* used for direction of throw, buzz, etc. */ 14. 15. const char *breathwep[] = { "fragments", 16. "fire", 17. "sleep gas", 18. "frost", 19. "death", 20. "lightning", 21. "poison gas", 22. "acid" 23. }; 24. 25. int 26. thitu(tlev, dam, name) /* u is hit by sth, but not a monster */ 27. register int tlev, dam; 28. register char *name; 29. { 30. char buf[BUFSZ]; 31. boolean acidic = (!strcmp(name, "splash of venom") && dam); 32. /* A horrible kludge... the problem is that we want to do something 33. * special--and we can't do it after returning since we might die and 34. * not return, but the special stuff should be done anyway... 35. */ 36. 37. setan(name, buf); 38. if(u.uac + tlev <= rnd(20)) { 39. if(Blind || !flags.verbose) pline("It misses."); 40. else You("are almost hit by %s!", buf); 41. return(0); 42. } else { 43. if(Blind || !flags.verbose) You("are hit!"); 44. else You("are hit by %s!", buf); 45. Strcpy(buf,name); 46. /* If name came from xname() we must copy it, otherwise if 47. * you die, the possession identify will call xname(), 48. * overwriting xname's buffer, and your tombstone will say 49. * you were killed by a green gem or some such. 50. */ 51. #ifdef POLYSELF 52. if (acidic && resists_acid(uasmon)) 53. pline("It doesn't seem to hurt you."); 54. else { 55. #endif 56. if (acidic) pline("It burns!"); 57. losehp(dam, buf); 58. #ifdef POLYSELF 59. } 60. #endif 61. return(1); 62. } 63. } 64. 65. /* Be sure this corresponds with what happens to player-thrown objects in 66. * dothrow.c (for consistency). --KAA 67. */ 68. static void 69. drop_throw(obj, ohit, x, y) 70. register struct obj *obj; 71. boolean ohit; 72. int x,y; 73. { 74. int create; 75. 76. if (obj->otyp == CREAM_PIE || obj->olet == VENOM_SYM) 77. create = 0; 78. else if (ohit && 79. ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) || 80. obj->otyp == ROCK)) 81. create = !rn2(3); 82. else create = 1; 83. if (create && !flooreffects(obj,x,y)) { 84. obj->ox = x; 85. obj->oy = y; 86. obj->nobj = fobj; 87. fobj = obj; 88. stackobj(fobj); 89. levl[x][y].omask = 1; 90. } else free((genericptr_t)obj); 91. } 92. 93. static void 94. m_throw(x, y, dx, dy, range, obj) 95. register int x,y,dx,dy,range; /* direction and range */ 96. register struct obj *obj; 97. { 98. register struct monst *mtmp; 99. struct obj *singleobj; 100. char sym = obj->olet; 101. int damage; 102. int hitu, blindinc=0; 103. 104. bhitpos.x = x; 105. bhitpos.y = y; 106. 107. singleobj = splitobj(obj, (int)obj->quan-1); 108. /* splitobj leaves the new object in the chain (i.e. the monster's 109. * inventory). Remove it. We can do this in 1 line, but it's highly 110. * dependent on the fact that we know splitobj() places it immediately 111. * after obj. 112. */ 113. obj->nobj = singleobj->nobj; 114. 115. if(sym) { 116. tmp_at(-1, sym); /* open call */ 117. tmp_at(-3, (int)AT_OBJ); 118. } 119. while(range-- > 0) { /* Actually the loop is always exited by break */ 120. bhitpos.x += dx; 121. bhitpos.y += dy; 122. if(levl[bhitpos.x][bhitpos.y].mmask) { 123. mtmp = m_at(bhitpos.x,bhitpos.y); 124. 125. if(mtmp->data->ac + 8 + obj->spe <= rnd(20)) { 126. miss(distant_name(singleobj,xname), mtmp); 127. if (!range) { /* Last position; object drops */ 128. drop_throw(singleobj, 0, mtmp->mx, mtmp->my); 129. break; 130. } 131. } else { 132. damage = dmgval(obj, mtmp->data); 133. if (damage < 1) damage = 1; 134. if (obj->otyp==ACID_VENOM && resists_acid(mtmp->data)) 135. damage = 0; 136. hit(distant_name(singleobj,xname), mtmp,exclam(damage)); 137. if (obj->opoisoned) { 138. if (resists_poison(mtmp->data)) 139. kludge("The poison doesn't seem to affect %s.", 140. mon_nam(mtmp)); 141. else { 142. if (rn2(10)) damage += rnd(6); 143. else { 144. pline("The poison was deadly..."); 145. damage = mtmp->mhp; 146. } 147. } 148. } 149. if (obj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){ 150. if (resists_acid(mtmp->data)) { 151. pline("%s is unaffected.", Monnam(mtmp)); 152. damage = 0; 153. } else pline("The acid burns %s!", mon_nam(mtmp)); 154. } 155. mtmp->mhp -= damage; 156. if(mtmp->mhp < 1) { 157. if (cansee(mtmp->mx, mtmp->my)) 158. pline("%s is killed!", Monnam(mtmp)); 159. mondied(mtmp); 160. } 161. 162. if((obj->otyp == CREAM_PIE) || 163. (obj->otyp == BLINDING_VENOM)) { 164. if (cansee(mtmp->mx, mtmp->my)) 165. pline("%s is blinded by the %s.", 166. Monnam(mtmp), xname(singleobj)); 167. if(mtmp->msleep) mtmp->msleep = 0; 168. mtmp->mcansee = 0; 169. { 170. register unsigned rnd_tmp = rnd(25) + 20; 171. if((mtmp->mblinded + rnd_tmp) > 127) 172. mtmp->mblinded = 127; 173. else mtmp->mblinded += rnd_tmp; 174. } 175. } 176. drop_throw(singleobj, 1, bhitpos.x, bhitpos.y); 177. break; 178. } 179. } 180. if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 181. if (multi) nomul(0); 182. 183. switch(obj->otyp) { 184. int dam; 185. case CREAM_PIE: 186. case BLINDING_VENOM: 187. hitu = thitu(8, 0, xname(singleobj)); 188. break; 189. default: 190. dam = dmgval(obj, uasmon); 191. if (dam < 1) dam = 1; 192. hitu = thitu(8+obj->spe, dam, xname(singleobj)); 193. } 194. if (obj->opoisoned) 195. /* it's safe to call xname twice because it's the 196. same object both times... */ 197. poisoned(xname(singleobj), A_STR, xname(singleobj)); 198. if(hitu && (obj->otyp == CREAM_PIE || 199. obj->otyp == BLINDING_VENOM)) { 200. blindinc = rnd(25); 201. if(obj->otyp == CREAM_PIE) { 202. if(!Blind) pline("Yecch! You've been creamed."); 203. else pline("There's something sticky all over your %s.", body_part(FACE)); 204. } else { /* venom in the eyes */ 205. if(Blindfolded) /* nothing */ ; 206. else if(!Blind) pline("The venom blinds you."); 207. else Your("%s sting.", 208. makeplural(body_part(EYE))); 209. } 210. } 211. if (hitu || !range) { 212. drop_throw(singleobj, hitu, u.ux, u.uy); 213. break; 214. } 215. } else if (!range /* reached end of path */ 216. /* missile hits edge of screen */ 217. || !isok(bhitpos.x+dx,bhitpos.y+dy) 218. /* missile hits the wall */ 219. || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ) 220. || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR 221. || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR 222. #ifdef SINKS 223. /* Thrown objects "sink" */ 224. || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) 225. #endif 226. ) { 227. drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 228. break; 229. } 230. tmp_at(bhitpos.x, bhitpos.y); 231. } 232. tmp_at(bhitpos.x, bhitpos.y); 233. tmp_at(-1, -1); 234. /* blindfold keeps substances out of your eyes */ 235. if (blindinc && !Blindfolded) { 236. u.ucreamed += blindinc; 237. make_blinded(Blinded + blindinc,FALSE); 238. } 239. } 240. 241. /* Remove an item from the monster's inventory. 242. */ 243. void 244. m_useup(mon, obj) 245. struct monst *mon; 246. struct obj *obj; 247. { 248. struct obj *otmp, *prev; 249. 250. prev = ((struct obj *) 0); 251. for (otmp = mon->minvent; otmp; otmp = otmp->nobj) { 252. if (otmp == obj) { 253. if (prev) 254. prev->nobj = obj->nobj; 255. else 256. mon->minvent = obj->nobj; 257. free((genericptr_t) obj); 258. break; 259. } 260. prev = otmp; 261. } 262. } 263. 264. /* Always returns 0??? -SAC */ 265. int 266. thrwmu(mtmp) /* monster throws item at you */ 267. register struct monst *mtmp; 268. { 269. struct obj *otmp, *select_rwep(); 270. register xchar x, y; 271. 272. if(lined_up(mtmp)) { 273. 274. if((otmp = select_rwep(mtmp))) { 275. 276. /* If you are coming toward the monster, the monster 277. * should try to soften you up with missiles. If you are 278. * going away, you are probably hurt or running. Give 279. * chase, but if you are getting too far away, throw. 280. */ 281. x = mtmp->mx; 282. y = mtmp->my; 283. if(!URETREATING(x,y) || 284. !rn2(BOLT_LIM-movedist(x,mtmp->mux,y,mtmp->muy))) 285. { 286. m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 287. movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp); 288. if (!otmp->quan) m_useup(mtmp, otmp); 289. nomul(0); 290. return 0; 291. } 292. } 293. } 294. return 0; 295. } 296. 297. int 298. spitmu(mtmp) /* monster spits substance at you */ 299. register struct monst *mtmp; 300. { 301. register struct obj *otmp; 302. 303. if(mtmp->mcan) { 304. 305. if(flags.soundok) 306. pline("A dry rattle comes from %s's throat", mon_nam(mtmp)); 307. return 0; 308. } 309. if(lined_up(mtmp)) { 310. otmp = mksobj(mtmp->data==&mons[PM_COBRA] ? 311. BLINDING_VENOM : ACID_VENOM, FALSE); 312. /* really incorrect; should check the attack type; this might 313. * fail if someone introduces another monster with a venom 314. * attack... 315. */ 316. if(!rn2(BOLT_LIM-movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy))) { 317. 318. m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 319. movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp); 320. nomul(0); 321. return 0; 322. } 323. } 324. return 0; 325. } 326. 327. int 328. breamu(mtmp, mattk) /* monster breathes at you (ranged) */ 329. register struct monst *mtmp; 330. register struct attack *mattk; 331. { 332. if(lined_up(mtmp)) { 333. 334. if(mtmp->mcan) { 335. if(flags.soundok) { 336. if(canseemon(mtmp)) 337. pline("%s coughs.", Monnam(mtmp)); 338. else 339. You("hear a cough."); 340. } 341. return(0); 342. } 343. if(rn2(3)) { 344. 345. if((mattk->adtyp >= 1) && (mattk->adtyp < 11)) { 346. 347. if(canseemon(mtmp)) 348. pline("%s breathes %s!", Monnam(mtmp), 349. breathwep[mattk->adtyp-1]); 350. buzz((int) (-20 - (mattk->adtyp-1)), (int)mattk->damn, 351. mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); 352. nomul(0); 353. } else impossible("Breath weapon %d used", mattk->adtyp-1); 354. } 355. } 356. return(1); 357. } 358. 359. boolean 360. linedup(ax, ay, bx, by) 361. register xchar ax, ay, bx, by; 362. { 363. register xchar x, y; 364. 365. tbx = ax - bx; /* These two values are set for use */ 366. tby = ay - by; /* after successful return. */ 367. 368. if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */ 369. && movedist(tbx, 0, tby, 0) < BOLT_LIM) { 370. 371. /* Check if there are any dead squares between. If so, 372. * it will not be possible to shoot. 373. */ 374. x = bx; y = by; 375. while(x != ax || y != ay) { 376. 377. if (!ACCESSIBLE(levl[x][y].typ) || 378. (IS_DOOR(levl[x][y].typ) && 379. (levl[x][y].doormask & (D_LOCKED | D_CLOSED)))) 380. return FALSE; 381. x += sgn(tbx), y += sgn(tby); 382. } 383. return TRUE; 384. } 385. return FALSE; 386. } 387. 388. boolean 389. lined_up(mtmp) /* is mtmp in position to use ranged attack? */ 390. register struct monst *mtmp; 391. { 392. return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); 393. } 394. 395. /* Check if a monster is carrying a particular item. 396. */ 397. struct obj * 398. m_carrying(mtmp, type) 399. struct monst *mtmp; 400. int type; 401. { 402. register struct obj *otmp; 403. 404. for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 405. if(otmp->otyp == type) 406. return(otmp); 407. return((struct obj *) 0); 408. } 409. 410. static int 411. movedist(x0, x1, y0, y1) 412. { 413. register int absdx, absdy; 414. 415. absdx = abs(x1 - x0); 416. absdy = abs(y1 - y0); 417. 418. return (max(absdx,absdy)); 419. }