ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/weapon.c

This is weapon.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)weapon.c	3.0	89/11/19
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

/*
 *	This module contains code for calculation of "to hit" and damage
 *	bonuses for any given weapon used, as well as weapons selection
 *	code for monsters.
 */
#include	"hack.h"

#ifdef OVLB

static const char kebabable[] = { S_XORN, S_DRAGON, S_NAGA, S_GIANT, 0 };

/*
 * 	hitval returns an integer representing the "to hit" bonuses
 *	of "otmp" against the monster type "ptr".
 */
int
hitval(otmp, ptr)
struct	obj *otmp;
struct	permonst *ptr;
{
	int	tmp = 0;

	if(otmp->olet == WEAPON_SYM || otmp->otyp == PICK_AXE
						|| otmp->otyp == UNICORN_HORN)
		tmp += otmp->spe;

/*	Put weapon specific "to hit" bonuses in below:		*/
	switch(otmp->otyp) {

#ifdef TOLKIEN
	    case DWARVISH_MATTOCK:
#endif
	    case TWO_HANDED_SWORD:	tmp -= 1; break;
	    case KATANA:		tmp += 1; break;
#ifdef TOLKIEN
	    case ELVEN_DAGGER:
	    case ORCISH_DAGGER:
#endif
	    case DAGGER:
	    case SCALPEL:
	    case ATHAME:
	    case SHURIKEN:		tmp += 2; break;
#ifdef WORM
	    case CRYSKNIFE:		tmp += 3; break;
#endif
	}

/*	Put weapon vs. monster type "to hit" bonuses in below:	*/

	/* Blessed weapons used against undead or demons */
	if(otmp->olet == WEAPON_SYM && otmp->blessed &&
	   (is_demon(ptr) || is_undead(ptr))) tmp += 2;

	if(otmp->otyp >= SPEAR && otmp->otyp <= JAVELIN &&
	   index(kebabable, ptr->mlet)) tmp += 2;

/*	Put specially named weapon "to hit" bonuses in below:	*/
#ifdef NAMED_ITEMS
	tmp += spec_abon(otmp, ptr);
#endif
	return(tmp);
}

/*
 * 	dmgval returns an integer representing the damage bonuses
 *	of "otmp" against the monster type "ptr".
 */
int
dmgval(otmp, ptr)
struct	obj *otmp;
struct	permonst *ptr;
{
	int	tmp = 0;

	if(otmp->otyp == CREAM_PIE)	return(0);

	if(ptr->msize >= MZ_HUMAN) {
	    if(objects[otmp->otyp].wldam)
		tmp = rnd(objects[otmp->otyp].wldam);
	    switch (otmp->otyp) {
		case CROSSBOW_BOLT:
		case MORNING_STAR:
		case PARTISAN:
#ifdef TOLKIEN
		case ELVEN_BROADSWORD:
#endif
		case BROADSWORD:	tmp++; break;

		case FLAIL:
		case RANSEUR:
		case VOULGE:		tmp += rnd(4); break;

		case ACID_VENOM:
		case HALBERD:
		case SPETUM:		tmp += rnd(6); break;

		case BARDICHE:
		case TRIDENT:		tmp += d(2,4); break;

#ifdef TOLKIEN
		case DWARVISH_MATTOCK:
#endif
		case TWO_HANDED_SWORD:	tmp += d(2,6); break;
	    }
	} else {
	    if(objects[otmp->otyp].wsdam)
		tmp = rnd(objects[otmp->otyp].wsdam);
	    switch (otmp->otyp) {
		case CROSSBOW_BOLT:
		case MACE:
		case WAR_HAMMER:
		case FLAIL:
		case SPETUM:
		case TRIDENT:		tmp++; break;

		case BARDICHE:
		case BILL_GUISARME:
		case GUISARME:
		case LUCERN_HAMMER:
		case MORNING_STAR:
		case RANSEUR:
		case BROADSWORD:
#ifdef TOLKIEN
		case ELVEN_BROADSWORD:
#endif
		case VOULGE:		tmp += rnd(4); break;

		case ACID_VENOM:	tmp += rnd(6); break;
	    }
	}
	if (otmp->otyp == BULLWHIP && thick_skinned(ptr))
		/* thick skinned/scaled creatures don't feel it */
		tmp = 0;
	if (otmp->olet == WEAPON_SYM || otmp->otyp == PICK_AXE
						|| otmp->otyp == UNICORN_HORN)
		tmp += otmp->spe;

/*	Put weapon vs. monster type damage bonuses in below:	*/
	if(otmp->olet == WEAPON_SYM) {
	    if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
		tmp += rnd(4);
	}

/*	Put specially named weapon damage bonuses in below:	*/
#ifdef NAMED_ITEMS
	tmp += spec_dbon(otmp, ptr, tmp);
#endif
	return(tmp);
}

