Source:NetHack 3.1.0/weapon.c

Below is the full text to weapon.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	93/01/15	*/ 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.  #ifdef OVLB 13.   14.   static const char NEARDATA kebabable[] = { S_XORN, S_DRAGON, S_NAGA, S_GIANT, 0 }; 15.   16.   /*  17.    *	hitval returns an integer representing the "to hit" bonuses 18.   *	of "otmp" against the monster type "ptr". 19.   */  20.   int 21.  hitval(otmp, ptr) 22.  struct	obj *otmp; 23.  struct	permonst *ptr; 24.  {  25.   	int	tmp = 0; 26.   27.   	if (otmp->oclass == WEAPON_CLASS ||  28.   	    otmp->otyp == PICK_AXE || otmp->otyp == UNICORN_HORN) 29.  		tmp += otmp->spe; 30.   31.   /*	Put weapon specific "to hit" bonuses in below:		*/ 32.  	tmp += objects[otmp->otyp].oc_hitbon; 33.   34.   /*	Put weapon vs. monster type "to hit" bonuses in below:	*/ 35.   36.   	/* Blessed weapons used against undead or demons */ 37.  	if(otmp->oclass == WEAPON_CLASS && otmp->blessed &&  38.   	   (is_demon(ptr) || is_undead(ptr))) tmp += 2; 39.   40.   	if(otmp->otyp >= SPEAR && otmp->otyp <= JAVELIN &&  41.   	   index(kebabable, ptr->mlet)) tmp += 2; 42.   43.   	/* Check specially named weapon "to hit" bonuses */ 44.  	if (otmp->oartifact) tmp += spec_abon(otmp, ptr); 45.  	return tmp; 46.  }  47.    48.   /*  49.    *	dmgval returns an integer representing the damage bonuses 50.   *	of "otmp" against the monster type "ptr". 51.   */  52.   int 53.  dmgval(otmp, ptr) 54.  struct	obj *otmp; 55.  struct	permonst *ptr; 56.  {  57.   	int	tmp = 0; 58.   59.   	if(otmp->otyp == CREAM_PIE)	return(0); 60.   61.   	if(ptr->msize >= MZ_HUMAN) { 62.  	    if(objects[otmp->otyp].oc_wldam) 63.  		tmp = rnd(objects[otmp->otyp].oc_wldam); 64.  	    switch (otmp->otyp) { 65.  		case CROSSBOW_BOLT: 66.  		case MORNING_STAR: 67.  		case PARTISAN: 68.  		case ELVEN_BROADSWORD: 69.  		case BROADSWORD:	tmp++; break; 70.   71.   		case FLAIL: 72.  		case RANSEUR: 73.  		case VOULGE:		tmp += rnd(4); break; 74.   75.   		case ACID_VENOM: 76.  		case HALBERD: 77.  		case SPETUM:		tmp += rnd(6); break; 78.   79.   		case BATTLE_AXE: 80.  		case BARDICHE: 81.  		case TRIDENT:		tmp += d(2,4); break; 82.   83.   		case TSURUGI: 84.  		case DWARVISH_MATTOCK: 85.  		case TWO_HANDED_SWORD:	tmp += d(2,6); break; 86.  	    }  87.   	} else { 88.  	    if(objects[otmp->otyp].oc_wsdam) 89.  		tmp = rnd(objects[otmp->otyp].oc_wsdam); 90.  	    switch (otmp->otyp) { 91.  		case CROSSBOW_BOLT: 92.  		case MACE: 93.  		case WAR_HAMMER: 94.  		case FLAIL: 95.  		case SPETUM: 96.  		case TRIDENT:		tmp++; break; 97.   98.   		case BATTLE_AXE: 99.  		case BARDICHE: 100. 		case BILL_GUISARME: 101. 		case GUISARME: 102. 		case LUCERN_HAMMER: 103. 		case MORNING_STAR: 104. 		case RANSEUR: 105. 		case BROADSWORD: 106. 		case ELVEN_BROADSWORD: 107. 		case VOULGE:		tmp += rnd(4); break; 108.  109.  		case ACID_VENOM:	tmp += rnd(6); break; 110. 	    }  111.  	}  112.  	if (otmp->oclass == WEAPON_CLASS || otmp->otyp == PICK_AXE  113.  						|| otmp->otyp == UNICORN_HORN) 114. 		tmp += otmp->spe; 115.  116.  	tmp -= otmp->oeroded; 117.  118.  	if (objects[otmp->otyp].oc_material <= LEATHER && thick_skinned(ptr)) 119. 		/* thick skinned/scaled creatures don't feel it */ 120. 		tmp = 0; 121. 	if (ptr == &mons[PM_SHADE] && objects[otmp->otyp].oc_material != SILVER) 122. 		tmp = 0; 123.  124.  /*	Put weapon vs. monster type damage bonuses in below:	*/ 125. 	if(otmp->oclass == WEAPON_CLASS) { 126. 	    if (otmp->blessed && (is_undead(ptr) || is_demon(ptr))) 127. 		tmp += rnd(4); 128. 	    if ((otmp->otyp == AXE || otmp->otyp == BATTLE_AXE)  129.  		&& is_wooden(ptr)) 130. 		tmp += rnd(4); 131. 	    if (objects[otmp->otyp].oc_material == SILVER && hates_silver(ptr)) 132. 		tmp += rnd(20); 133. 	}  134.   135.  	return(tmp); 136. }  137.   138.  void 139. set_uasmon		/* update the "uasmon" structure */ 140. {  141.  #ifdef POLYSELF 142. 	if(u.umonnum >= 0) uasmon = &mons[u.umonnum]; 143. 	else { 144. #endif 145.  146.  		uasmon = &playermon; 147. 		playermon.mlevel = u.ulevel; 148. 		playermon.ac = u.uac; 149. 		playermon.mr = (u.ulevel > 8) ? 5 * (u.ulevel-7) : u.ulevel; 150. #ifdef POLYSELF 151. 	}  152.  #endif 153. 	return; 154. }  155.   156.  #endif /* OVLB */ 157. #ifdef OVL0 158.  159.  #define	Oselect(x)	if((otmp = oselect(mtmp, x))) return(otmp); 160.  161.  static struct obj * FDECL(oselect, (struct monst *,int)); 162.  163.  static struct obj * 164. oselect(mtmp, x)  165. struct monst *mtmp; 166. int x;  167. { 168.  	struct obj *otmp; 169.  170.  	for(otmp=mtmp->minvent; otmp; otmp = otmp->nobj) { 171. 		if (otmp->otyp == x && touch_artifact(otmp,mtmp)) 172. 			return otmp; 173. 	}  174.  	return (struct obj *)0; 175. }  176.   177.  static const int NEARDATA rwep[] = 178. 	{ DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN, 179. 	  SHURIKEN, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW, 180. 	  CROSSBOW_BOLT, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, ROCK, 181. 	  LOADSTONE, LUCKSTONE, DART, /* BOOMERANG, */ CREAM_PIE 182. 	  /* note: CREAM_PIE should NOT be #ifdef KOPS */ 183. 	  };  184.   185.  static struct obj *propellor; 186.  187.  struct obj * 188. select_rwep(mtmp)	/* select a ranged weapon for the monster */ 189. register struct monst *mtmp; 190. {  191.  	register struct obj *otmp; 192. 	int i;  193. 194. #ifdef KOPS 195. 	char mlet = mtmp->data->mlet; 196. #endif 197.  198.  	propellor = &zeroobj; 199. #ifdef KOPS 200. 	if(mlet == S_KOP)	/* pies are first choice for Kops */ 201. 	    Oselect(CREAM_PIE); 202. #endif 203. 	if(throws_rocks(mtmp->data))	/* ...boulders for giants */ 204. 	    Oselect(BOULDER); 205. 	/*  206.  	 * other than these two specific cases, always select the 207. 	 * most potent ranged weapon to hand. 208. 	 */  209.  	for (i = 0; i < SIZE(rwep); i++) { 210. 	    int prop; 211.  212.  	    propellor = &zeroobj; 213. 	    /* shooting gems from slings; this goes just before the darts */ 214. 	    if (rwep[i]==DART && !likes_gems(mtmp->data)  215.  			&& (propellor = m_carrying(mtmp, SLING))) { 216. 		for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) { 217. 		    if(otmp->oclass==GEM_CLASS &&  218.  				(otmp->otyp != LOADSTONE || !otmp->cursed)) 219. 			return(otmp); 220. 		}  221.  	    }  222.  	    prop = (objects[rwep[i]]).w_propellor; 223. 	    if (prop > 0) { 224. 		switch (prop) { 225. 		case WP_BOW: 226. 		  propellor = (oselect(mtmp, ELVEN_BOW)); 227. 		  if (!propellor) propellor = (oselect(mtmp, BOW)); 228. 		  if (!propellor) propellor = (oselect(mtmp, ORCISH_BOW)); 229. 		  break; 230. 		case WP_SLING: 231. 		  propellor = (oselect(mtmp, SLING)); 232. 		  break; 233. 		case WP_CROSSBOW: 234. 		  propellor = (oselect(mtmp, CROSSBOW)); 235. 		}  236.  #ifdef MUSE 237. 		if ((otmp = MON_WEP(mtmp)) && otmp->cursed && otmp != propellor  238.  				&& mtmp->weapon_check == NO_WEAPON_WANTED) 239. 			propellor = 0; 240. #endif 241. 	    }  242.  	    /* propellor = obj, propellor to use 243. 	     * propellor = &zeroobj, doesn't need a propellor 244. 	     * propellor = 0, needed one and didn't have one 245. 	     */  246.  	    if (propellor != 0) { 247. 		/* Note: cannot use m_carrying for loadstones, since it will 248. 		 * always select the first object of a type, and maybe the 249. 		 * monster is carrying two but only the first is unthrowable. 250. 		 */  251.  		if (rwep[i] != LOADSTONE) { 252. #ifdef MUSE 253. 			/* Don't throw a cursed weapon-in-hand */ 254. 			if ((otmp = oselect(mtmp, rwep[i]))  255.  			    && (!otmp->cursed || otmp != MON_WEP(mtmp))) 256. 				return(otmp); 257. #else 258. 			Oselect(rwep[i]); 259. #endif 260. 		} else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) { 261. 		    if (otmp->otyp == LOADSTONE && !otmp->cursed) 262. 			return otmp; 263. 		}  264.  	    }  265.  	  }  266.   267.  	/* failure */ 268. 	return (struct obj *)0; 269. }  270.   271.  /* 0 = used by any monster; 1 = only used by strong monsters */ 272. static const struct hwep { short otyp, big; } NEARDATA hwep[] = { 273. 	  {TSURUGI,1}, {RUNESWORD,0}, 274. 	  {DWARVISH_MATTOCK,1}, {TWO_HANDED_SWORD,1}, {BATTLE_AXE,1}, 275. 	  {KATANA,0}, {UNICORN_HORN,1}, {CRYSKNIFE,0}, 276. 	  {TRIDENT,0}, {LONG_SWORD,0}, {ELVEN_BROADSWORD,0}, {BROADSWORD,0}, 277. 	  {LUCERN_HAMMER,1}, {SCIMITAR,1}, {SILVER_SABER,0}, {HALBERD,1}, 278. 	  {PARTISAN,1}, {LANCE,1}, {FAUCHARD,1}, {BILL_GUISARME,1}, 279. 	  {BEC_DE_CORBIN,1}, {GUISARME,1}, {RANSEUR,1}, {SPETUM,1}, 280. 	  {VOULGE,1}, {BARDICHE,0}, {MORNING_STAR,0}, {GLAIVE,0}, 281. 	  {ELVEN_SHORT_SWORD,0}, {DWARVISH_SHORT_SWORD,0}, {SHORT_SWORD,0}, 282. 	  {ORCISH_SHORT_SWORD,0}, {MACE,0}, {AXE,0}, {DWARVISH_SPEAR,0}, 283. 	  {ELVEN_SPEAR,0}, {SPEAR,0}, {ORCISH_SPEAR,0}, {FLAIL,0}, 284. 	  {QUARTERSTAFF,1}, {JAVELIN,0}, {AKLYS,0}, {CLUB,0}, {PICK_AXE,0}, 285. #ifdef KOPS 286. 	  {RUBBER_HOSE,0}, 287. #endif /* KOPS */ 288. 	  {WAR_HAMMER,0}, {ELVEN_DAGGER,0}, {DAGGER,0}, {ORCISH_DAGGER,0}, 289. 	  {ATHAME,0}, {SCALPEL,0}, {KNIFE,0}, {WORM_TOOTH,0}, {BULLWHIP,0} 290. 	};  291.   292.  struct obj * 293. select_hwep(mtmp)	/* select a hand to hand weapon for the monster */ 294. register struct monst *mtmp; 295. {  296.  	register struct obj *otmp; 297. 	register int i;  298. register const struct hwep *hw; 299. 	boolean strong = strongmonst(mtmp->data); 300.  301.  	if(is_giant(mtmp->data))	/* giants just love to use clubs */ 302. 	    Oselect(CLUB); 303.  304.  	/* only strong monsters can wield big (esp. long) weapons */ 305. 	/* all monsters can wield the remaining weapons */ 306. 	for (i = 0, hw = hwep; i < SIZE(hwep); i++, hw++) 307. 	    if ((strong || !hw->big) &&  308.  #ifdef MUSE  309.  	      (!objects[hw->otyp].oc_bimanual || !which_armor(mtmp, W_ARMS)) &&  310.  #endif  311.  	(objects[hw->otyp].oc_material != SILVER || !hates_silver(mtmp->data))) 312. 		Oselect(hw->otyp); 313.  314.  	/* failure */ 315. 	return (struct obj *)0; 316. }  317.   318.  #ifdef MUSE 319. /* Called after polymorphing a monster, robbing it, etc.... Monsters 320.  * otherwise never unwield stuff on their own. Shouldn't print messages. 321.  */  322.  void 323. possibly_unwield(mon) 324. register struct monst *mon; 325. {  326.  	register struct obj *obj; 327. 	struct obj *otmp, *backobj, *mw_tmp; 328.  329.  	if (!(mw_tmp = MON_WEP(mon))) 330. 		return; 331. 	for(obj=mon->minvent; obj; obj=obj->nobj) 332. 		if (obj == mw_tmp) break; 333. 	if (!obj) { /* The weapon was stolen or destroyed */ 334. 		MON_NOWEP(mon); 335. 		mon->weapon_check = NEED_WEAPON; 336. 		return; 337. 	}  338.  	if (!attacktype(mon->data, AT_WEAP)) { 339. 		MON_NOWEP(mon); 340. 		mon->weapon_check = NO_WEAPON_WANTED; 341. 		if (cansee(mon->mx, mon->my)) { 342. 			pline("%s drops %s.", Monnam(mon),  343.  				distant_name(obj, doname)); 344. 		}  345.  		backobj = 0; 346. 		for(otmp = mon->minvent; otmp; otmp = otmp->nobj) { 347. 			/* flooreffects unnecessary, can't wield boulders */ 348. 			if (otmp == obj) { 349. 				if (!backobj) mon->minvent = otmp->nobj; 350. 				else backobj->nobj = otmp->nobj; 351. 				place_object(otmp, mon->mx, mon->my); 352. 				otmp->nobj = fobj; 353. 				fobj = otmp; 354. 				stackobj(fobj); 355. 				if(cansee(mon->mx,mon->my)) 356. 					newsym(mon->mx, mon->my); 357. 				break; 358. 			}  359.  			backobj = otmp; 360. 		}  361.  		return; 362. 	}  363.  	/* The remaining case where there is a change is where a monster 364. 	 * is polymorphed into a stronger/weaker monster with a different 365. 	 * choice of weapons. This has no parallel for players. It can 366. 	 * be handled by waiting until mon_wield_item is actually called. 367. 	 * Though the monster still wields the wrong weapon until then, 368. 	 * this is OK since the player can't see it. 369. 	 * Possible problem: big monster with big cursed weapon gets 370. 	 * polymorphed into little monster. But it's not quite clear how to 371. * handle this anyway.... 372. */ 373.  	mon->weapon_check = NEED_WEAPON; 374. 	return; 375. }  376.   377.  /* Let a monster try to wield a weapon, based on mon->weapon_check. 378.  * Returns 1 if the monster took time to do it, 0 if it did not. 379.  */  380.  int 381. mon_wield_item(mon) 382. register struct monst *mon; 383. {  384.  	struct obj *obj; 385.  386.  	/* This case actually should never happen */ 387. 	if (mon->weapon_check == NO_WEAPON_WANTED) return 0; 388.  389.  	switch(mon->weapon_check) { 390. 		case NEED_HTH_WEAPON: 391. 			obj = select_hwep(mon); 392. 			break; 393. 		case NEED_RANGED_WEAPON: 394. 			(void)select_rwep(mon); 395. 			obj = propellor; 396. 			break; 397. 		case NEED_PICK_AXE: 398. 			obj = m_carrying(mon, PICK_AXE); 399. 			break; 400. 		default: impossible("weapon_check %d for %s?",  401.  				mon->weapon_check, mon_nam(mon)); 402. 			return 0; 403. 	}  404.  	if (obj && obj != &zeroobj) { 405. 		struct obj *mw_tmp = MON_WEP(mon); 406. 		if (mw_tmp == obj) { /* already wielding it */ 407. 			mon->weapon_check = NEED_WEAPON; 408. 			return 0; 409. 		}  410.  		/* Actually, this isn't necessary--as soon as the monster 411. 		 * wields the weapon, the weapon welds itself, so the monster 412. 		 * can know it's cursed and needn't even bother trying. 413. 		 * Still....  414. */ 415.  		if (mw_tmp && mw_tmp->cursed) { 416. 		    if (obj->otyp == PICK_AXE) { 417. 			if (canseemon(mon)) { 418. 			    pline("Since %s weapon %s welded to %s hand,",  419.  				s_suffix(mon_nam(mon)),  420.  				(mw_tmp->quan == 1L) ? "is" : "are",  421.  				humanoid(mon->data)  422.  					? (mon->female ? "her" : "his") 423.  					: "its"); 424. 			    pline("%s cannot wield that %s.",  425.  				mon_nam(mon), xname(obj)); 426. 			    mw_tmp->bknown = 1; 427. 			}  428.  		    } else { 429. 			if (canseemon(mon)) { 430. 			    pline("%s tries to wield %s.", Monnam(mon),  431.  				doname(obj)); 432. 			    pline("%s %s %s welded to %s hand!",  433.  				s_suffix(Monnam(mon)), xname(mw_tmp),  434.  				(mw_tmp->quan == 1L) ? "is" : "are",  435.  				humanoid(mon->data)  436.  					? (mon->female ? "her" : "his") 437.  					: "its"); 438. 			    mw_tmp->bknown = 1; 439. 			}  440.  		    }  441.  		    mon->weapon_check = NO_WEAPON_WANTED; 442. 		    return 1; 443. 		}  444.  		mon->mw = obj;		/* wield obj */ 445. 		mon->weapon_check = NEED_WEAPON; 446. 		if (canseemon(mon)) { 447. 			pline("%s wields %s!", Monnam(mon), doname(obj)); 448. 			if (obj->cursed) { 449. 				pline("%s %s to %s hand!",  450.  					The(xname(obj)),  451.  					(obj->quan == 1L) ? "welds itself"  452.  					    : "weld themselves",  453.  					s_suffix(mon_nam(mon))); 454. 				obj->bknown = 1; 455. 			}  456.  		}  457.  		return 1; 458. 	}  459.  	mon->weapon_check = NEED_WEAPON; 460. 	return 0; 461. }  462.   463.  /* rearrange a monster's inventory so that wielded weapon is first */ 464. void 465. sort_mwep(mon) 466. struct monst *mon; 467. {  468.  	struct obj *otmp, *prev, *mw_tmp = MON_WEP(mon); 469.  470.  	if (!mw_tmp) return; 471. 	for (otmp = mon->minvent, prev = 0; otmp; otmp = otmp->nobj) { 472. 		if (otmp == mw_tmp)  break; 473. 		prev = otmp; 474. 	}  475.  	if (!otmp) { 476. 		MON_NOWEP(mon); 477. 	} else if (prev) { 478. 		prev->nobj = otmp->nobj; 479. 		otmp->nobj = mon->minvent; 480. 		mon->minvent = otmp; 481. 	}  482.  }  483.  #endif 484.  485.  int 486. abon {	/* attack bonus for strength & dexterity */ 487. 	int	sbon; 488. 	register int	str = ACURR(A_STR), dex = ACURR(A_DEX); 489.  490.  #ifdef POLYSELF 491. 	if (u.umonnum >= 0) return(adj_lev(&mons[u.umonnum])-3); 492. #endif 493. 	if (str < 6) sbon = -2; 494. 	else if (str < 8) sbon = -1; 495. 	else if (str < 17) sbon = 0; 496. 	else if (str < 69) sbon = 1;	/* up to 18/50 */ 497. 	else if (str < 118) sbon = 2; 498. 	else sbon = 3; 499. /*  500.   *	Temporary kludge - make it a bit easier for a low level character 501.  *			   to hit until we tune the game a little better. 502.  */  503.  	sbon += (u.ulevel < 3) ? 1 : 0; 504.   505.  	if (dex < 4) return(sbon-3); 506. 	else if (dex < 6) return(sbon-2); 507. 	else if (dex < 8) return(sbon-1); 508. 	else if (dex < 14) return(sbon); 509. 	else return(sbon + dex-14); 510. }  511.   512.  #endif /* OVL0 */ 513. #ifdef OVL1 514.  515.  int 516. dbon {	/* damage bonus for strength */ 517. 	register int	str = ACURR(A_STR); 518.  519.  #ifdef POLYSELF 520. 	if (u.umonnum >= 0) return(0); 521. #endif 522.  523.  	if (str < 6) return(-1); 524. 	else if (str < 16) return(0); 525. 	else if (str < 18) return(1); 526. 	else if (str == 18) return(2);		/* up to 18 */ 527. 	else if (str < 94) return(3);		/* up to 18/75 */ 528. 	else if (str < 109) return(4);		/* up to 18/90 */ 529. 	else if (str < 118) return(5);		/* up to 18/99 */ 530. 	else return(6); 531. }  532.   533.  #endif /* OVL1 */ 534.  535.  /*weapon.c*/