Source:NetHack 3.3.0/weapon.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to weapon.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.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.3	1999/11/29	*/
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.   /* Categories whose names don't come from OBJ_NAME(objects[type])
13.    */
14.   #define PN_BARE_HANDED			(-1)	/* includes martial arts */
15.   #define PN_TWO_WEAPONS			(-2)
16.   #define PN_RIDING			(-3)
17.   #define PN_POLEARMS			(-4)
18.   #define PN_SABER			(-5)
19.   #define PN_HAMMER			(-6)
20.   #define PN_WHIP				(-7)
21.   #define PN_ATTACK_SPELL			(-8)
22.   #define PN_HEALING_SPELL		(-9)
23.   #define PN_DIVINATION_SPELL		(-10)
24.   #define PN_ENCHANTMENT_SPELL		(-11)
25.   #define PN_CLERIC_SPELL			(-12)
26.   #define PN_ESCAPE_SPELL			(-13)
27.   #define PN_MATTER_SPELL			(-14)
28.   
29.   #ifndef OVLB
30.   
31.   STATIC_DCL NEARDATA const short skill_names_indices[];
32.   STATIC_DCL NEARDATA const char *odd_skill_names[];
33.   STATIC_DCL NEARDATA const char *barehands_or_martial[];
34.   
35.   #else	/* OVLB */
36.   
37.   STATIC_VAR NEARDATA const short skill_names_indices[P_NUM_SKILLS] = {
38.   	0,                DAGGER,         KNIFE,        AXE,
39.   	PICK_AXE,         SHORT_SWORD,    BROADSWORD,   LONG_SWORD,
40.   	TWO_HANDED_SWORD, SCIMITAR,       PN_SABER,     CLUB,
41.   	MACE,             MORNING_STAR,   FLAIL,
42.   	PN_HAMMER,        QUARTERSTAFF,   PN_POLEARMS,  SPEAR,
43.   	JAVELIN,          TRIDENT,        LANCE,        BOW,
44.   	SLING,            CROSSBOW,       DART,
45.   	SHURIKEN,         BOOMERANG,      PN_WHIP,      UNICORN_HORN,
46.   	PN_ATTACK_SPELL,     PN_HEALING_SPELL,
47.   	PN_DIVINATION_SPELL, PN_ENCHANTMENT_SPELL,
48.   	PN_CLERIC_SPELL,     PN_ESCAPE_SPELL,
49.   	PN_MATTER_SPELL,
50.   	PN_BARE_HANDED,   PN_TWO_WEAPONS,
51.   #ifdef STEED
52.   	PN_RIDING
53.   #endif
54.   };
55.   
56.   /* note: entry [0] isn't used */
57.   STATIC_VAR NEARDATA const char *odd_skill_names[] = {
58.       "no skill",
59.       "bare hands",		/* use barehands_or_martial[] instead */
60.       "two weapon combat",
61.       "riding",
62.       "polearms",
63.       "saber",
64.       "hammer",
65.       "whip",
66.       "attack spells",
67.       "healing spells",
68.       "divination spells",
69.       "enchantment spells",
70.       "clerical spells",
71.       "escape spells",
72.       "matter spells",
73.   };
74.   /* indexed vis `is_martial() */
75.   STATIC_VAR NEARDATA const char *barehands_or_martial[] = {
76.       "bare handed combat", "martial arts"
77.   };
78.   
79.   STATIC_OVL
80.   void give_may_advance_msg(skill)
81.   int skill;
82.   {
83.   	You("feel more confident in your %sskills.",
84.   		skill == P_NONE ?
85.   			"" :
86.   		skill <= P_LAST_WEAPON ?
87.   			"weapon " :
88.   		skill <= P_LAST_SPELL ?
89.   			"spell casting " :
90.   		"fighting ");
91.   }
92.   
93.   #endif	/* OVLB */
94.   
95.   STATIC_DCL boolean FDECL(can_advance, (int, BOOLEAN_P));
96.   STATIC_DCL int FDECL(slots_required, (int));
97.   
98.   #ifdef OVL1
99.   
100.  STATIC_DCL char *FDECL(skill_level_name, (int,char *));
101.  STATIC_DCL void FDECL(skill_advance, (int));
102.  
103.  #endif	/* OVL1 */
104.  
105.  #define P_NAME(type) ((skill_names_indices[type] > 0) ? \
106.  		      OBJ_NAME(objects[skill_names_indices[type]]) : \
107.  		      (type == P_BARE_HANDED_COMBAT) ? \
108.  			barehands_or_martial[martial_bonus()] : \
109.  			odd_skill_names[-skill_names_indices[type]])
110.  
111.  #ifdef OVLB
112.  static NEARDATA const char kebabable[] = {
113.  	S_XORN, S_DRAGON, S_JABBERWOCK, S_NAGA, S_GIANT, '\0'
114.  };
115.  
116.  /*
117.   *	hitval returns an integer representing the "to hit" bonuses
118.   *	of "otmp" against the monster.
119.   */
120.  int
121.  hitval(otmp, mon)
122.  struct obj *otmp;
123.  struct monst *mon;
124.  {
125.  	int	tmp = 0;
126.  	struct permonst *ptr = mon->data;
127.  	boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
128.  
129.  	if (Is_weapon)
130.  		tmp += otmp->spe;
131.  
132.  /*	Put weapon specific "to hit" bonuses in below:		*/
133.  	tmp += objects[otmp->otyp].oc_hitbon;
134.  
135.  /*	Put weapon vs. monster type "to hit" bonuses in below:	*/
136.  
137.  	/* Blessed weapons used against undead or demons */
138.  	if (Is_weapon && otmp->blessed &&
139.  	   (is_demon(ptr) || is_undead(ptr))) tmp += 2;
140.  
141.  	if (is_spear(otmp) &&
142.  	   index(kebabable, ptr->mlet)) tmp += 2;
143.    
144.  	/* trident is highly effective against swimmers */
145.  	if (otmp->otyp == TRIDENT && is_swimmer(ptr)) {
146.  	   if (is_pool(mon->mx, mon->my)) tmp += 4;
147.  	   else if (ptr->mlet == S_EEL || ptr->mlet == S_SNAKE) tmp += 2;
148.  	}
149.  
150.  	/* Picks used against xorns and earth elementals */
151.  	if (is_pick(otmp) &&
152.  	   (passes_walls(ptr) && thick_skinned(ptr))) tmp += 2;
153.  
154.  #ifdef INVISIBLE_OBJECTS
155.  	/* Invisible weapons against monsters who can't see invisible */
156.  	if (otmp->oinvis && !perceives(ptr)) tmp += 3;
157.  #endif
158.  
159.  	/* Check specially named weapon "to hit" bonuses */
160.  	if (otmp->oartifact) tmp += spec_abon(otmp, mon);
161.  
162.  	return tmp;
163.  }
164.  
165.  /* Historical note: The original versions of Hack used a range of damage
166.   * which was similar to, but not identical to the damage used in Advanced
167.   * Dungeons and Dragons.  I figured that since it was so close, I may as well
168.   * make it exactly the same as AD&D, adding some more weapons in the process.
169.   * This has the advantage that it is at least possible that the player would
170.   * already know the damage of at least some of the weapons.  This was circa
171.   * 1987 and I used the table from Unearthed Arcana until I got tired of typing
172.   * them in (leading to something of an imbalance towards weapons early in
173.   * alphabetical order).  The data structure still doesn't include fields that
174.   * fully allow the appropriate damage to be described (there's no way to say
175.   * 3d6 or 1d6+1) so we add on the extra damage in dmgval() if the weapon
176.   * doesn't do an exact die of damage.
177.   *
178.   * Of course new weapons were added later in the development of Nethack.  No
179.   * AD&D consistency was kept, but most of these don't exist in AD&D anyway.
180.   *
181.   * Second edition AD&D came out a few years later; luckily it used the same
182.   * table.  As of this writing (1999), third edition is in progress but not
183.   * released.  Let's see if the weapon table stays the same.  --KAA
184.   */
185.  
186.  /*
187.   *	dmgval returns an integer representing the damage bonuses
188.   *	of "otmp" against the monster.
189.   */
190.  int
191.  dmgval(otmp, mon)
192.  struct obj *otmp;
193.  struct monst *mon;
194.  {
195.  	int tmp = 0, otyp = otmp->otyp;
196.  	struct permonst *ptr = mon->data;
197.  	boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
198.  
199.  	if (otyp == CREAM_PIE) return 0;
200.  
201.  	if (bigmonst(ptr)) {
202.  	    if (objects[otyp].oc_wldam)
203.  		tmp = rnd(objects[otyp].oc_wldam);
204.  	    switch (otyp) {
205.  		case IRON_CHAIN:
206.  		case CROSSBOW_BOLT:
207.  		case MORNING_STAR:
208.  		case PARTISAN:
209.  		case RUNESWORD:
210.  		case ELVEN_BROADSWORD:
211.  		case BROADSWORD:	tmp++; break;
212.  
213.  		case FLAIL:
214.  		case RANSEUR:
215.  		case VOULGE:		tmp += rnd(4); break;
216.  
217.  		case ACID_VENOM:
218.  		case HALBERD:
219.  		case SPETUM:		tmp += rnd(6); break;
220.  
221.  		case BATTLE_AXE:
222.  		case BARDICHE:
223.  		case TRIDENT:		tmp += d(2,4); break;
224.  
225.  		case TSURUGI:
226.  		case DWARVISH_MATTOCK:
227.  		case TWO_HANDED_SWORD:	tmp += d(2,6); break;
228.  	    }
229.  	} else {
230.  	    if (objects[otyp].oc_wsdam)
231.  		tmp = rnd(objects[otyp].oc_wsdam);
232.  	    switch (otyp) {
233.  		case IRON_CHAIN:
234.  		case CROSSBOW_BOLT:
235.  		case MACE:
236.  		case WAR_HAMMER:
237.  		case FLAIL:
238.  		case SPETUM:
239.  		case TRIDENT:		tmp++; break;
240.  
241.  		case BATTLE_AXE:
242.  		case BARDICHE:
243.  		case BILL_GUISARME:
244.  		case GUISARME:
245.  		case LUCERN_HAMMER:
246.  		case MORNING_STAR:
247.  		case RANSEUR:
248.  		case BROADSWORD:
249.  		case ELVEN_BROADSWORD:
250.  		case RUNESWORD:
251.  		case VOULGE:		tmp += rnd(4); break;
252.  
253.  		case ACID_VENOM:	tmp += rnd(6); break;
254.  	    }
255.  	}
256.  	if (Is_weapon) {
257.  		tmp += otmp->spe;
258.  		/* negative enchantment mustn't produce negative damage */
259.  		if (tmp < 0) tmp = 0;
260.  	}
261.  
262.  	if (objects[otyp].oc_material <= LEATHER && thick_skinned(ptr))
263.  		/* thick skinned/scaled creatures don't feel it */
264.  		tmp = 0;
265.  	if (ptr == &mons[PM_SHADE] && objects[otyp].oc_material != SILVER)
266.  		tmp = 0;
267.  
268.  	/* "very heavy iron ball"; weight increase is in increments of 160 */
269.  	if (otyp == HEAVY_IRON_BALL && tmp > 0) {
270.  	    int wt = (int)objects[HEAVY_IRON_BALL].oc_weight;
271.  
272.  	    if ((int)otmp->owt > wt) {
273.  		wt = ((int)otmp->owt - wt) / 160;
274.  		tmp += rnd(4 * wt);
275.  		if (tmp > 25) tmp = 25;	/* objects[].oc_wldam */
276.  	    }
277.  	}
278.  
279.  /*	Put weapon vs. monster type damage bonuses in below:	*/
280.  	if (Is_weapon || otmp->oclass == GEM_CLASS ||
281.  		otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) {
282.  	    int bonus = 0;
283.  
284.  #ifdef STEED
285.  		/* KMH -- Lances are especially made for riding */
286.  		if (otmp == uwep && u.usteed &&
287.  				objects[otmp->otyp].oc_skill == P_LANCE)
288.  			bonus += d(2,10);
289.  #endif
290.  
291.  	    if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
292.  		bonus += rnd(4);
293.  	    if (is_axe(otmp) && is_wooden(ptr))
294.  		bonus += rnd(4);
295.  	    if (objects[otyp].oc_material == SILVER && hates_silver(ptr))
296.  		bonus += rnd(20);
297.  
298.  	    /* if the weapon is going to get a double damage bonus, adjust
299.  	       this bonus so that effectively it's added after the doubling */
300.  	    if (bonus > 1 && otmp->oartifact && spec_dbon(otmp, mon, 25) >= 25)
301.  		bonus = (bonus + 1) / 2;
302.  
303.  	    tmp += bonus;
304.  	}
305.  
306.  	if (tmp > 0) {
307.  		/* It's debateable whether a rusted blunt instrument
308.  		   should do less damage than a pristine one, since
309.  		   it will hit with essentially the same impact, but
310.  		   there ought to some penalty for using damaged gear
311.  		   so always subtract erosion even for blunt weapons. */
312.  		tmp -= greatest_erosion(otmp);
313.  		if (tmp < 1) tmp = 1;
314.  	}
315.  
316.  	return(tmp);
317.  }
318.  
319.  #endif /* OVLB */
320.  #ifdef OVL0
321.  
322.  STATIC_DCL struct obj *FDECL(oselect, (struct monst *,int));
323.  #define Oselect(x)	if ((otmp = oselect(mtmp, x)) != 0) return(otmp);
324.  
325.  STATIC_OVL struct obj *
326.  oselect(mtmp, x)
327.  struct monst *mtmp;
328.  int x;
329.  {
330.  	struct obj *otmp;
331.  
332.  	for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
333.  	    if (otmp->otyp == x &&
334.  		    /* never select non-cockatrice corpses */
335.  		    !((x == CORPSE || x == EGG) &&
336.  			!touch_petrifies(&mons[otmp->corpsenm])) &&
337.  		    (!otmp->oartifact || touch_artifact(otmp,mtmp)))
338.  		return otmp;
339.  	}
340.  	return (struct obj *)0;
341.  }
342.  
343.  static NEARDATA const int rwep[] =
344.  {	DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
345.  	  SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
346.  	  CROSSBOW_BOLT, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, FLINT,
347.  	  ROCK, LOADSTONE, LUCKSTONE, DART, /* BOOMERANG, */ CREAM_PIE
348.  	  /* note: CREAM_PIE should NOT be #ifdef KOPS */
349.  };
350.  
351.  static NEARDATA const int pwep[] =
352.  {	HALBERD, PARTISAN, LANCE, FAUCHARD, BILL_GUISARME, BEC_DE_CORBIN,
353.  	GUISARME, RANSEUR, SPETUM, VOULGE, BARDICHE, GLAIVE
354.  };
355.  
356.  static struct obj *propellor;
357.  
358.  struct obj *
359.  select_rwep(mtmp)	/* select a ranged weapon for the monster */
360.  register struct monst *mtmp;
361.  {
362.  	register struct obj *otmp;
363.  	int i;
364.  
365.  #ifdef KOPS
366.  	char mlet = mtmp->data->mlet;
367.  #endif
368.  
369.  	propellor = &zeroobj;
370.  	Oselect(EGG); /* cockatrice egg */
371.  #ifdef KOPS
372.  	if(mlet == S_KOP)	/* pies are first choice for Kops */
373.  	    Oselect(CREAM_PIE);
374.  #endif
375.  	if(throws_rocks(mtmp->data))	/* ...boulders for giants */
376.  	    Oselect(BOULDER);
377.  
378.  	/* Select polearms first; they do more damage and aren't expendable */
379.  	for (i = 0; i < SIZE(pwep); i++) {
380.  		/* Only strong monsters can wield big (esp. long) weapons.
381.  		 * Big weapon is basically the same as bimanual.
382.  		 * All monsters can wield the remaining weapons.
383.  		 */
384.  		if (((strongmonst(mtmp->data) && (mtmp->misc_worn_check & W_ARMS) == 0)
385.  			|| !objects[pwep[i]].oc_bimanual) &&
386.  		    (objects[pwep[i]].oc_material != SILVER
387.  			|| !hates_silver(mtmp->data)))
388.  			Oselect(pwep[i]);
389.  	}
390.  
391.  	/*
392.  	 * other than these two specific cases, always select the
393.  	 * most potent ranged weapon to hand.
394.  	 */
395.  	for (i = 0; i < SIZE(rwep); i++) {
396.  	    int prop;
397.  
398.  	    /* shooting gems from slings; this goes just before the darts */
399.  	    /* (shooting rocks is already handled via the rwep[] ordering) */
400.  	    if (rwep[i] == DART && !likes_gems(mtmp->data) &&
401.  		    m_carrying(mtmp, SLING)) {		/* propellor */
402.  		for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
403.  		    if (otmp->oclass == GEM_CLASS &&
404.  			    (otmp->otyp != LOADSTONE || !otmp->cursed)) {
405.  			propellor = m_carrying(mtmp, SLING);
406.  			return otmp;
407.  		    }
408.  	    }
409.  
410.  		/* KMH -- This belongs here so darts will work */
411.  	    propellor = &zeroobj;
412.  
413.  	    prop = (objects[rwep[i]]).oc_skill;
414.  	    if (prop > 0) {
415.  		switch (prop) {
416.  		case P_BOW:
417.  		  propellor = (oselect(mtmp, YUMI));
418.  		  if (!propellor) propellor = (oselect(mtmp, ELVEN_BOW));
419.  		  if (!propellor) propellor = (oselect(mtmp, BOW));
420.  		  if (!propellor) propellor = (oselect(mtmp, ORCISH_BOW));
421.  		  break;
422.  		case P_SLING:
423.  		  propellor = (oselect(mtmp, SLING));
424.  		  break;
425.  		case P_CROSSBOW:
426.  		  propellor = (oselect(mtmp, CROSSBOW));
427.  		}
428.  		if ((otmp = MON_WEP(mtmp)) && otmp->cursed && otmp != propellor
429.  				&& mtmp->weapon_check == NO_WEAPON_WANTED)
430.  			propellor = 0;
431.  	    }
432.  	    /* propellor = obj, propellor to use
433.  	     * propellor = &zeroobj, doesn't need a propellor
434.  	     * propellor = 0, needed one and didn't have one
435.  	     */
436.  	    if (propellor != 0) {
437.  		/* Note: cannot use m_carrying for loadstones, since it will
438.  		 * always select the first object of a type, and maybe the
439.  		 * monster is carrying two but only the first is unthrowable.
440.  		 */
441.  		if (rwep[i] != LOADSTONE) {
442.  			/* Don't throw a cursed weapon-in-hand or an artifact */
443.  			if ((otmp = oselect(mtmp, rwep[i])) && !otmp->oartifact
444.  			    && (!otmp->cursed || otmp != MON_WEP(mtmp)))
445.  				return(otmp);
446.  		} else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
447.  		    if (otmp->otyp == LOADSTONE && !otmp->cursed)
448.  			return otmp;
449.  		}
450.  	    }
451.  	  }
452.  
453.  	/* failure */
454.  	return (struct obj *)0;
455.  }
456.  
457.  /* Weapons in order of preference */
458.  static NEARDATA short hwep[] = {
459.  	  CORPSE,  /* cockatrice corpse */
460.  	  TSURUGI, RUNESWORD, DWARVISH_MATTOCK, TWO_HANDED_SWORD, BATTLE_AXE,
461.  	  KATANA, UNICORN_HORN, CRYSKNIFE, TRIDENT, LONG_SWORD,
462.  	  ELVEN_BROADSWORD, BROADSWORD, LUCERN_HAMMER, SCIMITAR, SILVER_SABER,
463.  	  MORNING_STAR, ELVEN_SHORT_SWORD, DWARVISH_SHORT_SWORD, SHORT_SWORD,
464.  	  ORCISH_SHORT_SWORD, MACE, AXE, DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR,
465.  	  ORCISH_SPEAR, FLAIL, BULLWHIP, QUARTERSTAFF, JAVELIN, AKLYS, CLUB,
466.  	  PICK_AXE,
467.  #ifdef KOPS
468.  	  RUBBER_HOSE,
469.  #endif /* KOPS */
470.  	  WAR_HAMMER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, ATHAME, SCALPEL,
471.  	  KNIFE, WORM_TOOTH
472.  	};
473.  
474.  struct obj *
475.  select_hwep(mtmp)	/* select a hand to hand weapon for the monster */
476.  register struct monst *mtmp;
477.  {
478.  	register struct obj *otmp;
479.  	register int i;
480.  	boolean strong = strongmonst(mtmp->data);
481.  	boolean wearing_shield = (mtmp->misc_worn_check & W_ARMS) != 0;
482.  
483.  	/* prefer artifacts to everything else */
484.  	for(otmp=mtmp->minvent; otmp; otmp = otmp->nobj) {
485.  		if (otmp->oclass == WEAPON_CLASS
486.  			&& otmp->oartifact && touch_artifact(otmp,mtmp)
487.  			&& ((strong && !wearing_shield)
488.  			    || !objects[otmp->otyp].oc_bimanual))
489.  		    return otmp;
490.  	}
491.  
492.  	if(is_giant(mtmp->data))	/* giants just love to use clubs */
493.  	    Oselect(CLUB);
494.  
495.  	/* only strong monsters can wield big (esp. long) weapons */
496.  	/* big weapon is basically the same as bimanual */
497.  	/* all monsters can wield the remaining weapons */
498.  	for (i = 0; i < SIZE(hwep); i++)
499.  	    if (((strong && !wearing_shield)
500.  			|| !objects[hwep[i]].oc_bimanual) &&
501.  		    (objects[hwep[i]].oc_material != SILVER
502.  			|| !hates_silver(mtmp->data)))
503.  		Oselect(hwep[i]);
504.  
505.  	/* failure */
506.  	return (struct obj *)0;
507.  }
508.  
509.  /* Called after polymorphing a monster, robbing it, etc....  Monsters
510.   * otherwise never unwield stuff on their own.  Shouldn't print messages.
511.   */
512.  void
513.  possibly_unwield(mon)
514.  register struct monst *mon;
515.  {
516.  	register struct obj *obj;
517.  	struct obj *mw_tmp;
518.  
519.  	if (!(mw_tmp = MON_WEP(mon)))
520.  		return;
521.  	for(obj=mon->minvent; obj; obj=obj->nobj)
522.  		if (obj == mw_tmp) break;
523.  	if (!obj) { /* The weapon was stolen or destroyed */
524.  		MON_NOWEP(mon);
525.  		mon->weapon_check = NEED_WEAPON;
526.  		return;
527.  	}
528.  	if (!attacktype(mon->data, AT_WEAP)) {
529.  		mw_tmp->owornmask &= ~W_WEP;
530.  		MON_NOWEP(mon);
531.  		mon->weapon_check = NO_WEAPON_WANTED;
532.  		obj_extract_self(obj);
533.  		/* flooreffects unnecessary, can't wield boulders */
534.  		place_object(obj, mon->mx, mon->my);
535.  		stackobj(obj);
536.  		if (cansee(mon->mx, mon->my)) {
537.  			pline("%s drops %s.", Monnam(mon),
538.  				distant_name(obj, doname));
539.  			newsym(mon->mx, mon->my);
540.  		}
541.  		return;
542.  	}
543.  	/* The remaining case where there is a change is where a monster
544.  	 * is polymorphed into a stronger/weaker monster with a different
545.  	 * choice of weapons.  This has no parallel for players.  It can
546.  	 * be handled by waiting until mon_wield_item is actually called.
547.  	 * Though the monster still wields the wrong weapon until then,
548.  	 * this is OK since the player can't see it.
549.  	 * Note that if there is no change, setting the check to NEED_WEAPON
550.  	 * is harmless.
551.  	 * Possible problem: big monster with big cursed weapon gets
552.  	 * polymorphed into little monster.  But it's not quite clear how to
553.  	 * handle this anyway....
554.  	 */
555.  	mon->weapon_check = NEED_WEAPON;
556.  }
557.  
558.  /* Let a monster try to wield a weapon, based on mon->weapon_check.
559.   * Returns 1 if the monster took time to do it, 0 if it did not.
560.   */
561.  int
562.  mon_wield_item(mon)
563.  register struct monst *mon;
564.  {
565.  	struct obj *obj;
566.  
567.  	/* This case actually should never happen */
568.  	if (mon->weapon_check == NO_WEAPON_WANTED) return 0;
569.  
570.  	switch(mon->weapon_check) {
571.  		case NEED_HTH_WEAPON:
572.  			obj = select_hwep(mon);
573.  			break;
574.  		case NEED_RANGED_WEAPON:
575.  			(void)select_rwep(mon);
576.  			obj = propellor;
577.  			break;
578.  		case NEED_PICK_AXE:
579.  			obj = m_carrying(mon, PICK_AXE);
580.  			/* KMH -- allow other picks */
581.  			if (!obj) obj = m_carrying(mon, DWARVISH_MATTOCK);
582.  			break;
583.  		default: impossible("weapon_check %d for %s?",
584.  				mon->weapon_check, mon_nam(mon));
585.  			return 0;
586.  	}
587.  	if (obj && obj != &zeroobj) {
588.  		struct obj *mw_tmp = MON_WEP(mon);
589.  		if (mw_tmp && mw_tmp->otyp == obj->otyp) {
590.  		/* already wielding it */
591.  			mon->weapon_check = NEED_WEAPON;
592.  			return 0;
593.  		}
594.  		/* Actually, this isn't necessary--as soon as the monster
595.  		 * wields the weapon, the weapon welds itself, so the monster
596.  		 * can know it's cursed and needn't even bother trying.
597.  		 * Still....
598.  		 */
599.  		if (mw_tmp && mw_tmp->cursed && mw_tmp->otyp != CORPSE) {
600.  		    if (canseemon(mon)) {
601.  			char welded_buf[BUFSZ];
602.  			const char *mon_hand = mbodypart(mon, HAND);
603.  
604.  			if (bimanual(mw_tmp)) mon_hand = makeplural(mon_hand);
605.  			Sprintf(welded_buf, "%s welded to %s %s",
606.  				(mw_tmp->quan == 1L) ? "is" : "are",
607.  				his[pronoun_gender(mon)], mon_hand);
608.  
609.  			if (obj->otyp == PICK_AXE) {
610.  			    pline("Since %s weapon%s %s,",
611.  				  s_suffix(mon_nam(mon)),
612.  				  plur(mw_tmp->quan), welded_buf);
613.  			    pline("%s cannot wield that %s.",
614.  				mon_nam(mon), xname(obj));
615.  			} else {
616.  			    pline("%s tries to wield %s.", Monnam(mon),
617.  				doname(obj));
618.  			    pline("%s %s %s!",
619.  				  s_suffix(Monnam(mon)),
620.  				  xname(mw_tmp), welded_buf);
621.  			}
622.  			mw_tmp->bknown = 1;
623.  		    }
624.  		    mon->weapon_check = NO_WEAPON_WANTED;
625.  		    return 1;
626.  		}
627.  		mon->mw = obj;		/* wield obj */
628.  		if (mw_tmp) mw_tmp->owornmask &= ~W_WEP;
629.  		mon->weapon_check = NEED_WEAPON;
630.  		if (canseemon(mon)) {
631.  			pline("%s wields %s!", Monnam(mon), doname(obj));
632.  			if (obj->cursed && obj->otyp != CORPSE) {
633.  				pline("%s %s to %s hand!",
634.  					The(xname(obj)),
635.  					(obj->quan == 1L) ? "welds itself"
636.  					    : "weld themselves",
637.  					s_suffix(mon_nam(mon)));
638.  				obj->bknown = 1;
639.  			}
640.  		}
641.  		obj->owornmask = W_WEP;
642.  		return 1;
643.  	}
644.  	mon->weapon_check = NEED_WEAPON;
645.  	return 0;
646.  }
647.  
648.  int
649.  abon()		/* attack bonus for strength & dexterity */
650.  {
651.  	int sbon;
652.  	int str = ACURR(A_STR), dex = ACURR(A_DEX);
653.  
654.  	if (Upolyd) return(adj_lev(&mons[u.umonnum]) - 3);
655.  	if (str < 6) sbon = -2;
656.  	else if (str < 8) sbon = -1;
657.  	else if (str < 17) sbon = 0;
658.  	else if (str <= STR18(50)) sbon = 1;	/* up to 18/50 */
659.  	else if (str < STR18(100)) sbon = 2;
660.  	else sbon = 3;
661.  
662.  /* Game tuning kludge: make it a bit easier for a low level character to hit */
663.  	sbon += (u.ulevel < 3) ? 1 : 0;
664.  
665.  	if (dex < 4) return(sbon-3);
666.  	else if (dex < 6) return(sbon-2);
667.  	else if (dex < 8) return(sbon-1);
668.  	else if (dex < 14) return(sbon);
669.  	else return(sbon + dex-14);
670.  }
671.  
672.  #endif /* OVL0 */
673.  #ifdef OVL1
674.  
675.  int
676.  dbon()		/* damage bonus for strength */
677.  {
678.  	int str = ACURR(A_STR);
679.  
680.  	if (Upolyd) return(0);
681.  
682.  	if (str < 6) return(-1);
683.  	else if (str < 16) return(0);
684.  	else if (str < 18) return(1);
685.  	else if (str == 18) return(2);		/* up to 18 */
686.  	else if (str <= STR18(75)) return(3);		/* up to 18/75 */
687.  	else if (str <= STR18(90)) return(4);		/* up to 18/90 */
688.  	else if (str < STR18(100)) return(5);		/* up to 18/99 */
689.  	else return(6);
690.  }
691.  
692.  
693.  /* copy the skill level name into the given buffer */
694.  STATIC_OVL char *
695.  skill_level_name(skill, buf)
696.  int skill;
697.  char *buf;
698.  {
699.      const char *ptr;
700.  
701.      switch (P_SKILL(skill)) {
702.  	case P_UNSKILLED:    ptr = "Unskilled"; break;
703.  	case P_BASIC:	     ptr = "Basic";     break;
704.  	case P_SKILLED:	     ptr = "Skilled";   break;
705.  	case P_EXPERT:	     ptr = "Expert";    break;
706.  	/* these are for unarmed combat/martial arts only */
707.  	case P_MASTER:	     ptr = "Master";    break;
708.  	case P_GRAND_MASTER: ptr = "Grand Master"; break;
709.  	default:	     ptr = "Unknown";	break;
710.      }
711.      Strcpy(buf, ptr);
712.      return buf;
713.  }
714.  
715.  /* return the # of slots required to advance the skill */
716.  STATIC_OVL int
717.  slots_required(skill)
718.  int skill;
719.  {
720.      int tmp = P_SKILL(skill);
721.  
722.      /* The more difficult the training, the more slots it takes.
723.       *	unskilled -> basic	1
724.       *	basic -> skilled	2
725.       *	skilled -> expert	3
726.       */
727.      if (skill <= P_LAST_WEAPON || skill == P_TWO_WEAPON_COMBAT)
728.  	return tmp;
729.  
730.      /* Fewer slots used up for unarmed or martial.
731.       *	unskilled -> basic	1
732.       *	basic -> skilled	1
733.       *	skilled -> expert	2
734.       *	expert -> master	2
735.       *	master -> grand master	3
736.       */
737.      return (tmp + 1) / 2;
738.  }
739.  
740.  /* return true if this skill can be advanced */
741.  STATIC_OVL boolean
742.  can_advance(skill, speedy)
743.  int skill;
744.  boolean speedy;
745.  {
746.      return !P_RESTRICTED(skill)
747.  	    && P_SKILL(skill) < P_MAX_SKILL(skill) && (
748.  #ifdef WIZARD
749.  	    (wizard && speedy) ||
750.  #endif
751.  	    (P_ADVANCE(skill) >=
752.  		(unsigned) practice_needed_to_advance(P_SKILL(skill))
753.  	    && u.skills_advanced < P_SKILL_LIMIT
754.  	    && u.weapon_slots >= slots_required(skill)));
755.  }
756.  
757.  STATIC_OVL void
758.  skill_advance(skill)
759.  int skill;
760.  {
761.      u.weapon_slots -= slots_required(skill);
762.      P_SKILL(skill)++;
763.      u.skill_record[u.skills_advanced++] = skill;
764.      /* subtly change the adavnce message to indicate no more advancement */
765.      You("are now %s skilled in %s.",
766.      	P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more",
767.      	P_NAME(skill));
768.  }
769.  
770.  static struct skill_range {
771.  	short first, last;
772.  	const char *name;
773.  } skill_ranges[] = {
774.      { P_FIRST_H_TO_H, P_LAST_H_TO_H, "Fighting Skills" },
775.      { P_FIRST_WEAPON, P_LAST_WEAPON, "Weapon Skills" },
776.      { P_FIRST_SPELL,  P_LAST_SPELL,  "Spellcasting Skills" },
777.  };
778.  
779.  /*
780.   * The `#enhance' extended command.  What we _really_ would like is
781.   * to keep being able to pick things to advance until we couldn't any
782.   * more.  This is currently not possible -- the menu code has no way
783.   * to call us back for instant action.  Even if it did, we would also need
784.   * to be able to update the menu since selecting one item could make
785.   * others unselectable.
786.   */
787.  int
788.  enhance_weapon_skill()
789.  {
790.      int pass, i, n, len, longest, to_advance;
791.      char buf[BUFSZ], buf2[BUFSZ];
792.      menu_item *selected;
793.      anything any;
794.      winid win;
795.      boolean speedy = FALSE;
796.  
797.  
798.  #ifdef WIZARD
799.  	if (wizard && yn("Advance skills without practice?") == 'y')
800.  	    speedy = TRUE;
801.  #endif
802.  
803.  	do {
804.  	    /* find longest available skill name, count those that can advance */
805.  	    for (longest = 0, to_advance = 0, i = 0; i < P_NUM_SKILLS; i++) {
806.  		if (!P_RESTRICTED(i) && (len = strlen(P_NAME(i))) > longest)
807.  		    longest = len;
808.  		if (can_advance(i, speedy)) to_advance++;
809.  	    }
810.  
811.  	    win = create_nhwindow(NHW_MENU);
812.  	    start_menu(win);
813.  
814.  	    /* List the skills, making ones that could be advanced
815.  	       selectable.  List the miscellaneous skills first.
816.  	       Possible future enhancement:  list spell skills before
817.  	       weapon skills for spellcaster roles. */
818.  	  for (pass = 0; pass < SIZE(skill_ranges); pass++)
819.  	    for (i = skill_ranges[pass].first;
820.  		 i <= skill_ranges[pass].last; i++) {
821.  		/* Print headings for skill types */
822.  		any.a_void = 0;
823.  		if (i == skill_ranges[pass].first)
824.  		    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD,
825.  			     skill_ranges[pass].name, MENU_UNSELECTED);
826.  
827.  		if (P_RESTRICTED(i)) continue;
828.  		/*
829.  		 * Sigh, this assumes a monospaced font.
830.  		 * The 12 is the longest skill level name.
831.  		 * The "    " is room for a selection letter and dash, "a - ".
832.  		 */
833.  #ifdef WIZARD
834.  		if (wizard)
835.  		    Sprintf(buf2, " %s%-*s %-12s %4d(%4d)",
836.  			    to_advance == 0 || can_advance(i, speedy) ? "" : "    " ,
837.  			    longest, P_NAME(i),
838.  			    skill_level_name(i, buf),
839.  			    P_ADVANCE(i), practice_needed_to_advance(P_SKILL(i)));
840.  		else
841.  #endif
842.  		    Sprintf(buf2, " %s %-*s [%s]",
843.  			    to_advance == 0 || can_advance(i, speedy) ? "" : "    ",
844.  			    longest, P_NAME(i),
845.  			    skill_level_name(i, buf));
846.  
847.  		any.a_int = can_advance(i, speedy) ? i+1 : 0;
848.  		add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf2, MENU_UNSELECTED);
849.  	    }
850.  
851.  	    Strcpy(buf, to_advance ? "Pick a skill to advance:" : "Current skills:");
852.  #ifdef WIZARD
853.  	    if (wizard && !speedy) Sprintf(eos(buf), "  (%d slot%s available)",
854.  				u.weapon_slots, plur(u.weapon_slots));
855.  #endif
856.  	    end_menu(win, buf);
857.  	    n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
858.  	    destroy_nhwindow(win);
859.  	    if (n > 0) {
860.  		n = selected[0].item.a_int - 1;	/* get item selected */
861.  		free((genericptr_t)selected);
862.  		skill_advance(n);
863.  		/* check for more skills able to advance, if so then .. */
864.  		for (n = i = 0; i < P_NUM_SKILLS; i++) {
865.  		    if (can_advance(i, speedy)) {
866.  			if (!speedy) You_feel("you could be more dangerous!");
867.  			n++;
868.  			break;
869.  		    }
870.  		}
871.  	    }
872.  	} while (speedy && n > 0);
873.  	return 0;
874.  }
875.  
876.  /*
877.   * Change from restricted to unrestricted, allowing P_BASIC as max.  This
878.   * function may be called with with P_NONE.  Used in pray.c.
879.   */
880.  void
881.  unrestrict_weapon_skill(skill)
882.  int skill;
883.  {
884.      if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
885.  	P_SKILL(skill) = P_UNSKILLED;
886.  	P_MAX_SKILL(skill) = P_BASIC;
887.  	P_ADVANCE(skill) = 0;
888.      }
889.  }
890.  
891.  #endif /* OVL1 */
892.  #ifdef OVLB
893.  
894.  void
895.  use_skill(skill,degree)
896.  int skill;
897.  int degree;
898.  {
899.      boolean advance_before;
900.  
901.      if (skill != P_NONE && !P_RESTRICTED(skill)) {
902.  	advance_before = can_advance(skill, FALSE);
903.  	P_ADVANCE(skill)+=degree;
904.  	if (!advance_before && can_advance(skill, FALSE))
905.  	    give_may_advance_msg(skill);
906.      }
907.  }
908.  
909.  void
910.  add_weapon_skill(n)
911.  int n;	/* number of slots to gain; normally one */
912.  {
913.      int i, before, after;
914.  
915.      for (i = 0, before = 0; i < P_NUM_SKILLS; i++)
916.  	if (can_advance(i, FALSE)) before++;
917.      u.weapon_slots += n;
918.      for (i = 0, after = 0; i < P_NUM_SKILLS; i++)
919.  	if (can_advance(i, FALSE)) after++;
920.      if (before < after)
921.  	give_may_advance_msg(P_NONE);
922.  }
923.  
924.  void
925.  lose_weapon_skill(n)
926.  int n;	/* number of slots to lose; normally one */
927.  {
928.      int skill;
929.  
930.      while (--n >= 0) {
931.  	/* deduct first from unused slots, then from last placed slot, if any */
932.  	if (u.weapon_slots) {
933.  	    u.weapon_slots--;
934.  	} else if (u.skills_advanced) {
935.  	    skill = u.skill_record[--u.skills_advanced];
936.  	    if (P_SKILL(skill) <= P_UNSKILLED)
937.  		panic("lose_weapon_skill (%d)", skill);
938.  	    P_SKILL(skill)--;	/* drop skill one level */
939.  	    /* Lost skill might have taken more than one slot; refund rest. */
940.  	    u.weapon_slots = slots_required(skill) - 1;
941.  	    /* It might now be possible to advance some other pending
942.  	       skill by using the refunded slots, but giving a message
943.  	       to that affect would seem pretty confusing.... */
944.  	}
945.      }
946.  }
947.  
948.  int
949.  weapon_type(obj)
950.  struct obj *obj;
951.  {
952.  	/* KMH -- now uses the object table */
953.      int type;
954.  
955.  
956.  	if (!obj)
957.  		/* Not using a weapon */
958.  		return (P_BARE_HANDED_COMBAT);
959.  	if (u.twoweap)
960.  		return (P_TWO_WEAPON_COMBAT);
961.  	if (obj->oclass != WEAPON_CLASS && obj->oclass != TOOL_CLASS &&
962.  	    obj->oclass != GEM_CLASS)
963.  		/* Not a weapon, weapon-tool, or ammo */
964.  		return (P_NONE);
965.  	type = objects[obj->otyp].oc_skill;
966.  	return ((type < 0) ? -type : type);
967.  }
968.  
969.  /*
970.   * Return hit bonus/penalty based on skill of weapon.
971.   * Treat restricted weapons as unskilled.
972.   */
973.  int
974.  weapon_hit_bonus(weapon)
975.  struct obj *weapon;
976.  {
977.      int type, bonus = 0;
978.      static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
979.  
980.      type = weapon_type(weapon);
981.      if (type == P_NONE) {
982.  	bonus = 0;
983.      } else if (type <= P_LAST_WEAPON) {
984.  	switch (P_SKILL(type)) {
985.  	    default: impossible(bad_skill, P_SKILL(type)); /* fall through */
986.  	    case P_ISRESTRICTED:
987.  	    case P_UNSKILLED:   bonus = -4; break;
988.  	    case P_BASIC:       bonus =  0; break;
989.  	    case P_SKILLED:     bonus =  2; break;
990.  	    case P_EXPERT:      bonus =  3; break;
991.  	}
992.      } else if (type == P_TWO_WEAPON_COMBAT) {
993.  	switch (P_SKILL(type)) {
994.  	    default: impossible(bad_skill, P_SKILL(type)); /* fall through */
995.  	    case P_ISRESTRICTED:
996.  	    case P_UNSKILLED:   bonus = -9; break;
997.  	    case P_BASIC:	bonus = -7; break;
998.  	    case P_SKILLED:	bonus = -5; break;
999.  	    case P_EXPERT:	bonus = -3; break;
1000. 	}
1001.     } else if (type == P_BARE_HANDED_COMBAT) {
1002. 	/* restricted == 0 */
1003. 	bonus = ((P_SKILL(type) + 1) * (martial_bonus() ? 2 : 1)) / 2;
1004.     }
1005. 
1006. #ifdef STEED
1007. 	/* KMH -- It's harder to hit while you are riding */
1008. 	if (u.usteed)
1009. 		switch (P_SKILL(P_RIDING)) {
1010. 		    case P_ISRESTRICTED:
1011. 		    case P_UNSKILLED:   bonus -= 2; break;
1012. 		    case P_BASIC:       bonus -= 1; break;
1013. 		    case P_SKILLED:     break;
1014. 		    case P_EXPERT:      break;
1015. 		}
1016. #endif
1017. 
1018.     return bonus;
1019. }
1020. 
1021. /*
1022.  * Return damage bonus/penalty based on skill of weapon.
1023.  * Treat restricted weapons as unskilled.
1024.  */
1025. int
1026. weapon_dam_bonus(weapon)
1027. struct obj *weapon;
1028. {
1029.     int type, bonus = 0;
1030. 
1031.     type = weapon_type(weapon);
1032.     if (type == P_NONE) {
1033. 	bonus = 0;
1034.     } else if (P_RESTRICTED(type) || type <= P_LAST_WEAPON) {
1035. 	switch (P_SKILL(type)) {
1036. 	    default: impossible("weapon_dam_bonus: bad skill %d",P_SKILL(type));
1037. 		     /* fall through */
1038. 	    case P_ISRESTRICTED:
1039. 	    case P_UNSKILLED:	bonus = -2; break;
1040. 	    case P_BASIC:	bonus =  0; break;
1041. 	    case P_SKILLED:	bonus =  1; break;
1042. 	    case P_EXPERT:	bonus =  2; break;
1043. 	}
1044.     } else if (type == P_BARE_HANDED_COMBAT && P_SKILL(type)) {
1045. 	bonus = (P_SKILL(type) * (martial_bonus() ? 2 : 1)) / 2;
1046.     }
1047. 
1048. #ifdef STEED
1049. 	/* KMH -- Riding gives some thrusting damage */
1050. 	if (u.usteed) {
1051. 		switch (P_SKILL(P_RIDING)) {
1052. 		    case P_ISRESTRICTED:
1053. 		    case P_UNSKILLED:   break;
1054. 		    case P_BASIC:       break;
1055. 		    case P_SKILLED:     bonus += 1; break;
1056. 		    case P_EXPERT:      bonus += 2; break;
1057. 		}
1058. 	}
1059. #endif
1060. 
1061.     return bonus;
1062. }
1063. 
1064. /*
1065.  * Initialize weapon skill array for the game.  Start by setting all
1066.  * skills to restricted, then set the skill for every weapon the
1067.  * hero is holding, finally reading the given array that sets
1068.  * maximums.
1069.  */
1070. void
1071. skill_init(class_skill)
1072. struct def_skill *class_skill;
1073. {
1074. 	struct obj *obj;
1075. 	int skmax, skill;
1076. 
1077. 	/* initialize skill array; by default, everything is restricted */
1078. 	for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1079. 	    P_SKILL(skill) = P_ISRESTRICTED;
1080. 	    P_MAX_SKILL(skill) = P_ISRESTRICTED;
1081. 	    P_ADVANCE(skill) = 0;
1082. 	}
1083. 
1084. 	/* Set skill for all weapons in inventory to be basic */
1085. 	for (obj = invent; obj; obj = obj->nobj) {
1086. 	    skill = weapon_type(obj);
1087. 	    if (skill != P_NONE)
1088. 		P_SKILL(skill) = P_BASIC;
1089. 	}
1090. 
1091. 	/* set skills for magic */
1092. 	if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
1093. 		P_SKILL(P_HEALING_SPELL) = P_BASIC;
1094. 	} else if (Role_if(PM_PRIEST)) {
1095. 		P_SKILL(P_CLERIC_SPELL) = P_BASIC;
1096. 	} else if (Role_if(PM_WIZARD)) {
1097. 		P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1098. 		P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
1099. 	}
1100. 
1101. 	/* walk through array to set skill maximums */
1102. 	for (; class_skill->skill != P_NONE; class_skill++) {
1103. 	    skmax = class_skill->skmax;
1104. 	    skill = class_skill->skill;
1105. 
1106. 	    P_MAX_SKILL(skill) = skmax;
1107. 	    if (P_SKILL(skill) == P_ISRESTRICTED)	/* skill pre-set */
1108. 		P_SKILL(skill) = P_UNSKILLED;
1109. 	}
1110. 
1111. 	/* High potential fighters already know how to use their hands. */
1112. 	if (P_MAX_SKILL(P_BARE_HANDED_COMBAT) > P_EXPERT)
1113. 	    P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
1114. 
1115. 	/* Roles that start with a horse know how to ride it */
1116. #ifdef STEED
1117. 	if (urole.petnum == PM_PONY)
1118. 	    P_SKILL(P_RIDING) = P_BASIC;
1119. #endif
1120. 
1121. 	/*
1122. 	 * Make sure we haven't missed setting the max on a skill
1123. 	 * & set advance
1124. 	 */
1125. 	for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1126. 	    if (!P_RESTRICTED(skill)) {
1127. 		if (P_MAX_SKILL(skill) < P_SKILL(skill)) {
1128. 		    impossible("skill_init: curr > max: %s", P_NAME(skill));
1129. 		    P_MAX_SKILL(skill) = P_SKILL(skill);
1130. 		}
1131. 		P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill)-1);
1132. 	    }
1133. 	}
1134. }
1135. 
1136. #endif /* OVLB */
1137. 
1138. /*weapon.c*/