void
set_uasmon() {		/* update the "uasmon" structure */

#ifdef POLYSELF
	if(u.umonnum >= 0) uasmon = &mons[u.umonnum];
	else {
#endif

		uasmon = &playermon;
		playermon.mlevel = u.ulevel;
		playermon.ac = u.uac;
		playermon.mr = (u.ulevel > 8) ? 5 * (u.ulevel-7) : u.ulevel;
#ifdef POLYSELF
	}
#endif
	return;
}

#endif /* OVLB */
#ifdef OVL0

#define	Oselect(x)	if((otmp = m_carrying(mtmp, x))) return(otmp);

#ifdef TOLKIEN
static const int rwep[] =
	{ DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
	  SHURIKEN, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
	  CROSSBOW_BOLT, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, ROCK,
	  LOADSTONE, LUCKSTONE, DART, BOOMERANG, CREAM_PIE
	  /* note: CREAM_PIE should NOT be #ifdef KOPS */
	  };
#else
static const int rwep[] =
	{ SPEAR, JAVELIN, SHURIKEN, SILVER_ARROW, ARROW, CROSSBOW_BOLT,
	  DAGGER, KNIFE, ROCK, LOADSTONE, LUCKSTONE, DART, BOOMERANG, CREAM_PIE
	  /* note: CREAM_PIE should NOT be #ifdef KOPS */
	  };
#endif

struct obj *
select_rwep(mtmp)	/* select a ranged weapon for the monster */
register struct monst *mtmp;
{
	register struct obj *otmp;
	int i;
#ifdef KOPS
	char mlet = mtmp->data->mlet;

	if(mlet == S_KOP)	/* pies are first choice for Kops */
	    Oselect(CREAM_PIE);
#endif
	if(throws_rocks(mtmp->data))	/* ...boulders for giants */
	    Oselect(BOULDER);
	/*
	 * other than these two specific cases, always select the
	 * most potent ranged weapon to hand.
	 */
	for (i = 0; i < SIZE(rwep); i++) {
	    boolean no_propellor = FALSE;
	    int prop;

	    /* shooting gems from slings; this goes just before the darts */
	    if (rwep[i]==DART && !likes_gems(mtmp->data)
			&& m_carrying(mtmp, SLING)) {
		for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
		    if(otmp->olet==GEM_SYM &&
				(otmp->otyp != LOADSTONE || !otmp->cursed))
			return(otmp);
		}
	    }
	    prop = (objects[rwep[i]]).w_propellor;
	    if (prop > 0) {
		switch (prop) {
		case WP_BOW:
#ifdef TOLKIEN
		  no_propellor = !(m_carrying(mtmp, BOW) ||
				   m_carrying(mtmp, ELVEN_BOW) ||
				   m_carrying(mtmp, ORCISH_BOW));
#else
		  no_propellor = !(m_carrying(mtmp, BOW));
#endif
		  break;
		case WP_SLING:
		  no_propellor = !(m_carrying(mtmp, SLING));
		  break;
		case WP_CROSSBOW:
		  no_propellor = !(m_carrying(mtmp, CROSSBOW));
		}
	      }
	    if (!no_propellor) {
		/* Note: cannot use m_carrying for loadstones, since it will
		 * always select the first object of a type, and maybe the
		 * monster is carrying two but only the first is unthrowable.
		 */
		if (rwep[i] != LOADSTONE) {
			Oselect(rwep[i]);
		} else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
		    if (otmp->otyp == LOADSTONE && !otmp->cursed)
			return otmp;
		}
	    }
	  }

	/* failure */
	return (struct obj *)0;
}

#ifdef TOLKIEN
/* 0 = used by any monster; 1 = only used by strong monsters */
static const int hwep[][2] =
	{ {DWARVISH_MATTOCK,1}, {TWO_HANDED_SWORD,1}, {KATANA,0},
	  {UNICORN_HORN,1},
#ifdef WORM
	  {CRYSKNIFE,0},
#endif
	  {TRIDENT,0}, {LONG_SWORD,0}, {ELVEN_BROADSWORD,0}, {BROADSWORD,0},
	  {LUCERN_HAMMER,1}, {SCIMITAR,1}, {HALBERD,1}, {PARTISAN,1},
	  {LANCE,1}, {FAUCHARD,1}, {BILL_GUISARME,1}, {BEC_DE_CORBIN,1},
	  {GUISARME,1}, {RANSEUR,1}, {SPETUM,1}, {VOULGE,1}, {BARDICHE,0},
	  {MORNING_STAR,0}, {GLAIVE,0}, {ELVEN_SHORT_SWORD,0},
	  {DWARVISH_SHORT_SWORD,0}, {SHORT_SWORD,0}, {ORCISH_SHORT_SWORD,0},
	  {MACE,0}, {AXE,0}, {DWARVISH_SPEAR,0}, {ELVEN_SPEAR,0}, {SPEAR,0},
	  {ORCISH_SPEAR,0}, {FLAIL,0}, {QUARTERSTAFF,1}, {JAVELIN,0},
	  {AKLYS,0}, {CLUB,0}, {PICK_AXE,0},
#ifdef KOPS
	  {RUBBER_HOSE,0},
#endif /* KOPS */
	  {WAR_HAMMER,0}, {ELVEN_DAGGER,0}, {DAGGER,0}, {ORCISH_DAGGER,0},
	  {ATHAME,0}, {SCALPEL,0}, {KNIFE,0},
#ifdef WORM
	  {WORM_TOOTH,0},
#endif
	  {BULLWHIP,0}
	};
