Source:NetHack 3.0.0/weapon.c
Jump to navigation
Jump to search
Below is the full text to weapon.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/weapon.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: @(#)weapon.c 3.0 89/04/24 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. /* 6. * This module contains code for calculation of "to hit" and damage 7. * bonuses for any given weapon used, as well as weapons selection 8. * code for monsters. 9. */ 10. #include "hack.h" 11. 12. static const char kebabable[] = { S_XORN, S_DRAGON, S_NAGA, S_GIANT, 0 }; 13. 14. /* 15. * hitval returns an integer representing the "to hit" bonuses 16. * of "otmp" against the monster type "ptr". 17. */ 18. int 19. hitval(otmp, ptr) 20. struct obj *otmp; 21. struct permonst *ptr; 22. { 23. int tmp = 0; 24. 25. if(otmp->olet == WEAPON_SYM || otmp->otyp == PICK_AXE) 26. tmp += otmp->spe; 27. 28. /* Put weapon specific "to hit" bonuses in below: */ 29. switch(otmp->otyp) { 30. 31. #ifdef TOLKIEN 32. case DWARVISH_MATTOCK: 33. #endif 34. case TWO_HANDED_SWORD: tmp -= 1; break; 35. case KATANA: tmp += 1; break; 36. #ifdef TOLKIEN 37. case ELVEN_DAGGER: 38. case ORCISH_DAGGER: 39. #endif 40. case DAGGER: 41. case SHURIKEN: tmp += 2; break; 42. #ifdef WORM 43. case CRYSKNIFE: tmp += 3; break; 44. #endif 45. } 46. 47. /* Put weapon vs. monster type "to hit" bonuses in below: */ 48. 49. /* Blessed weapons used against undead or demons */ 50. if(otmp->olet == WEAPON_SYM && otmp->blessed && 51. (is_demon(ptr) || is_undead(ptr))) tmp += 2; 52. 53. if(otmp->otyp >= SPEAR && otmp->otyp <= JAVELIN && 54. index(kebabable, ptr->mlet)) tmp += 2; 55. 56. /* Put specially named weapon "to hit" bonuses in below: */ 57. #ifdef NAMED_ITEMS 58. tmp += spec_abon(otmp, ptr); 59. #endif 60. return(tmp); 61. } 62. 63. /* 64. * dmgval returns an integer representing the damage bonuses 65. * of "otmp" against the monster type "ptr". 66. */ 67. int 68. dmgval(otmp, ptr) 69. struct obj *otmp; 70. struct permonst *ptr; 71. { 72. int tmp = 0; 73. 74. if(otmp->otyp == CREAM_PIE) return(0); 75. 76. if(bigmonst(ptr)) { 77. if(objects[otmp->otyp].wldam) 78. tmp = rnd(objects[otmp->otyp].wldam); 79. switch (otmp->otyp) { 80. case CROSSBOW_BOLT: 81. case MORNING_STAR: 82. case PARTISAN: 83. #ifdef TOLKIEN 84. case ELVEN_BROADSWORD: 85. #endif 86. case BROADSWORD: tmp += 1; break; 87. 88. case FLAIL: 89. case RANSEUR: 90. case VOULGE: tmp += rnd(4); break; 91. 92. case ACID_VENOM: 93. case HALBERD: 94. case SPETUM: tmp += rnd(6); break; 95. 96. case BARDICHE: 97. case TRIDENT: tmp += d(2,4); break; 98. 99. #ifdef TOLKIEN 100. case DWARVISH_MATTOCK: 101. #endif 102. case TWO_HANDED_SWORD: tmp += d(2,6); break; 103. } 104. } else { 105. if(objects[otmp->otyp].wsdam) 106. tmp = rnd(objects[otmp->otyp].wsdam); 107. switch (otmp->otyp) { 108. case CROSSBOW_BOLT: 109. case MACE: 110. case FLAIL: 111. case SPETUM: 112. case TRIDENT: tmp += 1; break; 113. 114. case BARDICHE: 115. case BILL_GUISARME: 116. case GUISARME: 117. case LUCERN_HAMMER: 118. case MORNING_STAR: 119. case RANSEUR: 120. case BROADSWORD: 121. #ifdef TOLKIEN 122. case ELVEN_BROADSWORD: 123. #endif 124. case VOULGE: tmp += rnd(4); break; 125. 126. case ACID_VENOM: tmp += rnd(6); break; 127. } 128. } 129. if (otmp->otyp == BULLWHIP && thick_skinned(ptr)) 130. /* thick skinned/scaled creatures don't feel it */ 131. tmp = 0; 132. if (otmp->olet == WEAPON_SYM || otmp->otyp == PICK_AXE) 133. tmp += otmp->spe; 134. 135. /* Put weapon vs. monster type damage bonuses in below: */ 136. if(otmp->olet == WEAPON_SYM) { 137. if (otmp->blessed && (is_undead(ptr) || is_demon(ptr))) 138. tmp += rnd(4); 139. } 140. 141. /* Put specially named weapon damage bonuses in below: */ 142. #ifdef NAMED_ITEMS 143. tmp += spec_dbon(otmp, ptr, tmp); 144. #endif 145. return(tmp); 146. } 147. 148. void 149. set_uasmon() { /* update the "uasmon" structure */ 150. 151. #ifdef POLYSELF 152. if(u.umonnum >= 0) uasmon = &mons[u.umonnum]; 153. else { 154. #endif 155. 156. uasmon = &playermon; 157. playermon.mlevel = u.ulevel; 158. playermon.ac = u.uac; 159. playermon.mr = (u.ulevel > 8) ? 5 * (u.ulevel-7) : u.ulevel; 160. #ifdef POLYSELF 161. } 162. #endif 163. return; 164. } 165. 166. #define Oselect(x) if((otmp = m_carrying(mtmp, x))) return(otmp); 167. 168. #ifdef TOLKIEN 169. static const int rwep[] = 170. { DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN, 171. SHURIKEN, ELVEN_ARROW, ARROW, ORCISH_ARROW, CROSSBOW_BOLT, 172. ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, ROCK, LOADSTONE, 173. LUCKSTONE, DART, BOOMERANG, CREAM_PIE 174. /* note: CREAM_PIE should NOT be #ifdef KOPS */ 175. }; 176. #else 177. static const int rwep[] = 178. { SPEAR, JAVELIN, SHURIKEN, ARROW, CROSSBOW_BOLT, DAGGER, KNIFE, 179. ROCK, LOADSTONE, LUCKSTONE, DART, BOOMERANG, CREAM_PIE 180. /* note: CREAM_PIE should NOT be #ifdef KOPS */ 181. }; 182. #endif 183. 184. struct obj * 185. select_rwep(mtmp) /* select a ranged weapon for the monster */ 186. register struct monst *mtmp; 187. { 188. register struct obj *otmp; 189. int i; 190. #ifdef KOPS 191. char mlet = mtmp->data->mlet; 192. 193. if(mlet == S_KOP) /* pies are first choice for Kops */ 194. Oselect(CREAM_PIE); 195. #endif 196. if(throws_rocks(mtmp->data)) /* ...boulders for giants */ 197. Oselect(BOULDER); 198. /* 199. * other than these two specific cases, always select the 200. * most potent ranged weapon to hand. 201. */ 202. for (i = 0; i < SIZE(rwep); i++) { 203. boolean no_propellor = FALSE; 204. int prop; 205. 206. /* shooting gems from slings; this goes just before the darts */ 207. if (rwep[i]==DART && !likes_gems(mtmp->data) 208. /* && m_carrying(mtmp, SLING) */) { 209. for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) { 210. if(otmp->olet==GEM_SYM && 211. (otmp->otyp != LOADSTONE || !otmp->cursed)) 212. return(otmp); 213. } 214. } 215. prop = (objects[rwep[i]]).w_propellor; 216. if (prop > 0) { 217. switch (prop) { 218. case WP_BOW: 219. #ifdef TOLKIEN 220. no_propellor = !(m_carrying(mtmp, BOW) || 221. m_carrying(mtmp, ELVEN_BOW) || 222. m_carrying(mtmp, ORCISH_BOW)); 223. #else 224. no_propellor = !(m_carrying(mtmp, BOW)); 225. #endif 226. break; 227. /* case WP_SLING: 228. no_propellor = (m_carrying(mtmp, SLING) != 0); 229. break; */ 230. case WP_CROSSBOW: 231. no_propellor = (m_carrying(mtmp, CROSSBOW) != 0); 232. } 233. } 234. if (!no_propellor) Oselect(rwep[i]); 235. } 236. 237. /* failure */ 238. return (struct obj *)0; 239. } 240. 241. #ifdef TOLKIEN 242. /* 0 = used by any monster; 1 = only used by strong monsters */ 243. static const int hwep[][2] = 244. { {DWARVISH_MATTOCK,1}, {TWO_HANDED_SWORD,1}, {KATANA,0}, 245. #ifdef WORM 246. {CRYSKNIFE,0}, 247. #endif 248. {TRIDENT,0}, {LONG_SWORD,0}, {ELVEN_BROADSWORD,0}, {BROADSWORD,0}, 249. {LUCERN_HAMMER,1}, {SCIMITAR,1}, {HALBERD,1}, {PARTISAN,1}, 250. {LANCE,1}, {FAUCHARD,1}, {BILL_GUISARME,1}, {BEC_DE_CORBIN,1}, 251. {GUISARME,1}, {RANSEUR,1}, {SPETUM,1}, {VOULGE,1}, {BARDICHE,0}, 252. {MORNING_STAR,0}, {GLAIVE,0}, {ELVEN_SHORT_SWORD,0}, 253. {DWARVISH_SHORT_SWORD,0}, {SHORT_SWORD,0}, {ORCISH_SHORT_SWORD,0}, 254. {MACE,0}, {AXE,0}, {DWARVISH_SPEAR,0}, {ELVEN_SPEAR,0}, {SPEAR,0}, 255. {ORCISH_SPEAR,0}, {FLAIL,0}, {QUARTERSTAFF,1}, {JAVELIN,0}, 256. {AKLYS,0}, {CLUB,0}, {PICK_AXE,0}, 257. #ifdef KOPS 258. {RUBBER_HOSE,0}, 259. #endif /* KOPS */ 260. {ELVEN_DAGGER,0}, {DAGGER,0}, {ORCISH_DAGGER,0}, {SCALPEL,0}, 261. {KNIFE,0}, 262. #ifdef WORM 263. {WORM_TOOTH,0}, 264. #endif 265. {BULLWHIP,0} 266. }; 267. #else /* TOLKIEN */ 268. /* 0 = used by any monster; 1 = only used by strong monsters */ 269. static const int hwep[][2] = 270. { {TWO_HANDED_SWORD,1}, {KATANA,0}, 271. #ifdef WORM 272. {CRYSKNIFE,0}, 273. #endif 274. {TRIDENT,0}, {LONG_SWORD,0}, {BROADSWORD,0}, {LUCERN_HAMMER,1}, 275. {SCIMITAR,1}, {HALBERD,1}, {PARTISAN,1}, {LANCE,1}, {FAUCHARD,1}, 276. {BILL_GUISARME,1}, {BEC_DE_CORBIN,1}, {GUISARME,1}, {RANSEUR,1}, 277. {SPETUM,1}, {VOULGE,1}, {BARDICHE,0}, {MORNING_STAR,0}, {GLAIVE,0}, 278. {SHORT_SWORD,0}, {MACE,0}, {AXE,0}, {SPEAR,0}, {FLAIL,0}, 279. {QUARTERSTAFF,1}, {JAVELIN,0}, {AKLYS,0}, {CLUB,0}, {PICK_AXE,0}, 280. #ifdef KOPS 281. {RUBBER_HOSE,0}, 282. #endif /* KOPS */ 283. {DAGGER,0}, {SCALPEL,0}, {KNIFE,0}, 284. #ifdef WORM 285. {WORM_TOOTH,0}, 286. #endif 287. {BULLWHIP,0} 288. }; 289. #endif /* TOLKIEN */ 290. 291. struct obj * 292. select_hwep(mtmp) /* select a hand to hand weapon for the monster */ 293. register struct monst *mtmp; 294. { 295. register struct obj *otmp; 296. int i; 297. boolean strong = strongmonst(mtmp->data); 298. 299. if(is_giant(mtmp->data)) /* giants just love to use clubs */ 300. Oselect(CLUB); 301. 302. /* only strong monsters can wield big (esp. long) weapons */ 303. /* all monsters can wield the remaining weapons */ 304. for (i = 0; i < SIZE(hwep); i++) 305. if (strong || hwep[i][1]==0) 306. Oselect(hwep[i][0]); 307. 308. /* failure */ 309. return (struct obj *)0; 310. } 311. 312. int 313. abon() { /* attack bonus for strength & dexterity */ 314. int sbon; 315. 316. #ifdef POLYSELF 317. if (u.umonnum >= 0) return(adj_lev(&mons[u.umonnum])-3); 318. #endif 319. if(ACURR(A_STR) < 6) sbon = -2; 320. else if(ACURR(A_STR) < 8) sbon = -1; 321. else if(ACURR(A_STR) < 17) sbon = 0; 322. else if(ACURR(A_STR) < 69) sbon = 1; /* up to 18/50 */ 323. else if(ACURR(A_STR) < 118) sbon = 2; 324. else sbon = 3; 325. 326. if(ACURR(A_DEX) < 4) return(sbon-3); 327. else if(ACURR(A_DEX) < 6) return(sbon-2); 328. else if(ACURR(A_DEX) < 8) return(sbon-1); 329. else if(ACURR(A_DEX) < 14) return(sbon); 330. else return(sbon+ACURR(A_DEX)-15); 331. } 332. 333. int 334. dbon() { /* damage bonus for strength */ 335. #ifdef POLYSELF 336. if (u.umonnum >= 0) return(0); 337. #endif 338. 339. if(ACURR(A_STR) < 6) return(-1); 340. else if(ACURR(A_STR) < 16) return(0); 341. else if(ACURR(A_STR) < 18) return(1); 342. else if(ACURR(A_STR) == 18) return(2); /* up to 18 */ 343. else if(ACURR(A_STR) < 94) return(3); /* up to 18/75 */ 344. else if(ACURR(A_STR) < 109) return(4); /* up to 18/90 */ 345. else if(ACURR(A_STR) < 118) return(5); /* up to 18/99 */ 346. else return(6); 347. }