Source:SLASH'EM 0.0.7E7F2/weapon.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to weapon.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/weapon.c#line123]], for example.

The latest source code for vanilla NetHack is at 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.4	2002/11/07	*/
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.   #define PN_POLEARMS		(-1)
14.   #define PN_SABER		(-2)
15.   #define PN_HAMMER		(-3)
16.   #define PN_WHIP			(-4)
17.   #define PN_PADDLE		(-5)
18.   #define PN_FIREARMS		(-6)
19.   #define PN_ATTACK_SPELL		(-7)
20.   #define PN_HEALING_SPELL	(-8)
21.   #define PN_DIVINATION_SPELL	(-9)
22.   #define PN_ENCHANTMENT_SPELL	(-10)
23.   #define PN_PROTECTION_SPELL	(-11)
24.   #define PN_BODY_SPELL		(-12)
25.   #define PN_MATTER_SPELL		(-13)
26.   #define PN_BARE_HANDED		(-14)
27.   #define PN_MARTIAL_ARTS		(-15)
28.   #define PN_RIDING		(-16)
29.   #define PN_TWO_WEAPONS		(-17)
30.   #ifdef LIGHTSABERS
31.   #define PN_LIGHTSABER		(-18)
32.   #endif
33.   
34.   static void FDECL(give_may_advance_msg, (int));
35.   STATIC_PTR int NDECL(practice);
36.   static int FDECL(get_obj_skill, (struct obj *));
37.   
38.   #ifdef LIGHTSABERS
39.   static void FDECL(mon_ignite_lightsaber, (struct obj *, struct monst *));
40.   #endif
41.   
42.   /*WAC practicing needs a delay counter*/
43.   static NEARDATA schar delay;            /* moves left for practice */
44.   static NEARDATA boolean speed_advance = FALSE;
45.   
46.   STATIC_DCL void FDECL(give_may_advance_msg, (int));
47.   
48.   #ifndef OVLB
49.   
50.   STATIC_DCL NEARDATA const short skill_names_indices[];
51.   STATIC_DCL NEARDATA const char *odd_skill_names[];
52.   
53.   #else	/* OVLB */
54.   
55.   /* KMH, balance patch -- updated */
56.   STATIC_OVL NEARDATA const short skill_names_indices[P_NUM_SKILLS] = {
57.   	0,                DAGGER,         KNIFE,        AXE,
58.   	PICK_AXE,         SHORT_SWORD,    BROADSWORD,   LONG_SWORD,
59.   	TWO_HANDED_SWORD, SCIMITAR,       PN_SABER,     CLUB,
60.   	PN_PADDLE,        MACE,           MORNING_STAR,   FLAIL,
61.   	PN_HAMMER,        QUARTERSTAFF,   PN_POLEARMS,  SPEAR,
62.   	JAVELIN,          TRIDENT,        LANCE,        BOW,
63.   	SLING,            PN_FIREARMS,    CROSSBOW,       DART,
64.   	SHURIKEN,         BOOMERANG,      PN_WHIP,      UNICORN_HORN,
65.   #ifdef LIGHTSABERS
66.   	PN_LIGHTSABER,
67.   #endif
68.   	PN_ATTACK_SPELL,     PN_HEALING_SPELL,
69.   	PN_DIVINATION_SPELL, PN_ENCHANTMENT_SPELL,
70.   	PN_PROTECTION_SPELL,            PN_BODY_SPELL,
71.   	PN_MATTER_SPELL,
72.   	PN_BARE_HANDED, 		PN_MARTIAL_ARTS, 
73.   	PN_TWO_WEAPONS,
74.   #ifdef STEED
75.   	PN_RIDING,
76.   #endif
77.   };
78.   
79.   
80.   STATIC_OVL NEARDATA const char * const odd_skill_names[] = {
81.       "no skill",
82.       "polearms",
83.       "saber",
84.       "hammer",
85.       "whip",
86.       "paddle",
87.       "firearms",
88.       "attack spells",
89.       "healing spells",
90.       "divination spells",
91.       "enchantment spells",
92.       "protection spells",
93.       "body spells",
94.       "matter spells",
95.       "bare-handed combat",
96.       "martial arts",
97.       "riding",
98.       "two-handed combat",
99.   #ifdef LIGHTSABERS
100.      "lightsaber"
101.  #endif
102.  };
103.  
104.  
105.  STATIC_OVL void
106.  give_may_advance_msg(skill)
107.  int skill;
108.  {
109.  	You_feel("more %s in your %sskills.",
110.  	    !P_RESTRICTED(skill) ? "confident" : "comfortable",
111.  		skill == P_NONE ?
112.  			"" :
113.  		skill <= P_LAST_WEAPON ?
114.  			"weapon " :
115.  		skill <= P_LAST_SPELL ?
116.  			"spell casting " :
117.              skill <= P_LAST_H_TO_H ?
118.  	            "fighting ":
119.  	            "");
120.  }
121.  
122.  #endif	/* OVLB */
123.  
124.  STATIC_DCL boolean FDECL(can_advance, (int, BOOLEAN_P));
125.  STATIC_DCL boolean FDECL(could_advance, (int));
126.  STATIC_DCL boolean FDECL(peaked_skill, (int));
127.  STATIC_DCL int FDECL(slots_required, (int));
128.  STATIC_DCL boolean FDECL(can_practice, (int)); /* WAC for Practicing */
129.  
130.  #ifdef OVL1
131.  
132.  STATIC_DCL char *FDECL(skill_level_name, (int,char *));
133.  STATIC_DCL void FDECL(skill_advance, (int));
134.  
135.  #endif	/* OVL1 */
136.  
137.  #ifdef OVLB
138.  
139.  #define P_NAME(type) (skill_names_indices[type] > 0 ? \
140.  		      OBJ_NAME(objects[skill_names_indices[type]]) : \
141.  			odd_skill_names[-skill_names_indices[type]])
142.  
143.  static NEARDATA const char kebabable[] = {
144.  	S_XORN, S_DRAGON, S_JABBERWOCK, S_NAGA, S_GIANT, '\0'
145.  };
146.  
147.  /*
148.   *	hitval returns an integer representing the "to hit" bonuses
149.   *	of "otmp" against the monster.
150.   */
151.  int
152.  hitval(otmp, mon)
153.  struct obj *otmp;
154.  struct monst *mon;
155.  {
156.  	int	tmp = 0;
157.  	struct permonst *ptr = mon->data;
158.  	boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
159.  
160.  	if (Is_weapon)
161.  		tmp += otmp->spe;
162.  
163.  /*	Put weapon specific "to hit" bonuses in below:		*/
164.  	tmp += objects[otmp->otyp].oc_hitbon;
165.  	tmp += weapon_hit_bonus(otmp);  /* weapon skill */
166.  	if (u.twoweap && (otmp == uwep || otmp == uswapwep))
167.  		tmp += (skill_bonus(P_TWO_WEAPON_COMBAT) * 2) - 5;
168.  
169.  /*	Put weapon vs. monster type "to hit" bonuses in below:	*/
170.  
171.  	/* Blessed weapons used against undead or demons */
172.  	if (Is_weapon && otmp->blessed &&
173.  	   (is_demon(ptr) || is_undead(ptr))) tmp += 2;
174.  
175.  	/* KMH, balance patch -- new macro */
176.  	if (is_spear(otmp) && index(kebabable, ptr->mlet)) tmp += 2;
177.  
178.  	/* KMH -- Paddles are effective against insects */
179.  	if (Is_weapon && (objects[otmp->otyp].oc_skill == P_PADDLE) &&
180.  			(ptr->mlet == S_ANT || ptr->mlet == S_SPIDER || ptr->mlet == S_XAN))
181.  		tmp += 2;
182.  
183.  	/* trident is highly effective against swimmers */
184.  	if (otmp->otyp == TRIDENT && is_swimmer(ptr)) {
185.  	   if (is_pool(mon->mx, mon->my)) tmp += 4;
186.  	   else if (ptr->mlet == S_EEL || ptr->mlet == S_SNAKE) tmp += 2;
187.  	}
188.  
189.  	/* pick-axe used against xorns and earth elementals */
190.  	/* WAC made generic against "rock people" */
191.  	/* KMH, balance patch -- allow all picks */
192.  	if (is_pick(otmp) &&
193.  /*           (passes_walls(ptr) && thick_skinned(ptr))) tmp += 2;*/
194.             (made_of_rock(ptr))) tmp += 2;
195.  
196.  
197.  #ifdef INVISIBLE_OBJECTS
198.  	/* invisible weapons against monsters who can't see invisible */
199.  	if (otmp->oinvis && !perceives(ptr)) tmp += 3;
200.  #endif
201.  
202.  	/* Check specially named weapon "to hit" bonuses */
203.  	if (otmp->oartifact) tmp += spec_abon(otmp, mon);
204.  
205.  	return tmp;
206.  }
207.  
208.  /* Historical note: The original versions of Hack used a range of damage
209.   * which was similar to, but not identical to the damage used in Advanced
210.   * Dungeons and Dragons.  I figured that since it was so close, I may as well
211.   * make it exactly the same as AD&D, adding some more weapons in the process.
212.   * This has the advantage that it is at least possible that the player would
213.   * already know the damage of at least some of the weapons.  This was circa
214.   * 1987 and I used the table from Unearthed Arcana until I got tired of typing
215.   * them in (leading to something of an imbalance towards weapons early in
216.   * alphabetical order).  The data structure still doesn't include fields that
217.   * fully allow the appropriate damage to be described (there's no way to say
218.   * 3d6 or 1d6+1) so we add on the extra damage in dmgval() if the weapon
219.   * doesn't do an exact die of damage.
220.   *
221.   * Of course new weapons were added later in the development of Nethack.  No
222.   * AD&D consistency was kept, but most of these don't exist in AD&D anyway.
223.   *
224.   * Second edition AD&D came out a few years later; luckily it used the same
225.   * table.  As of this writing (1999), third edition is in progress but not
226.   * released.  Let's see if the weapon table stays the same.  --KAA
227.   * October 2000: It didn't.  Oh, well.
228.   */
229.  
230.  /*
231.   *	dmgval returns an integer representing the damage bonuses
232.   *	of "otmp" against the monster.
233.   */
234.  int
235.  dmgval(otmp, mon)
236.  struct obj *otmp;
237.  struct monst *mon;
238.  {
239.  	int tmp = 0, otyp = otmp->otyp;
240.  	struct permonst *ptr = mon->data;
241.  	boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
242.  
243.  	if (otyp == CREAM_PIE) return 0;
244.  
245.  # ifdef P_SPOON
246.  	if (otmp->oartifact == ART_HOUCHOU)
247.  	        return 9999;
248.  # endif /* P_SPOON */
249.  
250.  	if (bigmonst(ptr)) {
251.  	    if (objects[otyp].oc_wldam)
252.  		tmp = rnd(objects[otyp].oc_wldam);
253.  	    switch (otyp) {
254.  		case IRON_CHAIN:
255.  		case CROSSBOW_BOLT:
256.  		case MORNING_STAR:
257.  		case PARTISAN:
258.  		case RUNESWORD:
259.  		case ELVEN_BROADSWORD:
260.  		case BROADSWORD:	tmp++; break;
261.  
262.  		case FLAIL:
263.  		case RANSEUR:
264.  		case VOULGE:		tmp += rnd(4); break;
265.  
266.  		case ACID_VENOM:
267.  		case HALBERD:
268.  		case SPETUM:		tmp += rnd(6); break;
269.  
270.  		case BATTLE_AXE:
271.  		case BARDICHE:
272.  		case TRIDENT:		tmp += d(2,4); break;
273.  
274.  		case TSURUGI:
275.  		case DWARVISH_MATTOCK:
276.  		case TWO_HANDED_SWORD:	tmp += d(2,6); break;
277.  
278.  #ifdef LIGHTSABERS
279.  		case GREEN_LIGHTSABER:  tmp +=13; break;
280.  #ifdef D_SABER
281.  		case BLUE_LIGHTSABER:   tmp +=12; break;
282.  #endif
283.  		case RED_DOUBLE_LIGHTSABER: 
284.  					if (otmp->altmode) tmp += rnd(11);
285.  					/* fallthrough */
286.  		case RED_LIGHTSABER:    tmp +=10; break;
287.  #endif
288.  	    }
289.  	} else {
290.  	    if (objects[otyp].oc_wsdam)
291.  		tmp = rnd(objects[otyp].oc_wsdam);
292.  	    switch (otyp) {
293.  		case IRON_CHAIN:
294.  		case CROSSBOW_BOLT:
295.  		case MACE:
296.  		case SILVER_MACE:
297.  		case WAR_HAMMER:
298.  		case FLAIL:
299.  		case SPETUM:
300.  		case TRIDENT:		tmp++; break;
301.  
302.  		case BATTLE_AXE:
303.  		case BARDICHE:
304.  		case BILL_GUISARME:
305.  		case GUISARME:
306.  		case LUCERN_HAMMER:
307.  		case MORNING_STAR:
308.  		case RANSEUR:
309.  		case BROADSWORD:
310.  		case ELVEN_BROADSWORD:
311.  		case RUNESWORD:
312.  		case VOULGE:		tmp += rnd(4); break;
313.  
314.  #ifdef LIGHTSABERS
315.  		case GREEN_LIGHTSABER:  tmp +=9; break;
316.  #ifdef D_SABER
317.  		case BLUE_LIGHTSABER:   tmp +=8; break;
318.  #endif
319.  		case RED_DOUBLE_LIGHTSABER:
320.  					if (otmp->altmode) tmp += rnd(9);
321.  					/* fallthrough */
322.  		case RED_LIGHTSABER: 	tmp +=6; break;
323.  #endif
324.  
325.  		case ACID_VENOM:	tmp += rnd(6); break;
326.  	    }
327.  	}
328.  	if (Is_weapon) {
329.  		tmp += otmp->spe;
330.  		/* negative enchantment mustn't produce negative damage */
331.  		if (tmp < 0) tmp = 0;
332.  	}
333.  
334.  	if (objects[otyp].oc_material <= LEATHER && thick_skinned(ptr))
335.  		/* thick skinned/scaled creatures don't feel it */
336.  		tmp = 0;
337.  	if (ptr == &mons[PM_SHADE] && objects[otyp].oc_material != SILVER)
338.  		tmp = 0;
339.  
340.  	/* "very heavy iron ball"; weight increase is in increments of 160 */
341.  	if (otyp == HEAVY_IRON_BALL && tmp > 0) {
342.  	    int wt = (int)objects[HEAVY_IRON_BALL].oc_weight;
343.  
344.  	    if ((int)otmp->owt > wt) {
345.  		wt = ((int)otmp->owt - wt) / 160;
346.  		tmp += rnd(4 * wt);
347.  		if (tmp > 25) tmp = 25;	/* objects[].oc_wldam */
348.  	    }
349.  	}
350.  
351.  /*	Put weapon vs. monster type damage bonuses in below:	*/
352.  	if (Is_weapon || otmp->oclass == GEM_CLASS ||
353.  		otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) {
354.  	    int bonus = 0;
355.  
356.  	    if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
357.  		bonus += rnd(4);
358.  	    if (is_axe(otmp) && is_wooden(ptr))
359.  		bonus += rnd(4);
360.  	    if (objects[otyp].oc_material == SILVER && hates_silver(ptr))
361.  		bonus += rnd(20);
362.  
363.  	    /* Ralf Engels - added more special cases*/
364.  	    /* You can kill a eye with a needle */
365.  	    /* WAC--currently disabled since spheres and gas spores are S_EYE too */
366.  /*	    if((objects[otyp].oc_dir & (PIERCE) ) && (ptr->mlet == S_EYE))
367.  		  	bonus += 2; */
368.  	    /* You cut worms */
369.  	    if((objects[otyp].oc_dir & (SLASH) ) && (ptr->mlet == S_WORM))
370.  			bonus += 2;
371.  	    /* You pierce blobs */
372.  	    if((objects[otyp].oc_dir & (PIERCE) ) && (ptr->mlet == S_BLOB))
373.  			bonus += 2;
374.  	    /* You slash jellies */
375.  	    if((objects[otyp].oc_dir & (SLASH) ) && (ptr->mlet == S_JELLY))
376.  			bonus += 2;
377.  	    /* concussion damage is better agains chitinous armour */
378.  	    if( (objects[otyp].oc_dir & (WHACK) ) &&
379.  	        (ptr->mlet == S_ANT || ptr->mlet == S_SPIDER || ptr->mlet == S_XAN))
380.  			bonus += 2; 
381.  	    /* flyers can better be reached with a polearm */
382.  	    if( (is_pole(otmp) || is_spear(otmp) ) && is_flyer(ptr) )
383.  			bonus += 2; 
384.  	    if (is_pick(otmp) && made_of_rock(ptr) ) 
385.  			bonus += 3;
386.  
387.  	    /* if the weapon is going to get a double damage bonus, adjust
388.  	       this bonus so that effectively it's added after the doubling */
389.  	    if (bonus > 1 && otmp->oartifact && spec_dbon(otmp, mon, 25) >= 25)
390.  		bonus = (bonus + 1) / 2;
391.  
392.  	    tmp += bonus;
393.  	}
394.  
395.  	if (tmp > 0) {
396.  		/* It's debateable whether a rusted blunt instrument
397.  		   should do less damage than a pristine one, since
398.  		   it will hit with essentially the same impact, but
399.  		   there ought to some penalty for using damaged gear
400.  		   so always subtract erosion even for blunt weapons. */
401.  		tmp -= greatest_erosion(otmp);
402.  		if (tmp < 1) tmp = 1;
403.  	}
404.  
405.  	return(tmp);
406.  }
407.  
408.  #endif /* OVLB */
409.  #ifdef OVL0
410.  
411.  STATIC_DCL struct obj *FDECL(oselect, (struct monst *,int));
412.  #define Oselect(x)	if ((otmp = oselect(mtmp, x)) != 0) return(otmp);
413.  
414.  STATIC_OVL struct obj *
415.  oselect(mtmp, x)
416.  struct monst *mtmp;
417.  int x;
418.  {
419.  	struct obj *otmp;
420.  
421.  	for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
422.  	    if (otmp->otyp == x &&
423.  		    /* never select non-cockatrice corpses */
424.  		    !((x == CORPSE || x == EGG) &&
425.  			!touch_petrifies(&mons[otmp->corpsenm])) &&
426.  #ifdef LIGHTSABERS
427.                      (!is_lightsaber(otmp) || otmp->age) &&
428.  #endif
429.  		    (!otmp->oartifact || touch_artifact(otmp,mtmp)))
430.  		return otmp;
431.  	}
432.  	return (struct obj *)0;
433.  }
434.  
435.  
436.  /* WAC added the Ya, increased priority of silver dagger, added Spoon */
437.  /* KMH -- added bullets */
438.  static NEARDATA const int rwep[] =
439.  {	
440.  #ifdef SPOON
441.  	SPOON,
442.  #endif
443.  #ifdef FIREARMS
444.  	FRAG_GRENADE, GAS_GRENADE, ROCKET, SILVER_BULLET, BULLET, SHOTGUN_SHELL,
445.  #endif
446.  	DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR,
447.  	JAVELIN, SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, DARK_ELVEN_ARROW, 
448.  	ARROW, ORCISH_ARROW, CROSSBOW_BOLT, SILVER_DAGGER, ELVEN_DAGGER, 
449.  	DARK_ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, FLINT, ROCK, 
450.  	LOADSTONE, LUCKSTONE, DART,
451.  	/* BOOMERANG, */ CREAM_PIE
452.  	/* note: CREAM_PIE should NOT be #ifdef KOPS */
453.  };
454.  
455.  static NEARDATA const int pwep[] =
456.  {	HALBERD, BARDICHE, SPETUM, BILL_GUISARME, VOULGE, RANSEUR, GUISARME,
457.  	GLAIVE, LUCERN_HAMMER, BEC_DE_CORBIN, FAUCHARD, PARTISAN, LANCE
458.  };
459.  
460.  
461.  static struct obj *propellor;
462.  
463.  struct obj *
464.  select_rwep(mtmp)	/* select a ranged weapon for the monster */
465.  register struct monst *mtmp;
466.  {
467.  	register struct obj *otmp;
468.  	int i;
469.  
470.  #ifdef KOPS
471.  	char mlet = mtmp->data->mlet;
472.  #endif
473.  
474.  	propellor = &zeroobj;
475.  	Oselect(EGG); /* cockatrice egg */
476.  #ifdef KOPS
477.  	if(mlet == S_KOP)	/* pies are first choice for Kops */
478.  	    Oselect(CREAM_PIE);
479.  #endif
480.  	if(throws_rocks(mtmp->data))	/* ...boulders for giants */
481.  	    Oselect(BOULDER);
482.  
483.  	/* Select polearms first; they do more damage and aren't expendable */
484.  	/* The limit of 13 here is based on the monster polearm range limit
485.  	 * (defined as 5 in mthrowu.c).  5 corresponds to a distance of 2 in
486.  	 * one direction and 1 in another; one space beyond that would be 3 in
487.  	 * one direction and 2 in another; 3^2+2^2=13.
488.  	 */
489.  	if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 13 && couldsee(mtmp->mx, mtmp->my)) {
490.  	    for (i = 0; i < SIZE(pwep); i++) {
491.  		/* Only strong monsters can wield big (esp. long) weapons.
492.  		 * Big weapon is basically the same as bimanual.
493.  		 * All monsters can wield the remaining weapons.
494.  		 */
495.  		if (((strongmonst(mtmp->data) && (mtmp->misc_worn_check & W_ARMS) == 0)
496.  			|| !objects[pwep[i]].oc_bimanual) &&
497.  		    (objects[pwep[i]].oc_material != SILVER
498.  			|| !hates_silver(mtmp->data))) {
499.  		    if ((otmp = oselect(mtmp, pwep[i])) != 0) {
500.  			propellor = otmp; /* force the monster to wield it */
501.  			return otmp;
502.  		    }
503.  		}
504.  	    }
505.  	}
506.  
507.  	/*
508.  	 * other than these two specific cases, always select the
509.  	 * most potent ranged weapon to hand.
510.  	 */
511.  	for (i = 0; i < SIZE(rwep); i++) {
512.  	    int prop;
513.  
514.  	    /* shooting gems from slings; this goes just before the darts */
515.  	    /* (shooting rocks is already handled via the rwep[] ordering) */
516.  	    if (rwep[i] == DART && !likes_gems(mtmp->data) &&
517.  		    m_carrying(mtmp, SLING)) {		/* propellor */
518.  		for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
519.  		    if (otmp->oclass == GEM_CLASS &&
520.  			    (otmp->otyp != LOADSTONE || !otmp->cursed)) {
521.  			propellor = m_carrying(mtmp, SLING);
522.  			return otmp;
523.  		    }
524.  	    }
525.  
526.  
527.  		/* KMH -- This belongs here so darts will work */
528.  	    propellor = &zeroobj;
529.  
530.  	    /* KMH, balance patch -- now using skills */
531.  	    prop = (objects[rwep[i]]).oc_skill;
532.  	    if (prop < 0) {
533.  		switch (-prop) {
534.  			/* WAC NOTE: remember to always start the 1st item in 
535.  			 *   a list of propellors with a
536.  			 * 	propellor = ...
537.  			 *   and follow up with
538.  			 *   if (!propellor) ...
539.  			 */
540.  		case P_BOW:
541.  		  propellor = (oselect(mtmp, YUMI));
542.  		  if (!propellor) propellor = (oselect(mtmp, ELVEN_BOW));
543.  		  /* WAC added dark elven bow */
544.  		  if (!propellor) propellor = (oselect(mtmp, DARK_ELVEN_BOW));
545.  		  if (!propellor) propellor = (oselect(mtmp, BOW));
546.  		  if (!propellor) propellor = (oselect(mtmp, ORCISH_BOW));
547.  		  break;
548.  		case P_SLING:
549.  		  propellor = (oselect(mtmp, SLING));
550.  		  break;
551.  		case P_CROSSBOW:
552.  		  propellor = (oselect(mtmp, CROSSBOW));
553.  #ifdef FIREARMS
554.  		case P_FIREARM:
555.  		  if ((objects[rwep[i]].w_ammotyp) == WP_BULLET) {
556.  			propellor = (oselect(mtmp, HEAVY_MACHINE_GUN));
557.  			if (!propellor) propellor = (oselect(mtmp, ASSAULT_RIFLE));
558.  			if (!propellor) propellor = (oselect(mtmp, SUBMACHINE_GUN));
559.  			if (!propellor) propellor = (oselect(mtmp, SNIPER_RIFLE));
560.  			if (!propellor) propellor = (oselect(mtmp, RIFLE));
561.  			if (!propellor) propellor = (oselect(mtmp, PISTOL));
562.  		  } else if ((objects[rwep[i]].w_ammotyp) == WP_SHELL) {
563.  			propellor = (oselect(mtmp, AUTO_SHOTGUN));
564.  			if (!propellor) propellor = (oselect(mtmp, SHOTGUN));
565.  		  } else if ((objects[rwep[i]].w_ammotyp) == WP_ROCKET) {
566.  			propellor = (oselect(mtmp, ROCKET_LAUNCHER));
567.  		  } else if ((objects[rwep[i]].w_ammotyp) == WP_GRENADE) {
568.  			propellor = (oselect(mtmp, GRENADE_LAUNCHER));
569.  			if (!propellor) propellor = &zeroobj;  /* can toss grenades */
570.  		  }
571.  		  break;
572.  #endif
573.  		}
574.  		if ((otmp = MON_WEP(mtmp)) && otmp->cursed && otmp != propellor
575.  				&& mtmp->weapon_check == NO_WEAPON_WANTED)
576.  			propellor = 0;
577.  	    }
578.  	    /* propellor = obj, propellor to use
579.  	     * propellor = &zeroobj, doesn't need a propellor
580.  	     * propellor = 0, needed one and didn't have one
581.  	     */
582.  	    if (propellor != 0) {
583.  		/* Note: cannot use m_carrying for loadstones, since it will
584.  		 * always select the first object of a type, and maybe the
585.  		 * monster is carrying two but only the first is unthrowable.
586.  		 */
587.  		/* STEPHEN WHITE'S NEW CODE */
588.  		if (rwep[i] != LOADSTONE) {
589.  			/* Don't throw a cursed weapon-in-hand or an artifact */
590.  			if ((otmp = oselect(mtmp, rwep[i])) && !otmp->oartifact
591.  			    && (!otmp->cursed || otmp != MON_WEP(mtmp)))
592.  				return(otmp);
593.  		/* STEPHEN WHITE'S NEW CODE */
594.  		/* KMH, balance patch -- removed stone of rotting */
595.  		} else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
596.  		    if (otmp->otyp == LOADSTONE && !otmp->cursed)
597.  			return otmp;
598.  		}
599.  	    }
600.  	  }
601.  
602.  	/* failure */
603.  	return (struct obj *)0;
604.  }
605.  
606.  /* Weapons in order of preference */
607.  /* WAC -- added dark elven short sword here */
608.  /* WAC -- removed polearms */
609.  static const NEARDATA short hwep[] = {
610.  	  CORPSE,  /* cockatrice corpse */
611.  	  TSURUGI, RUNESWORD, HEAVY_HAMMER, 
612.  	  DWARVISH_MATTOCK, 
613.  #ifdef LIGHTSABERS
614.  	  RED_DOUBLE_LIGHTSABER, RED_LIGHTSABER,
615.  #ifdef D_SABER
616.  	  BLUE_LIGHTSABER,
617.  #endif
618.  	  GREEN_LIGHTSABER,
619.  #endif
620.  	  TWO_HANDED_SWORD, BATTLE_AXE,
621.  	  KATANA, UNICORN_HORN, CRYSKNIFE, TRIDENT, LONG_SWORD,
622.  	  ELVEN_BROADSWORD, BROADSWORD, SCIMITAR, SILVER_SABER,
623.  	  SILVER_SHORT_SWORD, SILVER_LONG_SWORD, SILVER_MACE,
624.    	  MORNING_STAR, DARK_ELVEN_SHORT_SWORD, ELVEN_SHORT_SWORD, 
625.    	  DWARVISH_SHORT_SWORD, SHORT_SWORD,
626.  	  ORCISH_SHORT_SWORD, MACE, AXE, DWARVISH_SPEAR, SILVER_SPEAR,
627.  	  ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, FLAIL, BULLWHIP, QUARTERSTAFF,
628.  	  JAVELIN, AKLYS, CLUB, PICK_AXE, FLY_SWATTER, 
629.  #ifdef KOPS
630.  	  RUBBER_HOSE,
631.  #endif /* KOPS */
632.  	  WAR_HAMMER, SILVER_DAGGER, ELVEN_DAGGER, WOODEN_STAKE, DAGGER, 
633.  	  ORCISH_DAGGER,
634.  	  ATHAME, SCALPEL, KNIFE, TORCH, WORM_TOOTH
635.  };
636.  
637.  struct obj *
638.  select_hwep(mtmp)	/* select a hand to hand weapon for the monster */
639.  register struct monst *mtmp;
640.  {
641.  	register struct obj *otmp;
642.  	register int i;
643.  	boolean strong = strongmonst(mtmp->data);
644.  	boolean wearing_shield = (mtmp->misc_worn_check & W_ARMS) != 0;
645.  
646.  	/* prefer artifacts to everything else */
647.  	for(otmp=mtmp->minvent; otmp; otmp = otmp->nobj) {
648.  		if (otmp->oclass == WEAPON_CLASS
649.  			&& otmp->oartifact && touch_artifact(otmp,mtmp)
650.  			&& ((strong && !wearing_shield)
651.  			    || !objects[otmp->otyp].oc_bimanual))
652.  		    return otmp;
653.  	}
654.  
655.  	if(is_giant(mtmp->data))	/* giants just love to use clubs */
656.  	    Oselect(CLUB);
657.  
658.  	/* only strong monsters can wield big (esp. long) weapons */
659.  	/* big weapon is basically the same as bimanual */
660.  	/* all monsters can wield the remaining weapons */
661.  	for (i = 0; i < SIZE(hwep); i++) {
662.  	    if (hwep[i] == CORPSE && !(mtmp->misc_worn_check & W_ARMG))
663.  		continue;
664.  	    if (((strong && !wearing_shield)
665.  			|| !objects[hwep[i]].oc_bimanual) &&
666.  		    (objects[hwep[i]].oc_material != SILVER
667.  			|| !hates_silver(mtmp->data)))
668.  		Oselect(hwep[i]);
669.  	}
670.  
671.  	/* failure */
672.  	return (struct obj *)0;
673.  }
674.  
675.  /* Called after polymorphing a monster, robbing it, etc....  Monsters
676.   * otherwise never unwield stuff on their own.  Might print message.
677.   */
678.  void
679.  possibly_unwield(mon, polyspot)
680.  struct monst *mon;
681.  boolean polyspot;
682.  {
683.  	struct obj *obj, *mw_tmp;
684.  
685.  	if (!(mw_tmp = MON_WEP(mon)))
686.  		return;
687.  	for (obj = mon->minvent; obj; obj = obj->nobj)
688.  		if (obj == mw_tmp) break;
689.  	if (!obj) { /* The weapon was stolen or destroyed */
690.  		MON_NOWEP(mon);
691.  		mon->weapon_check = NEED_WEAPON;
692.  		return;
693.  	}
694.  	if (!attacktype(mon->data, AT_WEAP)) {
695.  		setmnotwielded(mon, mw_tmp);
696.  		MON_NOWEP(mon);
697.  		mon->weapon_check = NO_WEAPON_WANTED;
698.  		obj_extract_self(obj);
699.  		if (cansee(mon->mx, mon->my)) {
700.  		    pline("%s drops %s.", Monnam(mon),
701.  			  distant_name(obj, doname));
702.  		    newsym(mon->mx, mon->my);
703.  		}
704.  		/* might be dropping object into water or lava */
705.  		if (!flooreffects(obj, mon->mx, mon->my, "drop")) {
706.  		    if (polyspot) bypass_obj(obj);
707.  		    place_object(obj, mon->mx, mon->my);
708.  		    stackobj(obj);
709.  		}
710.  		return;
711.  	}
712.  	/* The remaining case where there is a change is where a monster
713.  	 * is polymorphed into a stronger/weaker monster with a different
714.  	 * choice of weapons.  This has no parallel for players.  It can
715.  	 * be handled by waiting until mon_wield_item is actually called.
716.  	 * Though the monster still wields the wrong weapon until then,
717.  	 * this is OK since the player can't see it.  (FIXME: Not okay since
718.  	 * probing can reveal it.)
719.  	 * Note that if there is no change, setting the check to NEED_WEAPON
720.  	 * is harmless.
721.  	 * Possible problem: big monster with big cursed weapon gets
722.  	 * polymorphed into little monster.  But it's not quite clear how to
723.  	 * handle this anyway....
724.  	 */
725.  	if (!(mw_tmp->cursed && mon->weapon_check == NO_WEAPON_WANTED))
726.  	    mon->weapon_check = NEED_WEAPON;
727.  	return;
728.  }
729.  
730.  /* Let a monster try to wield a weapon, based on mon->weapon_check.
731.   * Returns 1 if the monster took time to do it, 0 if it did not.
732.   */
733.  int
734.  mon_wield_item(mon)
735.  register struct monst *mon;
736.  {
737.  	struct obj *obj;
738.  
739.  	/* This case actually should never happen */
740.  	if (mon->weapon_check == NO_WEAPON_WANTED) return 0;
741.  	switch(mon->weapon_check) {
742.  		case NEED_HTH_WEAPON:
743.  			obj = select_hwep(mon);
744.  			break;
745.  		case NEED_RANGED_WEAPON:
746.  			(void)select_rwep(mon);
747.  			obj = propellor;
748.  			
749.  			break;
750.  		case NEED_PICK_AXE:
751.  			obj = m_carrying(mon, PICK_AXE);
752.  			/* KMH -- allow other picks */
753.  			if (!obj && !which_armor(mon, W_ARMS))
754.  			    obj = m_carrying(mon, DWARVISH_MATTOCK);
755.  			break;
756.  		case NEED_AXE:
757.  			/* currently, only 2 types of axe */
758.  			obj = m_carrying(mon, BATTLE_AXE);
759.  			if (!obj || which_armor(mon, W_ARMS))
760.  			    obj = m_carrying(mon, AXE);
761.  			break;
762.  		case NEED_PICK_OR_AXE:
763.  			/* prefer pick for fewer switches on most levels */
764.  			obj = m_carrying(mon, DWARVISH_MATTOCK);
765.  			if (!obj) obj = m_carrying(mon, BATTLE_AXE);
766.  			if (!obj || which_armor(mon, W_ARMS)) {
767.  			    obj = m_carrying(mon, PICK_AXE);
768.  			    if (!obj) obj = m_carrying(mon, AXE);
769.  			}
770.  			break;
771.  		default: impossible("weapon_check %d for %s?",
772.  				mon->weapon_check, mon_nam(mon));
773.  			return 0;
774.  	}
775.  	if (obj && obj != &zeroobj) {
776.  		struct obj *mw_tmp = MON_WEP(mon);
777.  		
778.  		if (mw_tmp && mw_tmp->otyp == obj->otyp) {
779.  		/* already wielding it */
780.  #ifdef LIGHTSABERS
781.  			if (is_lightsaber(obj))
782.  			    mon_ignite_lightsaber(obj, mon);
783.  #endif
784.  			mon->weapon_check = NEED_WEAPON;
785.  			return 0;
786.  		}
787.  		/* Actually, this isn't necessary--as soon as the monster
788.  		 * wields the weapon, the weapon welds itself, so the monster
789.  		 * can know it's cursed and needn't even bother trying.
790.  		 * Still....
791.  		 */
792.  		if (mw_tmp && mw_tmp->cursed && mw_tmp->otyp != CORPSE) {
793.  		    if (canseemon(mon)) {
794.  			char welded_buf[BUFSZ];
795.  			const char *mon_hand = mbodypart(mon, HAND);
796.  
797.  			if (bimanual(mw_tmp)) mon_hand = makeplural(mon_hand);
798.  			Sprintf(welded_buf, "%s welded to %s %s",
799.  				otense(mw_tmp, "are"),
800.  				mhis(mon), mon_hand);
801.  
802.  			if (obj->otyp == PICK_AXE) {
803.  			    pline("Since %s weapon%s %s,",
804.  				  s_suffix(mon_nam(mon)),
805.  				  plur(mw_tmp->quan), welded_buf);
806.  			    pline("%s cannot wield that %s.",
807.  				mon_nam(mon), xname(obj));
808.  			} else {
809.  			    pline("%s tries to wield %s.", Monnam(mon),
810.  				doname(obj));
811.  			    pline("%s %s %s!",
812.  				  s_suffix(Monnam(mon)),
813.  				  xname(mw_tmp), welded_buf);
814.  			}
815.  			mw_tmp->bknown = 1;
816.  		    }
817.  		    mon->weapon_check = NO_WEAPON_WANTED;
818.  		    return 1;
819.  		}
820.  		mon->mw = obj;		/* wield obj */
821.  		setmnotwielded(mon, mw_tmp);
822.  		mon->weapon_check = NEED_WEAPON;
823.  		if (canseemon(mon)) {
824.  		    pline("%s wields %s!", Monnam(mon), doname(obj));
825.  		    if (obj->cursed && obj->otyp != CORPSE) {
826.  			pline("%s %s to %s %s!",
827.  			    Tobjnam(obj, "weld"),
828.  			    is_plural(obj) ? "themselves" : "itself",
829.  			    s_suffix(mon_nam(mon)), mbodypart(mon,HAND));
830.  			obj->bknown = 1;
831.  		    }
832.  		}
833.  		if (artifact_light(obj) && !obj->lamplit) {
834.  		    begin_burn(obj, FALSE);
835.  		    if (canseemon(mon))
836.  			pline("%s brilliantly in %s %s!",
837.  			    Tobjnam(obj, "glow"), 
838.  			    s_suffix(mon_nam(mon)), mbodypart(mon,HAND));
839.  		}
840.  		obj->owornmask = W_WEP;
841.  #ifdef LIGHTSABERS
842.  		if (is_lightsaber(obj))
843.  		    mon_ignite_lightsaber(obj, mon);
844.  #endif
845.  		return 1;
846.  	}
847.  	mon->weapon_check = NEED_WEAPON;
848.  	return 0;
849.  }
850.  
851.  #ifdef LIGHTSABERS
852.  static void
853.  mon_ignite_lightsaber(obj, mon)
854.  struct obj * obj;
855.  struct monst * mon;
856.  {
857.  	/* No obj or not lightsaber */
858.  	if (!obj || !is_lightsaber(obj)) return;
859.  
860.  	/* WAC - Check lightsaber is on */
861.  	if (!obj->lamplit) {
862.  	    if (obj->cursed && !rn2(2)) {
863.  		if (canseemon(mon)) pline("%s %s flickers and goes out.", 
864.  			s_suffix(Monnam(mon)), xname(obj));
865.  
866.  	    } else {
867.  		if (canseemon(mon)) {
868.  			makeknown(obj->otyp);
869.  			pline("%s ignites %s.", Monnam(mon),
870.  				an(xname(obj)));
871.  		}	    	
872.  		begin_burn(obj, FALSE);
873.  	    }
874.  	} else {
875.  		/* Double Lightsaber in single mode? Ignite second blade */
876.  		if (obj->otyp == RED_DOUBLE_LIGHTSABER && !obj->altmode) {
877.  		    /* Do we want to activate dual bladed mode? */
878.  		    if (!obj->altmode && (!obj->cursed || rn2(4))) {
879.  			if (canseemon(mon)) pline("%s ignites the second blade of %s.", 
880.  				Monnam(mon), an(xname(obj)));
881.  		    	obj->altmode = TRUE;
882.  		    	return;
883.  		    } else obj->altmode = FALSE;
884.  		    lightsaber_deactivate(obj, TRUE);
885.  		}
886.  		return;
887.  	}
888.  }
889.  #endif
890.  
891.  /* STEPHEN WHITE'S NEW CODE */
892.  int
893.  abon()		/* attack bonus for strength & dexterity */
894.  {
895.  	int sbon;
896.  	int str = ACURR(A_STR), dex = ACURR(A_DEX);
897.  
898.  	if (Upolyd) return(adj_lev(&mons[u.umonnum]) - 3);
899.  	/* [Tom] lowered these a little */        
900.  	if (str < 6) sbon = -2;
901.  	else if (str < 8) sbon = -1;
902.  	else if (str < 17) sbon = 0;
903.  	else if (str <= STR18(50)) sbon = 1;	/* up to 18/50 */
904.  	else if (str < STR18(100)) sbon = 1;
905.  	else if (str == STR18(100)) sbon = 2;  /* 18/00 */
906.  	else if (str == STR19(19)) sbon = 2;  /* 19 */
907.  	else if (str == STR19(20)) sbon = 3;  /* 20 */
908.  	else if (str == STR19(21)) sbon = 3;  /* 21 */
909.  	else if (str == STR19(22)) sbon = 4;  /* 22 */
910.  	else if (str == STR19(23)) sbon = 4;  /* 23 */
911.  	else if (str == STR19(24)) sbon = 5;  /* 24 */
912.  	else sbon = 5;
913.    
914.  	if (dex < 5) sbon -= 2;
915.  	else if (dex < 7) sbon -= 1;
916.  	else if (dex < 15) sbon += 0;
917.  	else if (dex == 15) sbon += 1;  /* 15 */
918.  	else if (dex == 16) sbon += 1;  /* 16 */
919.  	else if (dex == 17) sbon += 1;  /* 17 */
920.  	else if (dex == 18) sbon += 2;  /* 18 */
921.  	else if (dex == 19) sbon += 2;  /* 19 */
922.  	else if (dex == 20) sbon += 2;  /* 20 */
923.  	else if (dex == 21) sbon += 3;  /* 21 */
924.  	else if (dex == 22) sbon += 3;  /* 22 */
925.  	else if (dex == 23) sbon += 3;  /* 23 */
926.  	else if (dex == 24) sbon += 4;  /* 24 */
927.  	else sbon += 5;
928.  
929.  /* Game tuning kludge: make it a bit easier for a low level character to hit */
930.  	sbon += (u.ulevel < 3) ? 1 : 0;
931.  	return(sbon);
932.  }
933.  
934.  #endif /* OVL0 */
935.  #ifdef OVL1
936.  
937.  /* STEPHEN WHITE'S NEW CODE */
938.  int
939.  dbon()		/* damage bonus for strength */
940.  {
941.  	int str = ACURR(A_STR);
942.  
943.  	if (Upolyd) return(0);
944.  	/* [Tom] I lowered this a little */
945.  	if (str < 6) return(-1);
946.  	else if (str < 16) return(0);
947.  	else if (str < 18) return(1);
948.  	else if (str == 18) return(2);		/* up to 18 */
949.  	else if (str < STR18(100)) return(3);          /* up to 18/99 */
950.  	else if (str == STR18(100)) return(4);         /* 18/00 */
951.  	else if (str == STR19(19)) return(5);         /* 19 */
952.  	else if (str == STR19(20)) return(6);         /* 20 */
953.  	else if (str == STR19(21)) return(7);         /* 21 */
954.  	else if (str == STR19(22)) return(8);         /* 22 */
955.  	else if (str == STR19(23)) return(9);         /* 23 */
956.  	else if (str == STR19(24)) return(10);        /* 24 */
957.  	else return(11);
958.  }
959.  
960.  /* copy the skill level name into the given buffer */
961.  STATIC_OVL char *
962.  skill_level_name(skill, buf)
963.  int skill;
964.  char *buf;
965.  {
966.      const char *ptr;
967.  
968.      switch (P_SKILL(skill)) {
969.  	case P_UNSKILLED:    ptr = "Unskilled"; break;
970.  	case P_BASIC:	     ptr = "Basic";     break;
971.  	case P_SKILLED:	     ptr = "Skilled";   break;
972.  	case P_EXPERT:	     ptr = "Expert";    break;
973.  	case P_MASTER:	     ptr = "Master";    break;
974.  	case P_GRAND_MASTER: 
975.              if (skill <= P_LAST_WEAPON)
976.                      ptr = "Wizard" ;
977.              else if (skill <= P_LAST_SPELL)
978.                      ptr = "Legendary";
979.  	    else if (skill <= P_LAST_H_TO_H) 
980.  	    	    ptr = "Grand Master"; 
981.  	    else ptr = "Unprecedented";
982.  	    break;
983.  	default:	     ptr = "Unknown";	break;
984.      }
985.      Strcpy(buf, ptr);
986.      return buf;
987.  }
988.  
989.  /* return the # of slots required to advance the skill */
990.  STATIC_OVL int
991.  slots_required(skill)
992.  int skill;
993.  {
994.      int tmp = P_SKILL(skill);
995.  
996.        /* WAC if you're over your class max,  it's twice as costly */      
997.        if (tmp >= P_MAX_SKILL(skill)) tmp *=2;
998.        if (tmp < 0) tmp = 0; /* for Restricted skills */
999.    
1000.     /* The more difficult the training, the more slots it takes.
1001.      *	unskilled -> basic	1
1002.      *	basic -> skilled	2
1003.      *	skilled -> expert	3
1004.      */
1005.     if (skill <= P_LAST_SPELL)
1006. 	return tmp;
1007. 
1008.       /* Fewer slots used up for unarmed or martial, miscellaneous skills
1009.      *	unskilled -> basic	1
1010.      *	basic -> skilled	1
1011.      *	skilled -> expert	2
1012.      *	expert -> master	2
1013.      *	master -> grand master	3
1014.      */
1015.     return (tmp + 1) / 2;
1016. }
1017. 
1018. /* return true if this skill can be advanced */
1019. /*ARGSUSED*/
1020. STATIC_OVL boolean
1021. can_advance(skill, speedy)
1022. int skill;
1023. boolean speedy;
1024. {
1025.     return !P_RESTRICTED(skill)
1026. 	    && P_SKILL(skill) < P_MAX_SKILL(skill) && (
1027. #ifdef WIZARD
1028. 	    (wizard && speedy) ||
1029. #endif
1030. 	    (P_ADVANCE(skill) >=
1031. 		(unsigned) practice_needed_to_advance(P_SKILL(skill), skill)
1032. 	    && u.skills_advanced < P_SKILL_LIMIT
1033. 	    && u.weapon_slots >= slots_required(skill)));
1034. }
1035. 
1036. /* WAC return true if skill can be practiced */
1037. STATIC_OVL boolean
1038. can_practice(skill)
1039. int skill;
1040. {
1041.     return !P_RESTRICTED(skill)
1042.             && P_SKILL(skill) < P_MAX_SKILL(skill)
1043.             && u.skills_advanced < P_SKILL_LIMIT;
1044. }
1045. 
1046. 
1047. 
1048. /* return true if this skill could be advanced if more slots were available */
1049. STATIC_OVL boolean
1050. could_advance(skill)
1051. int skill;
1052. {
1053.     return !P_RESTRICTED(skill)
1054. 	    && P_SKILL(skill) < P_MAX_SKILL(skill) && (
1055. 	    (P_ADVANCE(skill) >=
1056. 		(unsigned) practice_needed_to_advance(P_SKILL(skill), skill)
1057. 	    && u.skills_advanced < P_SKILL_LIMIT));
1058. }
1059. 
1060. /* return true if this skill has reached its maximum and there's been enough
1061.    practice to become eligible for the next step if that had been possible */
1062. STATIC_OVL boolean
1063. peaked_skill(skill)
1064. int skill;
1065. {
1066.     return !P_RESTRICTED(skill)
1067. 	    && P_SKILL(skill) >= P_MAX_SKILL(skill) && (
1068. 	    (P_ADVANCE(skill) >=
1069. 		(unsigned) practice_needed_to_advance(P_SKILL(skill), skill)));
1070. }
1071. 
1072. STATIC_OVL void
1073. skill_advance(skill)
1074. int skill;
1075. {
1076. #ifdef WIZARD
1077.     if (wizard && speed_advance && P_RESTRICTED(skill)) {
1078.     	unrestrict_weapon_skill(skill);
1079. 	return;
1080.     }
1081. #endif
1082.     
1083.     u.weapon_slots -= slots_required(skill);
1084.     P_SKILL(skill)++;
1085.     u.skill_record[u.skills_advanced++] = skill;
1086.     /* subtly change the advance message to indicate no more advancement */
1087.     You("are now %s skilled in %s.",
1088. 	P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more",
1089. 	P_NAME(skill));
1090.     if (!tech_known(T_DISARM) && (P_SKILL(skill) == P_SKILLED) && 
1091.     		skill <= P_LAST_WEAPON && skill != P_WHIP) {
1092.     	learntech(T_DISARM, FROMOUTSIDE, 1);
1093.     	You("learn how to perform disarm!");
1094.     }
1095. }
1096. 
1097. const static struct skill_range {
1098. 	short first, last;
1099. 	const char *name;
1100. } skill_ranges[] = {
1101.     { P_FIRST_H_TO_H, P_LAST_H_TO_H, "Fighting Skills" },
1102.     { P_FIRST_WEAPON, P_LAST_WEAPON, "Weapon Skills" },
1103.     { P_FIRST_SPELL,  P_LAST_SPELL,  "Spellcasting Skills" },
1104. };
1105. 
1106. /*
1107.  * The `#enhance' extended command.  What we _really_ would like is
1108.  * to keep being able to pick things to advance until we couldn't any
1109.  * more.  This is currently not possible -- the menu code has no way
1110.  * to call us back for instant action.  Even if it did, we would also need
1111.  * to be able to update the menu since selecting one item could make
1112.  * others unselectable.
1113.  */
1114. int
1115. enhance_weapon_skill()
1116. {
1117.     int pass, i, n, len, longest,
1118. 	to_advance, eventually_advance, maxxed_cnt;
1119.     char buf[BUFSZ], sklnambuf[BUFSZ];
1120.     const char *prefix;
1121.     menu_item *selected;
1122.     anything any;
1123.     winid win;
1124.     boolean speedy = FALSE;
1125. 
1126. #ifdef WIZARD
1127. 	if (wizard && yn("Advance skills without practice?") == 'y')
1128. 	    speedy = TRUE;
1129. #endif
1130. 
1131. 	do {
1132. 	    /* find longest available skill name, count those that can advance */
1133. 	    to_advance = eventually_advance = maxxed_cnt = 0;
1134. 	    for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) {
1135. 		if (P_RESTRICTED(i)) continue;
1136. 		if (i == P_TWO_WEAPON_COMBAT &&
1137. 			youmonst.data->mattk[1].aatyp != AT_WEAP)
1138. 		    continue;
1139. 		if ((len = strlen(P_NAME(i))) > longest)
1140. 		    longest = len;
1141. 		if (can_advance(i, speedy)) to_advance++;
1142. 		else if (could_advance(i)) eventually_advance++;
1143. 		else if (peaked_skill(i)) maxxed_cnt++;
1144. 	    }
1145. 
1146. 	    win = create_nhwindow(NHW_MENU);
1147. 	    start_menu(win);
1148. 
1149. 	    /* start with a legend if any entries will be annotated
1150. 	       with "*" or "#" below */
1151. 	    if (eventually_advance > 0 || maxxed_cnt > 0) {
1152. 		any.a_void = 0;
1153. 		if (eventually_advance > 0) {
1154. 		    Sprintf(buf,
1155. 			    "(Skill%s flagged by \"*\" may be enhanced %s.)",
1156. 			    plur(eventually_advance),
1157. 			    (u.ulevel < MAXULEV) ?
1158. 				"when you're more experienced" :
1159. 				"if skill slots become available");
1160. 		    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
1161. 			     buf, MENU_UNSELECTED);
1162. 		}
1163. 		if (maxxed_cnt > 0) {
1164. 		    Sprintf(buf,
1165. 		  "(Skill%s flagged by \"#\" cannot be enhanced any further.)",
1166. 			    plur(maxxed_cnt));
1167. 		    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
1168. 			     buf, MENU_UNSELECTED);
1169. 		}
1170. 		add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
1171. 			     "", MENU_UNSELECTED);
1172. 	    }
1173. 
1174. 	    /* List the skills, making ones that could be advanced
1175. 	       selectable.  List the miscellaneous skills first.
1176. 	       Possible future enhancement:  list spell skills before
1177. 	       weapon skills for spellcaster roles. */
1178. 	  for (pass = 0; pass < SIZE(skill_ranges); pass++)
1179. 	    for (i = skill_ranges[pass].first;
1180. 		 i <= skill_ranges[pass].last; i++) {
1181. 		/* Print headings for skill types */
1182. 		any.a_void = 0;
1183. 		if (i == skill_ranges[pass].first)
1184. 		    add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
1185. 			     skill_ranges[pass].name, MENU_UNSELECTED);
1186. 
1187. 		if (P_RESTRICTED(i)) continue;
1188. 		if (i == P_TWO_WEAPON_COMBAT &&
1189. 			youmonst.data->mattk[1].aatyp != AT_WEAP)
1190. 		    continue;
1191. 		/*
1192. 		 * Sigh, this assumes a monospaced font unless
1193. 		 * iflags.menu_tab_sep is set in which case it puts
1194. 		 * tabs between columns.
1195. 		 * The 12 is the longest skill level name.
1196. 		 * The "    " is room for a selection letter and dash, "a - ".
1197. 		 */
1198. 		if (can_advance(i, speedy))
1199. 		    prefix = "";	/* will be preceded by menu choice */
1200. 		else if (could_advance(i))
1201. 		    prefix = "  * ";
1202. 		else if (peaked_skill(i))
1203. 		    prefix = "  # ";
1204. 		else
1205. 		    prefix = (to_advance + eventually_advance +
1206. 				maxxed_cnt > 0) ? "    " : "";
1207. 		(void) skill_level_name(i, sklnambuf);
1208. #ifdef WIZARD
1209. 		if (wizard) {
1210. 		    if (!iflags.menu_tab_sep)
1211. 			Sprintf(buf, " %s%-*s %-12s %4d(%4d)",
1212. 			    prefix, longest, P_NAME(i), sklnambuf,
1213. 			    P_ADVANCE(i),
1214. 			    practice_needed_to_advance(P_SKILL(i), i));
1215. 		    else
1216. 			Sprintf(buf, " %s%s\t%s\t%5d(%4d)",
1217. 			    prefix, P_NAME(i), sklnambuf,
1218. 			    P_ADVANCE(i),
1219. 			    practice_needed_to_advance(P_SKILL(i), i));
1220. 		 } else
1221. #endif
1222. 		{
1223. 		    if (!iflags.menu_tab_sep)
1224. 			Sprintf(buf, " %s %-*s [%s]",
1225. 			    prefix, longest, P_NAME(i), sklnambuf);
1226. 		    else
1227. 			Sprintf(buf, " %s%s\t[%s]",
1228. 			    prefix, P_NAME(i), sklnambuf);
1229. 		}
1230. 		any.a_int = can_advance(i, speedy) ? i+1 : 0;
1231. 		add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
1232. 			 buf, MENU_UNSELECTED);
1233. 	    }
1234. 
1235. 	    Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:" :
1236. 					   "Current skills:");
1237. #ifdef WIZARD
1238. 	    if (wizard && !speedy)
1239. 		Sprintf(eos(buf), "  (%d slot%s available)",
1240. 			u.weapon_slots, plur(u.weapon_slots));
1241. #endif
1242. 	    end_menu(win, buf);
1243. 	    n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
1244. 	    destroy_nhwindow(win);
1245. 	    if (n > 0) {
1246. 		n = selected[0].item.a_int - 1;	/* get item selected */
1247. 		free((genericptr_t)selected);
1248. 		skill_advance(n);
1249. 		/* check for more skills able to advance, if so then .. */
1250. 		for (n = i = 0; i < P_NUM_SKILLS; i++) {
1251. 		    if (can_advance(i, speedy)) {
1252. 			if (!speedy) You_feel("you could be more dangerous!");
1253. 			n++;
1254. 			break;
1255. 		    }
1256. 		}
1257. 	    }
1258. 	} while (speedy && n > 0);
1259. 	return 0;
1260. }
1261. 
1262. /*
1263.  * Change from restricted to unrestricted, allowing P_BASIC as max.  This
1264.  * function may be called with with P_NONE.  Used in pray.c.
1265.  */
1266. void
1267. unrestrict_weapon_skill(skill)
1268. int skill;
1269. {
1270.     if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
1271. 	P_SKILL(skill) = P_UNSKILLED;
1272. 	P_MAX_SKILL(skill) = P_BASIC;
1273. 	P_ADVANCE(skill) = 0;
1274.     }
1275. }
1276. 
1277. #endif /* OVL1 */
1278. #ifdef OVLB
1279. 
1280. void
1281. use_skill(skill,degree)
1282. int skill;
1283. int degree;
1284. {
1285.     boolean advance_before;
1286. 
1287. /*    if (skill != P_NONE && !P_RESTRICTED(skill)) {*/
1288.     if (skill != P_NONE) {
1289. 	advance_before = can_advance(skill, FALSE);
1290. 	P_ADVANCE(skill) += degree;
1291. 	if (!advance_before && can_advance(skill, FALSE)) {
1292. 	    give_may_advance_msg(skill);
1293. 	    if (P_RESTRICTED(skill)) {
1294. 	    	unrestrict_weapon_skill(skill);
1295. 	    }
1296. 	}
1297.     }
1298. }
1299. 
1300. void
1301. add_weapon_skill(n)
1302. int n;	/* number of slots to gain; normally one */
1303. {
1304.     int i, before, after;
1305. 
1306.     for (i = 0, before = 0; i < P_NUM_SKILLS; i++)
1307. 	if (can_advance(i, FALSE)) before++;
1308.     u.weapon_slots += n;
1309.     for (i = 0, after = 0; i < P_NUM_SKILLS; i++)
1310. 	if (can_advance(i, FALSE)) after++;
1311.     if (before < after)
1312. 	give_may_advance_msg(P_NONE);
1313. }
1314. 
1315. void
1316. lose_weapon_skill(n)
1317. int n;	/* number of slots to lose; normally one */
1318. {
1319.     int skill;
1320.     boolean maybe_loose_disarm = FALSE;
1321. 
1322.     while (--n >= 0) {
1323. 	/* deduct first from unused slots, then from last placed slot, if any */
1324. 	if (u.weapon_slots) {
1325. 	    u.weapon_slots--;
1326. 	} else if (u.skills_advanced) {
1327. 	    skill = u.skill_record[--u.skills_advanced];
1328. 	    if (P_SKILL(skill) <= P_UNSKILLED)
1329. 		panic("lose_weapon_skill (%d)", skill);
1330. 	    if (skill <= P_LAST_WEAPON && skill != P_WHIP &&
1331. 		    P_SKILL(skill) == P_SKILLED)
1332. 		maybe_loose_disarm = TRUE;
1333. 	    P_SKILL(skill)--;	/* drop skill one level */
1334. 	    /* Lost skill might have taken more than one slot; refund rest. */
1335. 	    u.weapon_slots = slots_required(skill) - 1;
1336. 	    /* It might now be possible to advance some other pending
1337. 	       skill by using the refunded slots, but giving a message
1338. 	       to that effect would seem pretty confusing.... */
1339. 	}
1340.     }
1341. 
1342.     if (maybe_loose_disarm && tech_known(T_DISARM)) {
1343. 	int i;
1344. 	for(i = u.skills_advanced - 1; i >= 0; i--) {
1345. 	    skill = u.skill_record[i];
1346. 	    if (skill <= P_LAST_WEAPON && skill != P_WHIP &&
1347. 		    P_SKILL(skill) >= P_SKILLED)
1348. 		break;
1349. 	}
1350. 	if (i < 0)
1351. 	    learntech(T_DISARM, FROMOUTSIDE, -1);
1352.     }
1353. }
1354. 
1355. int
1356. weapon_type(obj)
1357. struct obj *obj;
1358. {
1359. 	/* KMH, balance patch -- now uses the object table */
1360. 	int type;
1361. 
1362. 	if (!obj)
1363. 		/* Not using a weapon */
1364. 	    return (martial_bonus() ? P_MARTIAL_ARTS :
1365. 				P_BARE_HANDED_COMBAT);
1366. 	if (obj->oclass != WEAPON_CLASS && obj->oclass != TOOL_CLASS &&
1367. 	    obj->oclass != GEM_CLASS)
1368. 		/* Not a weapon, weapon-tool, or ammo */
1369. 		return (P_NONE);
1370. 	type = objects[obj->otyp].oc_skill;
1371. 	return ((type < 0) ? -type : type);
1372. }
1373. 
1374. int
1375. uwep_skill_type()
1376. {
1377. 	if (u.twoweap)
1378. 		return P_TWO_WEAPON_COMBAT;
1379. 	return weapon_type(uwep);
1380. }
1381. 
1382. /*
1383.  * Return hit bonus/penalty based on skill of weapon.
1384.  * Treat restricted weapons as unskilled.
1385.  */
1386. int
1387. weapon_hit_bonus(weapon)
1388. struct obj *weapon;
1389. {
1390.     int type, wep_type, bonus = 0;
1391. #if 0
1392.     int skill;
1393. #endif
1394.     static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
1395. 
1396.     wep_type = weapon_type(weapon);
1397. #if 0
1398.     /* use two weapon skill only if attacking with one of the wielded weapons */
1399.     type = (u.twoweap && (weapon == uwep || weapon == uswapwep)) ?
1400. 	    P_TWO_WEAPON_COMBAT : wep_type;
1401. #endif
1402.     type = wep_type;
1403.     if (type == P_NONE) {
1404. 	bonus = 0;
1405.     } else if (type <= P_LAST_WEAPON) {
1406. 	switch (P_SKILL(type)) {
1407. 	    default: impossible(bad_skill, P_SKILL(type)); /* fall through */
1408. 	    case P_ISRESTRICTED:
1409. 	    case P_UNSKILLED:   bonus = -4; break;
1410. 	    case P_BASIC:       bonus =  0; break;
1411. 		    case P_SKILLED:     bonus =  1; break;
1412. 		    case P_EXPERT:      bonus =  2; break;
1413. 		    case P_MASTER:	bonus =  3; break;
1414. 		    case P_GRAND_MASTER:	bonus =  4; break;
1415. 	}
1416. /* WAC -- No longer needed here...  */
1417. #if 0
1418.     } else if (type == P_TWO_WEAPON_COMBAT) {
1419. 	skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1420. 	if (P_SKILL(wep_type) < skill) skill = P_SKILL(wep_type);
1421. 	switch (skill) {
1422. 	    default: impossible(bad_skill, skill); /* fall through */
1423. 	    case P_ISRESTRICTED:
1424. 	    case P_UNSKILLED:   bonus = -9; break;
1425. 	    case P_BASIC:	bonus = -7; break;
1426. 	    case P_SKILLED:	bonus = -5; break;
1427. 	    case P_EXPERT:	bonus = -3; break;
1428. 	    case P_MASTER:	bonus = -1; break;
1429. 	    case P_GRAND_MASTER:	bonus =  1; break;
1430. 	}
1431. 	if (u.twoweap) bonus -= 2;
1432. 	}
1433. #endif
1434.         /* WAC  because we split Martial Arts and Bare handed */
1435.     } else if (type <= P_LAST_H_TO_H) {
1436. 	/*
1437. 	 *	       b.h.  m.a.
1438. 	 *	unskl:	+1   n/a
1439. 	 *	basic:	+1    +3
1440. 	 *	skild:	+2    +4
1441. 	 *	exprt:	+2    +5
1442. 	 *	mastr:	+3    +6
1443. 	 *	grand:	+3    +7
1444. 	 */
1445. 	bonus = P_SKILL(type);
1446. 	bonus = max(bonus,P_UNSKILLED) - 1;	/* unskilled => 0 */
1447. 	bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2;
1448.     }
1449. 
1450. #ifdef STEED
1451. 	/* KMH -- It's harder to hit while you are riding */
1452. 	if (u.usteed) {
1453. 		switch (P_SKILL(P_RIDING)) {
1454. 		    case P_ISRESTRICTED:
1455. 		    case P_UNSKILLED:   bonus -= 2; break;
1456. 		    case P_BASIC:       bonus -= 1; break;
1457. 		    case P_SKILLED:     break;
1458. 		    case P_EXPERT:      break;
1459. 		    case P_MASTER:	bonus += 1; break;
1460. 		    case P_GRAND_MASTER:	bonus += 2; break;
1461. 		}
1462. 		if (type == P_LANCE) bonus++;
1463. 	}
1464. #endif
1465. 
1466.     return bonus;
1467. }
1468. 
1469. /*
1470.  * Return damage bonus/penalty based on skill of weapon.
1471.  * Treat restricted weapons as unskilled.
1472.  */
1473. int
1474. weapon_dam_bonus(weapon)
1475. struct obj *weapon;
1476. {
1477.     int type, wep_type, bonus = 0;
1478. #if 0
1479.     int skill;
1480. #endif
1481. 
1482.     wep_type = weapon_type(weapon);
1483. #if 0
1484.     /* use two weapon skill only if attacking with one of the wielded weapons */
1485.     type = (u.twoweap && (weapon == uwep || weapon == uswapwep)) ?
1486. 	    P_TWO_WEAPON_COMBAT : wep_type;
1487. #endif
1488.     type = wep_type;
1489.     if (type == P_NONE) {
1490. 	bonus = 0;
1491.     } else if (type <= P_LAST_WEAPON) {
1492. 	switch (P_SKILL(type)) {
1493. 	    default: impossible("weapon_dam_bonus: bad skill %d",P_SKILL(type));
1494. 		     /* fall through */
1495. 	    case P_ISRESTRICTED:
1496. 	    case P_UNSKILLED:	bonus = -2; break;
1497. 	    case P_BASIC:	bonus =  0; break;
1498. 	    case P_SKILLED:	bonus =  1; break;
1499. 	    case P_EXPERT:	bonus =  2; break;
1500. 	    case P_MASTER:	bonus =  3; break;
1501. 	    case P_GRAND_MASTER:bonus =  4; break;
1502. 	}
1503. #if 0
1504.     } else if (type == P_TWO_WEAPON_COMBAT) {
1505. 	skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1506. 	if (P_SKILL(wep_type) < skill) skill = P_SKILL(wep_type);
1507. 	switch (skill) {
1508. 	    default:
1509. 	    case P_ISRESTRICTED:
1510. 	    case P_UNSKILLED:	bonus = -3; break;
1511. 	    case P_BASIC:	bonus = -1; break;
1512. 	    case P_SKILLED:	bonus = 0; break;
1513. 	    case P_EXPERT:	bonus = 1; break;
1514. 	}
1515. #endif
1516.         /* from == P_bare... to < = P_last_h.... */
1517.     } else if (type <= P_LAST_H_TO_H) {
1518. 	/*
1519. 	 *	       b.h.  m.a.
1520. 	 *	unskl:	 0   n/a
1521. 	 *	basic:	+1    +3
1522. 	 *	skild:	+1    +4
1523. 	 *	exprt:	+2    +6
1524. 	 *	mastr:	+2    +7
1525. 	 *	grand:	+3    +9
1526. 	 */
1527. 	bonus = P_SKILL(type);
1528. 	bonus = max(bonus,P_UNSKILLED) - 1;	/* unskilled => 0 */
1529. 	bonus = ((bonus + 1) * (martial_bonus() ? 3 : 1)) / 2;
1530.     } /* Misc skills aren't usually called by weapons */
1531. 
1532. #ifdef STEED
1533. 	/* KMH -- Riding gives some thrusting damage */
1534. 	if (u.usteed) {
1535. 		switch (P_SKILL(P_RIDING)) {
1536. 		    case P_ISRESTRICTED:
1537. 		    case P_UNSKILLED:   break;
1538. 		    case P_BASIC:       break;
1539. 		    case P_SKILLED:     bonus += 1; break;
1540. 		    case P_EXPERT:      bonus += 2; break;
1541. 		}
1542. 	}
1543. #endif
1544. 
1545.     return bonus;
1546. }
1547. 
1548. int
1549. skill_bonus(type)
1550. int type;
1551. {
1552.     int bonus = 0;
1553.     if (type == P_NONE) {
1554. 		bonus = 0;
1555.     } else if (type <= P_LAST_WEAPON) {
1556. 		switch (P_SKILL(type)) {
1557. 		    default: impossible("skill_bonus: bad skill %d",P_SKILL(type));
1558. 			     /* fall through */
1559. 		    case P_ISRESTRICTED:
1560. 		    case P_UNSKILLED:   bonus = -2; break;
1561. 		    case P_BASIC:       bonus =  0; break;
1562. 		    case P_SKILLED:     bonus =  1; break;
1563. 		    case P_EXPERT:      bonus =  2; break;
1564. 		    case P_MASTER:	bonus =  3; break;
1565. 		    case P_GRAND_MASTER:	bonus =  4; break;
1566. 		}
1567.     } else if (type == P_BARE_HANDED_COMBAT || type == P_MARTIAL_ARTS) {
1568. 		bonus = (P_SKILL(type) * (martial_bonus() ? 2 : 1)) / 2;
1569.     } else {
1570.     		/* Misc. */
1571. 		switch (P_SKILL(type)) {
1572. 		    default: impossible("skill_bonus: bad skill %d",P_SKILL(type));
1573. 			     /* fall through */
1574. 		    case P_ISRESTRICTED:
1575. 		    case P_UNSKILLED:   bonus = -2; break;
1576. 		    case P_BASIC:       bonus =  0; break;
1577. 		    case P_SKILLED:     bonus =  1; break;
1578. 		    case P_EXPERT:      bonus =  2; break;
1579. 		    case P_MASTER:	bonus =  3; break;
1580. 		    case P_GRAND_MASTER:	bonus =  4; break;
1581. 		}
1582.     }
1583. 
1584.     return bonus;
1585. }
1586. 
1587. /* Try to return an associated skill for the specified object */
1588. static 
1589. int get_obj_skill(obj)
1590. struct obj *obj;
1591. {
1592. 	int skill;
1593. 	
1594. 	/* Try for a weapon skill */
1595. 	skill = weapon_type(obj);
1596. 
1597. 	/* Try for a spell type */
1598. 	if (skill == P_NONE && obj->oclass == SPBOOK_CLASS) 
1599. 		skill = spell_skilltype(obj->otyp);
1600. 	
1601. 	/* Should be integrated into oc_subtyp as soon as more skills are 
1602. 	 * invented 
1603. 	 */
1604. #ifdef STEED
1605. 	if (obj->otyp == SADDLE) skill = P_RIDING;
1606. #endif
1607.     	/* Negative skills == not a skill */
1608. 	if (skill < P_NONE) skill = P_NONE;
1609. 
1610. 	return (skill);
1611. }
1612. 
1613. /*
1614.  * Initialize weapon skill array for the game.  Start by setting all
1615.  * skills to restricted, then set the skill for every weapon the
1616.  * hero is holding, finally reading the given array that sets
1617.  * maximums.
1618.  */
1619. void
1620. skill_init(class_skill)
1621. const struct def_skill *class_skill;
1622. {
1623. 	struct obj *obj;
1624. 	int skmax, skill;
1625. 
1626. 	/* initialize skill array; by default, everything is restricted */
1627. 	for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1628. 	    P_SKILL(skill) = P_ISRESTRICTED;
1629. 	    P_MAX_SKILL(skill) = P_ISRESTRICTED;
1630. 	    P_ADVANCE(skill) = 0;
1631. 	}
1632. 
1633. 	/* Walk through array to set skill maximums */
1634. 	for (; class_skill->skill != P_NONE; class_skill++) {
1635. 	    skill = class_skill->skill;
1636. 	    skmax = class_skill->skmax;
1637. 
1638. 	    P_MAX_SKILL(skill) = skmax;
1639. 	    if (P_SKILL(skill) == P_ISRESTRICTED)       /* skill pre-set */
1640. 			P_SKILL(skill) = P_UNSKILLED;
1641. 	    /* Really high potential in the skill
1642. 	     * Right now only used for H to H skills
1643. 	     */
1644. 	    if (P_MAX_SKILL(skill) > P_EXPERT) P_SKILL(skill) = P_BASIC;
1645. 	}
1646. 
1647. 	/* Set skill for all objects in inventory to be basic */
1648. 	for (obj = invent; obj; obj = obj->nobj) {
1649. 	    skill = get_obj_skill(obj);
1650. 	    if (skill != P_NONE) {
1651. 		P_SKILL(skill) = P_BASIC;
1652. 		/* KMH -- If you came into the dungeon with it, you should at least be skilled */
1653. 		if (P_MAX_SKILL(skill) < P_SKILLED) {
1654. 			pline("Warning: %s should be at least skilled.  Fixing...", P_NAME(skill));
1655. 			P_MAX_SKILL(skill) = P_SKILLED;
1656. 		}
1657. 	    }
1658. 	}
1659. 
1660. #if 0  /* This should all be handled above now... */
1661. 	/* set skills for magic */
1662.     /* WAC - added setup for role is F, I, M or N*/
1663. 	if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
1664. 		P_SKILL(P_HEALING_SPELL) = P_BASIC;
1665. 	} else if (Role_if(PM_PRIEST)) {
1666. 		P_SKILL(P_PROTECTION_SPELL) = P_BASIC;
1667.     } else if (Role_if(PM_NECROMANCER)) {
1668. 		P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1669.     } else if (Role_if(PM_FLAME_MAGE) || Role_if(PM_ICE_MAGE))  {
1670. 		P_SKILL(P_MATTER_SPELL) = P_BASIC;
1671. 	} else if (Role_if(PM_WIZARD)) {
1672. 		P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1673. 		P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
1674. 	}
1675. 
1676. 	/* High potential fighters already know how to use their hands. */
1677. 	if (P_MAX_SKILL(P_BARE_HANDED_COMBAT) > P_EXPERT)
1678. 	    P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
1679. 	if (P_MAX_SKILL(P_MARTIAL_ARTS) > P_EXPERT)
1680. 		P_SKILL(P_MARTIAL_ARTS) = P_BASIC;
1681. #endif
1682. 
1683. 	/* Roles that start with a horse know how to ride it */
1684. #ifdef STEED
1685. 	if (urole.petnum == PM_PONY)
1686. 	    P_SKILL(P_RIDING) = P_BASIC;
1687. #endif
1688. 
1689. 	/*
1690. 	 * Make sure we haven't missed setting the max on a skill
1691. 	 * & set advance
1692. 	 */
1693. 	for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1694. 	    if (!P_RESTRICTED(skill)) {
1695. 		if (P_MAX_SKILL(skill) < P_SKILL(skill)) {
1696. 		    impossible("skill_init: curr > max: %s", P_NAME(skill));
1697. 		    P_MAX_SKILL(skill) = P_SKILL(skill);
1698. 		}
1699. 		P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill)-1,skill);
1700. 	    }
1701. 	}
1702. }
1703. 
1704. /*WAC  weapon practice code*/
1705. STATIC_PTR int
1706. practice()
1707. {
1708. 	if (delay) {    /* not if (delay++), so at end delay == 0 */
1709. 		delay++;
1710. 		use_skill(weapon_type(uwep), 1);
1711. 		/*WAC a bit of practice so even if you're interrupted
1712. 		  you won't be wasting your time ;B*/
1713. 		return(1); /* still busy */
1714.     }
1715. 	You("finish your practice session.");
1716. 	use_skill(weapon_type(uwep),
1717. 	    practice_needed_to_advance(P_SKILL(weapon_type(uwep)),weapon_type(uwep))/3);
1718. 	return(0);
1719. }
1720. 
1721. void
1722. practice_weapon()
1723. {
1724. 	if (can_practice(weapon_type(uwep))
1725. #ifdef WIZARD
1726. 	    || (wizard && (yn("Skill at normal max. Practice?") == 'y'))
1727. #endif
1728. 	    ) {
1729. 		if (uwep)    
1730. 		    You("start practicing intensely with %s",doname(uwep));
1731. 		else
1732. 		    You("start practicing intensely with your %s %s.",
1733. 		            uarmg ? "gloved" : "bare",      /* Del Lamb */
1734. 		makeplural(body_part(HAND)));
1735. 
1736. 		delay=-10;
1737. 		set_occupation(practice, "practicing", 0);
1738. 	} else if (P_SKILL(weapon_type(uwep)) >= P_MAX_SKILL(weapon_type(uwep)))
1739. 		You("cannot increase your skill in %s.", P_NAME(weapon_type(uwep)));
1740. 	else You("cannot learn much about %s right now.",
1741.                 P_NAME(weapon_type(uwep)));
1742.                 
1743. }
1744. 
1745. void
1746. setmnotwielded(mon,obj)
1747. register struct monst *mon;
1748. register struct obj *obj;
1749. {
1750.     if (!obj) return;
1751.     if (artifact_light(obj) && obj->lamplit) {
1752. 	end_burn(obj, FALSE);
1753. 	if (canseemon(mon))
1754. 	    pline("%s in %s %s %s glowing.", The(xname(obj)),
1755. 		  s_suffix(mon_nam(mon)), mbodypart(mon,HAND),
1756. 		  otense(obj, "stop"));
1757.     }
1758.     obj->owornmask &= ~W_WEP;
1759. }
1760. 
1761. #endif /* OVLB */
1762. 
1763. /*weapon.c*/