#else /* TOLKIEN */
/* 0 = used by any monster; 1 = only used by strong monsters */
static const int hwep[][2] =
	{ {TWO_HANDED_SWORD,1}, {KATANA,0}, {UNICORN_HORN,1},
#ifdef WORM
	  {CRYSKNIFE,0},
#endif
	  {TRIDENT,0}, {LONG_SWORD,0}, {BROADSWORD,0}, {LUCERN_HAMMER,1},
	  {SCIMITAR,1}, {HALBERD,1}, {PARTISAN,1}, {LANCE,1}, {FAUCHARD,1},
	  {BILL_GUISARME,1}, {BEC_DE_CORBIN,1}, {GUISARME,1}, {RANSEUR,1},
	  {SPETUM,1}, {VOULGE,1}, {BARDICHE,0}, {MORNING_STAR,0}, {GLAIVE,0},
	  {SHORT_SWORD,0}, {MACE,0}, {AXE,0}, {SPEAR,0}, {FLAIL,0},
	  {QUARTERSTAFF,1}, {JAVELIN,0}, {AKLYS,0}, {CLUB,0}, {PICK_AXE,0},
#ifdef KOPS
	  {RUBBER_HOSE,0},
#endif /* KOPS */
	  {WAR_HAMMER,0}, {DAGGER,0}, {ATHAME,0}, {SCALPEL,0}, {KNIFE,0},
#ifdef WORM
	  {WORM_TOOTH,0},
#endif
	  {BULLWHIP,0}
	};
#endif /* TOLKIEN */

struct obj *
select_hwep(mtmp)	/* select a hand to hand weapon for the monster */
register struct monst *mtmp;
{
	register struct obj *otmp;
	int i;
	boolean strong = strongmonst(mtmp->data);

	if(is_giant(mtmp->data))	/* giants just love to use clubs */
	    Oselect(CLUB);

	/* only strong monsters can wield big (esp. long) weapons */
	/* all monsters can wield the remaining weapons */
	for (i = 0; i < SIZE(hwep); i++)
	    if (strong || hwep[i][1]==0)
		Oselect(hwep[i][0]);

	/* failure */
	return (struct obj *)0;
}

int
abon() {	/* attack bonus for strength & dexterity */
	int	sbon;

#ifdef POLYSELF
	if (u.umonnum >= 0) return(adj_lev(&mons[u.umonnum])-3);
#endif
	if(ACURR(A_STR) < 6) sbon = -2;
	else if(ACURR(A_STR) < 8) sbon = -1;
	else if(ACURR(A_STR) < 17) sbon = 0;
	else if(ACURR(A_STR) < 69) sbon = 1;	/* up to 18/50 */
	else if(ACURR(A_STR) < 118) sbon = 2;
	else sbon = 3;
/*
 *	Temporary kludge - make it a bit easier for a low level character
 *			   to hit until we tune the game a little better.
 */
	sbon += (u.ulevel < 3) ? 2 : (u.ulevel < 5) ? 1 : 0;

	if(ACURR(A_DEX) < 4) return(sbon-3);
	else if(ACURR(A_DEX) < 6) return(sbon-2);
	else if(ACURR(A_DEX) < 8) return(sbon-1);
	else if(ACURR(A_DEX) < 14) return(sbon);
	else return(sbon+ACURR(A_DEX)-14);
}

#endif /* OVL0 */
#ifdef OVL1

int
dbon() {	/* damage bonus for strength */
#ifdef POLYSELF
	if (u.umonnum >= 0) return(0);
#endif

	if(ACURR(A_STR) < 6) return(-1);
	else if(ACURR(A_STR) < 16) return(0);
	else if(ACURR(A_STR) < 18) return(1);
	else if(ACURR(A_STR) == 18) return(2);		/* up to 18 */
	else if(ACURR(A_STR) < 94) return(3);		/* up to 18/75 */
	else if(ACURR(A_STR) < 109) return(4);		/* up to 18/90 */
	else if(ACURR(A_STR) < 118) return(5);	/* up to 18/99 */
	else return(6);
}

#endif /* OVL1 */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.