Source:NetHack 3.0.0/weapon.c

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

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. }