1 /* NetHack 3.6 weapon.c $NHDT-Date: 1548209744 2019/01/23 02:15:44 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.69 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
9 /* JNetHack may be freely redistributed. See license for details. */
12 * This module contains code for calculation of "to hit" and damage
13 * bonuses for any given weapon used, as well as weapons selection
19 STATIC_DCL void FDECL(give_may_advance_msg, (int));
20 STATIC_DCL boolean FDECL(could_advance, (int));
21 STATIC_DCL boolean FDECL(peaked_skill, (int));
22 STATIC_DCL int FDECL(slots_required, (int));
23 STATIC_DCL void FDECL(skill_advance, (int));
25 /* Categories whose names don't come from OBJ_NAME(objects[type])
27 #define PN_BARE_HANDED (-1) /* includes martial arts */
28 #define PN_TWO_WEAPONS (-2)
29 #define PN_RIDING (-3)
30 #define PN_POLEARMS (-4)
32 #define PN_HAMMER (-6)
34 #define PN_ATTACK_SPELL (-8)
35 #define PN_HEALING_SPELL (-9)
36 #define PN_DIVINATION_SPELL (-10)
37 #define PN_ENCHANTMENT_SPELL (-11)
38 #define PN_CLERIC_SPELL (-12)
39 #define PN_ESCAPE_SPELL (-13)
40 #define PN_MATTER_SPELL (-14)
42 STATIC_VAR NEARDATA const short skill_names_indices[P_NUM_SKILLS] = {
43 0, DAGGER, KNIFE, AXE, PICK_AXE, SHORT_SWORD, BROADSWORD, LONG_SWORD,
44 TWO_HANDED_SWORD, SCIMITAR, PN_SABER, CLUB, MACE, MORNING_STAR, FLAIL,
45 PN_HAMMER, QUARTERSTAFF, PN_POLEARMS, SPEAR, TRIDENT, LANCE, BOW, SLING,
46 CROSSBOW, DART, SHURIKEN, BOOMERANG, PN_WHIP, UNICORN_HORN,
47 PN_ATTACK_SPELL, PN_HEALING_SPELL, PN_DIVINATION_SPELL,
48 PN_ENCHANTMENT_SPELL, PN_CLERIC_SPELL, PN_ESCAPE_SPELL, PN_MATTER_SPELL,
49 PN_BARE_HANDED, PN_TWO_WEAPONS, PN_RIDING
52 /* note: entry [0] isn't used */
53 STATIC_VAR NEARDATA const char *const odd_skill_names[] = {
55 "no skill", "bare hands", /* use barehands_or_martial[] instead */
56 "two weapon combat", "riding", "polearms", "saber", "hammer", "whip",
57 "attack spells", "healing spells", "divination spells",
58 "enchantment spells", "clerical spells", "escape spells", "matter spells",
60 "no skill", "
\91f
\8eè", /* use barehands_or_martial[] instead */
61 "
\93ñ
\93\81\97¬", "
\8bR
\8fæ", "
\92·
\95\80", "
\83T
\81[
\83x
\83\8b", "
\83n
\83\93\83}
\81[", "
\95Ú",
62 "
\8dU
\8c\82", "
\8e¡
\96ü", "
\97\
\92m",
63 "
\95â
\8f\95", "
\91m
\97µ", "
\92E
\8fo", "
\95¨
\8e¿",
66 /* indexed vis `is_martial() */
67 STATIC_VAR NEARDATA const char *const barehands_or_martial[] = {
69 "bare handed combat", "martial arts"
71 "
\91f
\8eè", "
\91Ì
\8fp"
75 #define P_NAME(type) \
76 ((skill_names_indices[type] > 0) \
77 ? OBJ_NAME(objects[skill_names_indices[type]]) \
78 : (type == P_BARE_HANDED_COMBAT) \
79 ? barehands_or_martial[martial_bonus()] \
80 : odd_skill_names[-skill_names_indices[type]])
82 static NEARDATA const char kebabable[] = { S_XORN, S_DRAGON, S_JABBERWOCK,
83 S_NAGA, S_GIANT, '\0' };
86 give_may_advance_msg(skill)
90 You_feel("more confident in your %sskills.",
91 (skill == P_NONE) ? ""
92 : (skill <= P_LAST_WEAPON) ? "weapon "
93 : (skill <= P_LAST_SPELL) ? "spell casting "
96 You("%s
\83X
\83L
\83\8b\82ð
\8d\82\82ß
\82é
\8e©
\90M
\82ª
\97N
\82¢
\82Ä
\82«
\82½
\81D",
97 (skill == P_NONE) ? ""
98 : (skill <= P_LAST_WEAPON) ? "
\95\90\8aí
\82Ì"
99 : (skill <= P_LAST_SPELL) ? "
\96\82\96@
\82Ì"
104 /* weapon's skill category name for use as generalized description of weapon;
105 mostly used to shorten "you drop your <weapon>" messages when slippery
106 fingers or polymorph causes hero to involuntarily drop wielded weapon(s) */
111 int skill = weapon_type(obj);
112 const char *descr = P_NAME(skill);
114 /* assorted special cases */
117 /* not a weapon or weptool: use item class name;
118 override class name "food" for corpses, tins, and eggs,
119 "large rock" for statues and boulders, and "tool" for towels */
120 descr = (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG
121 || obj->otyp == STATUE || obj->otyp == BOULDER
122 || obj->otyp == TOWEL)
123 ? OBJ_NAME(objects[obj->otyp])
124 : def_oc_syms[(int) obj->oclass].name;
128 descr = (obj->otyp == ROCK || is_graystone(obj))
133 /* avoid "rock"; what about known glass? */
134 : (obj->oclass == GEM_CLASS)
139 /* in case somebody adds odd sling ammo */
140 : def_oc_syms[(int) obj->oclass].name;
154 descr = "
\83{
\83\8b\83g";
157 if (obj->otyp == GRAPPLING_HOOK)
161 descr = "
\83t
\83b
\83N";
164 /* even if "dwarvish mattock" hasn't been discovered yet */
165 if (obj->otyp == DWARVISH_MATTOCK)
169 descr = "
\82Â
\82é
\82Í
\82µ";
174 return makesingular(descr);
178 * hitval returns an integer representing the "to hit" bonuses
179 * of "otmp" against the monster.
187 struct permonst *ptr = mon->data;
188 boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
193 /* Put weapon specific "to hit" bonuses in below: */
194 tmp += objects[otmp->otyp].oc_hitbon;
196 /* Put weapon vs. monster type "to hit" bonuses in below: */
198 /* Blessed weapons used against undead or demons */
199 if (Is_weapon && otmp->blessed
200 && (is_demon(ptr) || is_undead(ptr) || is_vampshifter(mon)))
203 if (is_spear(otmp) && index(kebabable, ptr->mlet))
206 /* trident is highly effective against swimmers */
207 if (otmp->otyp == TRIDENT && is_swimmer(ptr)) {
208 if (is_pool(mon->mx, mon->my))
210 else if (ptr->mlet == S_EEL || ptr->mlet == S_SNAKE)
214 /* Picks used against xorns and earth elementals */
215 if (is_pick(otmp) && (passes_walls(ptr) && thick_skinned(ptr)))
218 /* Check specially named weapon "to hit" bonuses */
220 tmp += spec_abon(otmp, mon);
225 /* Historical note: The original versions of Hack used a range of damage
226 * which was similar to, but not identical to the damage used in Advanced
227 * Dungeons and Dragons. I figured that since it was so close, I may as well
228 * make it exactly the same as AD&D, adding some more weapons in the process.
229 * This has the advantage that it is at least possible that the player would
230 * already know the damage of at least some of the weapons. This was circa
231 * 1987 and I used the table from Unearthed Arcana until I got tired of typing
232 * them in (leading to something of an imbalance towards weapons early in
233 * alphabetical order). The data structure still doesn't include fields that
234 * fully allow the appropriate damage to be described (there's no way to say
235 * 3d6 or 1d6+1) so we add on the extra damage in dmgval() if the weapon
236 * doesn't do an exact die of damage.
238 * Of course new weapons were added later in the development of Nethack. No
239 * AD&D consistency was kept, but most of these don't exist in AD&D anyway.
241 * Second edition AD&D came out a few years later; luckily it used the same
242 * table. As of this writing (1999), third edition is in progress but not
243 * released. Let's see if the weapon table stays the same. --KAA
244 * October 2000: It didn't. Oh, well.
248 * dmgval returns an integer representing the damage bonuses
249 * of "otmp" against the monster.
256 int tmp = 0, otyp = otmp->otyp;
257 struct permonst *ptr = mon->data;
258 boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
260 if (otyp == CREAM_PIE)
264 if (objects[otyp].oc_wldam)
265 tmp = rnd(objects[otyp].oc_wldam);
272 case ELVEN_BROADSWORD:
296 case DWARVISH_MATTOCK:
297 case TWO_HANDED_SWORD:
302 if (objects[otyp].oc_wsdam)
303 tmp = rnd(objects[otyp].oc_wsdam);
323 case ELVEN_BROADSWORD:
336 /* negative enchantment mustn't produce negative damage */
341 if (objects[otyp].oc_material <= LEATHER && thick_skinned(ptr))
342 /* thick skinned/scaled creatures don't feel it */
344 if (ptr == &mons[PM_SHADE] && !shade_glare(otmp))
347 /* "very heavy iron ball"; weight increase is in increments */
348 if (otyp == HEAVY_IRON_BALL && tmp > 0) {
349 int wt = (int) objects[HEAVY_IRON_BALL].oc_weight;
351 if ((int) otmp->owt > wt) {
352 wt = ((int) otmp->owt - wt) / IRON_BALL_W_INCR;
355 tmp = 25; /* objects[].oc_wldam */
359 /* Put weapon vs. monster type damage bonuses in below: */
360 if (Is_weapon || otmp->oclass == GEM_CLASS || otmp->oclass == BALL_CLASS
361 || otmp->oclass == CHAIN_CLASS) {
365 && (is_undead(ptr) || is_demon(ptr) || is_vampshifter(mon)))
367 if (is_axe(otmp) && is_wooden(ptr))
369 if (objects[otyp].oc_material == SILVER && mon_hates_silver(mon))
371 if (artifact_light(otmp) && otmp->lamplit && hates_light(ptr))
374 /* if the weapon is going to get a double damage bonus, adjust
375 this bonus so that effectively it's added after the doubling */
376 if (bonus > 1 && otmp->oartifact && spec_dbon(otmp, mon, 25) >= 25)
377 bonus = (bonus + 1) / 2;
383 /* It's debatable whether a rusted blunt instrument
384 should do less damage than a pristine one, since
385 it will hit with essentially the same impact, but
386 there ought to some penalty for using damaged gear
387 so always subtract erosion even for blunt weapons. */
388 tmp -= greatest_erosion(otmp);
396 /* check whether blessed and/or silver damage applies for *non-weapon* hit;
397 return value is the amount of the extra damage */
399 special_dmgval(magr, mdef, armask, silverhit_p)
400 struct monst *magr, *mdef;
401 long armask; /* armor mask, multiple bits accepted for W_ARMC|W_ARM|W_ARMU
402 * or W_ARMG|W_RINGL|W_RINGR only */
403 long *silverhit_p; /* output flag mask for silver bonus */
406 struct permonst *ptr = mdef->data;
407 boolean left_ring = (armask & W_RINGL) ? TRUE : FALSE,
408 right_ring = (armask & W_RINGR) ? TRUE : FALSE;
413 if (armask & (W_ARMC | W_ARM | W_ARMU)) {
414 if ((armask & W_ARMC) != 0L
415 && (obj = which_armor(magr, W_ARMC)) != 0)
417 else if ((armask & W_ARM) != 0L
418 && (obj = which_armor(magr, W_ARM)) != 0)
420 else if ((armask & W_ARMU) != 0L
421 && (obj = which_armor(magr, W_ARMU)) != 0)
425 } else if (armask & (W_ARMG | W_RINGL | W_RINGR)) {
426 armask = ((obj = which_armor(magr, W_ARMG)) != 0) ? W_ARMG : 0L;
428 obj = which_armor(magr, armask);
433 && (is_undead(ptr) || is_demon(ptr) || is_vampshifter(mdef)))
435 /* the only silver armor is shield of reflection (silver dragon
436 scales refer to color, not material) and the only way to hit
437 with one--aside from throwing--is to wield it and perform a
438 weapon hit, but we include a general check here */
439 if (objects[obj->otyp].oc_material == SILVER
440 && mon_hates_silver(mdef)) {
445 /* when no gloves we check for silver rings (blessed rings ignored) */
446 } else if ((left_ring || right_ring) && magr == &youmonst) {
447 if (left_ring && uleft) {
448 if (objects[uleft->otyp].oc_material == SILVER
449 && mon_hates_silver(mdef)) {
451 silverhit |= W_RINGL;
454 if (right_ring && uright) {
455 if (objects[uright->otyp].oc_material == SILVER
456 && mon_hates_silver(mdef)) {
457 /* two silver rings don't give double silver damage
458 but 'silverhit' messages might be adjusted for them */
459 if (!(silverhit & W_RINGL))
461 silverhit |= W_RINGR;
467 *silverhit_p = silverhit;
471 /* give a "silver <item> sears <target>" message;
472 not used for weapon hit, so we only handle rings */
474 silver_sears(magr, mdef, silverhit)
475 struct monst *magr UNUSED;
479 char rings[20]; /* plenty of room for "rings" */
480 int ltyp = ((uleft && (silverhit & W_RINGL) != 0L)
481 ? uleft->otyp : STRANGE_OBJECT),
482 rtyp = ((uright && (silverhit & W_RINGR) != 0L)
483 ? uright->otyp : STRANGE_OBJECT);
485 l_ag = (objects[ltyp].oc_material == SILVER && uleft->dknown),
486 r_ag = (objects[rtyp].oc_material == SILVER && uright->dknown);
488 if ((silverhit & (W_RINGL | W_RINGR)) != 0L) {
489 /* plural if both the same type (so not multi_claw and both rings
490 are non-Null) and either both known or neither known, or both
491 silver (in case there is ever more than one type of silver ring)
492 and both known; singular if multi_claw (where one of ltyp or
493 rtyp will always be STRANGE_OBJECT) even if both rings are known
494 silver [see hmonas(uhitm.c) for explanation of 'multi_claw'] */
495 both = ((ltyp == rtyp && uleft->dknown == uright->dknown)
497 Sprintf(rings, "ring%s", both ? "s" : "");
499 (l_ag || r_ag) ? "silver "
501 : ((silverhit & W_RINGL) != 0L) ? "left "
503 rings, vtense(rings, "sear"), mon_nam(mdef));
507 STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int));
509 if ((otmp = oselect(mtmp, x)) != 0) \
512 STATIC_OVL struct obj *
519 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
521 /* never select non-cockatrice corpses */
522 && !((x == CORPSE || x == EGG)
523 && !touch_petrifies(&mons[otmp->corpsenm]))
524 && (!otmp->oartifact || touch_artifact(otmp, mtmp)))
527 return (struct obj *) 0;
530 /* TODO: have monsters use aklys' throw-and-return */
531 static NEARDATA const int rwep[] = {
532 DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
533 SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
534 CROSSBOW_BOLT, SILVER_DAGGER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE,
535 FLINT, ROCK, LOADSTONE, LUCKSTONE, DART,
536 /* BOOMERANG, */ CREAM_PIE
539 static NEARDATA const int pwep[] = { HALBERD, BARDICHE, SPETUM,
540 BILL_GUISARME, VOULGE, RANSEUR,
541 GUISARME, GLAIVE, LUCERN_HAMMER,
542 BEC_DE_CORBIN, FAUCHARD, PARTISAN,
545 static struct obj *propellor;
547 /* select a ranged weapon for the monster */
550 register struct monst *mtmp;
552 register struct obj *otmp;
557 char mlet = mtmp->data->mlet;
559 propellor = (struct obj *) &zeroobj;
560 Oselect(EGG); /* cockatrice egg */
561 if (mlet == S_KOP) /* pies are first choice for Kops */
563 if (throws_rocks(mtmp->data)) /* ...boulders for giants */
566 /* Select polearms first; they do more damage and aren't expendable.
567 But don't pick one if monster's weapon is welded, because then
568 we'd never have a chance to throw non-wielding missiles. */
569 /* The limit of 13 here is based on the monster polearm range limit
570 * (defined as 5 in mthrowu.c). 5 corresponds to a distance of 2 in
571 * one direction and 1 in another; one space beyond that would be 3 in
572 * one direction and 2 in another; 3^2+2^2=13.
574 mwep = MON_WEP(mtmp);
575 /* NO_WEAPON_WANTED means we already tried to wield and failed */
576 mweponly = (mwelded(mwep) && mtmp->weapon_check == NO_WEAPON_WANTED);
577 if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 13
578 && couldsee(mtmp->mx, mtmp->my)) {
579 for (i = 0; i < SIZE(pwep); i++) {
580 /* Only strong monsters can wield big (esp. long) weapons.
581 * Big weapon is basically the same as bimanual.
582 * All monsters can wield the remaining weapons.
584 if (((strongmonst(mtmp->data)
585 && (mtmp->misc_worn_check & W_ARMS) == 0)
586 || !objects[pwep[i]].oc_bimanual)
587 && (objects[pwep[i]].oc_material != SILVER
588 || !mon_hates_silver(mtmp))) {
589 if ((otmp = oselect(mtmp, pwep[i])) != 0
590 && (otmp == mwep || !mweponly)) {
591 propellor = otmp; /* force the monster to wield it */
599 * other than these two specific cases, always select the
600 * most potent ranged weapon to hand.
602 for (i = 0; i < SIZE(rwep); i++) {
605 /* shooting gems from slings; this goes just before the darts */
606 /* (shooting rocks is already handled via the rwep[] ordering) */
607 if (rwep[i] == DART && !likes_gems(mtmp->data)
608 && m_carrying(mtmp, SLING)) { /* propellor */
609 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
610 if (otmp->oclass == GEM_CLASS
611 && (otmp->otyp != LOADSTONE || !otmp->cursed)) {
612 propellor = m_carrying(mtmp, SLING);
617 /* KMH -- This belongs here so darts will work */
618 propellor = (struct obj *) &zeroobj;
620 prop = objects[rwep[i]].oc_skill;
624 propellor = oselect(mtmp, YUMI);
626 propellor = oselect(mtmp, ELVEN_BOW);
628 propellor = oselect(mtmp, BOW);
630 propellor = oselect(mtmp, ORCISH_BOW);
633 propellor = oselect(mtmp, SLING);
636 propellor = oselect(mtmp, CROSSBOW);
638 if ((otmp = MON_WEP(mtmp)) && mwelded(otmp) && otmp != propellor
639 && mtmp->weapon_check == NO_WEAPON_WANTED)
642 /* propellor = obj, propellor to use
643 * propellor = &zeroobj, doesn't need a propellor
644 * propellor = 0, needed one and didn't have one
646 if (propellor != 0) {
647 /* Note: cannot use m_carrying for loadstones, since it will
648 * always select the first object of a type, and maybe the
649 * monster is carrying two but only the first is unthrowable.
651 if (rwep[i] != LOADSTONE) {
652 /* Don't throw a cursed weapon-in-hand or an artifact */
653 if ((otmp = oselect(mtmp, rwep[i])) && !otmp->oartifact
654 && !(otmp == MON_WEP(mtmp) && mwelded(otmp)))
657 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
658 if (otmp->otyp == LOADSTONE && !otmp->cursed)
665 return (struct obj *) 0;
668 /* is 'obj' a type of weapon that any monster knows how to throw? */
670 monmightthrowwep(obj)
675 for (idx = 0; idx < SIZE(rwep); ++idx)
676 if (obj->otyp == rwep[idx])
681 /* Weapons in order of preference */
682 static const NEARDATA short hwep[] = {
683 CORPSE, /* cockatrice corpse */
684 TSURUGI, RUNESWORD, DWARVISH_MATTOCK, TWO_HANDED_SWORD, BATTLE_AXE,
685 KATANA, UNICORN_HORN, CRYSKNIFE, TRIDENT, LONG_SWORD, ELVEN_BROADSWORD,
686 BROADSWORD, SCIMITAR, SILVER_SABER, MORNING_STAR, ELVEN_SHORT_SWORD,
687 DWARVISH_SHORT_SWORD, SHORT_SWORD, ORCISH_SHORT_SWORD, MACE, AXE,
688 DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, FLAIL,
689 BULLWHIP, QUARTERSTAFF, JAVELIN, AKLYS, CLUB, PICK_AXE, RUBBER_HOSE,
690 WAR_HAMMER, SILVER_DAGGER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, ATHAME,
691 SCALPEL, KNIFE, WORM_TOOTH
694 /* select a hand to hand weapon for the monster */
697 register struct monst *mtmp;
699 register struct obj *otmp;
701 boolean strong = strongmonst(mtmp->data);
702 boolean wearing_shield = (mtmp->misc_worn_check & W_ARMS) != 0;
704 /* prefer artifacts to everything else */
705 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
706 if (otmp->oclass == WEAPON_CLASS && otmp->oartifact
707 && touch_artifact(otmp, mtmp)
708 && ((strong && !wearing_shield)
709 || !objects[otmp->otyp].oc_bimanual))
713 if (is_giant(mtmp->data)) /* giants just love to use clubs */
716 /* only strong monsters can wield big (esp. long) weapons */
717 /* big weapon is basically the same as bimanual */
718 /* all monsters can wield the remaining weapons */
719 for (i = 0; i < SIZE(hwep); i++) {
720 if (hwep[i] == CORPSE && !(mtmp->misc_worn_check & W_ARMG)
721 && !resists_ston(mtmp))
723 if (((strong && !wearing_shield) || !objects[hwep[i]].oc_bimanual)
724 && (objects[hwep[i]].oc_material != SILVER
725 || !mon_hates_silver(mtmp)))
730 return (struct obj *) 0;
733 /* Called after polymorphing a monster, robbing it, etc.... Monsters
734 * otherwise never unwield stuff on their own. Might print message.
737 possibly_unwield(mon, polyspot)
741 struct obj *obj, *mw_tmp;
743 if (!(mw_tmp = MON_WEP(mon)))
745 for (obj = mon->minvent; obj; obj = obj->nobj)
748 if (!obj) { /* The weapon was stolen or destroyed */
750 mon->weapon_check = NEED_WEAPON;
753 if (!attacktype(mon->data, AT_WEAP)) {
754 setmnotwielded(mon, mw_tmp);
755 mon->weapon_check = NO_WEAPON_WANTED;
756 obj_extract_self(obj);
757 if (cansee(mon->mx, mon->my)) {
759 pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
761 pline("%s
\82Í%s
\82ð
\92u
\82¢
\82½
\81D", Monnam(mon), distant_name(obj, doname));
762 newsym(mon->mx, mon->my);
764 /* might be dropping object into water or lava */
766 if (!flooreffects(obj, mon->mx, mon->my, "drop")) {
768 if (!flooreffects(obj, mon->mx, mon->my, "
\97\8e\82¿
\82é")) {
771 place_object(obj, mon->mx, mon->my);
776 /* The remaining case where there is a change is where a monster
777 * is polymorphed into a stronger/weaker monster with a different
778 * choice of weapons. This has no parallel for players. It can
779 * be handled by waiting until mon_wield_item is actually called.
780 * Though the monster still wields the wrong weapon until then,
781 * this is OK since the player can't see it. (FIXME: Not okay since
782 * probing can reveal it.)
783 * Note that if there is no change, setting the check to NEED_WEAPON
785 * Possible problem: big monster with big cursed weapon gets
786 * polymorphed into little monster. But it's not quite clear how to
787 * handle this anyway....
789 if (!(mwelded(mw_tmp) && mon->weapon_check == NO_WEAPON_WANTED))
790 mon->weapon_check = NEED_WEAPON;
794 /* Let a monster try to wield a weapon, based on mon->weapon_check.
795 * Returns 1 if the monster took time to do it, 0 if it did not.
799 register struct monst *mon;
803 /* This case actually should never happen */
804 if (mon->weapon_check == NO_WEAPON_WANTED)
806 switch (mon->weapon_check) {
807 case NEED_HTH_WEAPON:
808 obj = select_hwep(mon);
810 case NEED_RANGED_WEAPON:
811 (void) select_rwep(mon);
815 obj = m_carrying(mon, PICK_AXE);
816 /* KMH -- allow other picks */
817 if (!obj && !which_armor(mon, W_ARMS))
818 obj = m_carrying(mon, DWARVISH_MATTOCK);
821 /* currently, only 2 types of axe */
822 obj = m_carrying(mon, BATTLE_AXE);
823 if (!obj || which_armor(mon, W_ARMS))
824 obj = m_carrying(mon, AXE);
826 case NEED_PICK_OR_AXE:
827 /* prefer pick for fewer switches on most levels */
828 obj = m_carrying(mon, DWARVISH_MATTOCK);
830 obj = m_carrying(mon, BATTLE_AXE);
831 if (!obj || which_armor(mon, W_ARMS)) {
832 obj = m_carrying(mon, PICK_AXE);
834 obj = m_carrying(mon, AXE);
838 impossible("weapon_check %d for %s?", mon->weapon_check,
842 if (obj && obj != &zeroobj) {
843 struct obj *mw_tmp = MON_WEP(mon);
845 if (mw_tmp && mw_tmp->otyp == obj->otyp) {
846 /* already wielding it */
847 mon->weapon_check = NEED_WEAPON;
850 /* Actually, this isn't necessary--as soon as the monster
851 * wields the weapon, the weapon welds itself, so the monster
852 * can know it's cursed and needn't even bother trying.
855 if (mw_tmp && mwelded(mw_tmp)) {
856 if (canseemon(mon)) {
858 char welded_buf[BUFSZ];
860 const char *mon_hand = mbodypart(mon, HAND);
862 if (bimanual(mw_tmp))
863 mon_hand = makeplural(mon_hand);
865 Sprintf(welded_buf, "%s welded to %s %s",
866 otense(mw_tmp, "are"), mhis(mon), mon_hand);
869 if (obj->otyp == PICK_AXE) {
871 pline("Since %s weapon%s %s,", s_suffix(mon_nam(mon)),
872 plur(mw_tmp->quan), welded_buf);
874 pline("%s
\82Í
\95\90\8aí
\82ð
\8eè
\82É
\82µ
\82æ
\82¤
\82Æ
\82µ
\82½
\82ª
\81C", mon_nam(mon));
877 pline("%s cannot wield that %s.", mon_nam(mon),
880 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82Å
\82«
\82È
\82©
\82Á
\82½
\81D", mon_nam(mon),
885 pline("%s tries to wield %s.", Monnam(mon), doname(obj));
887 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82µ
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", Monnam(mon), doname(obj));
889 pline("%s %s!", Yname2(mw_tmp), welded_buf);
891 pline("%s
\82Í%s
\82ð
\8eè
\82É
\82µ
\82½
\81I", Monnam(mon), xname(mw_tmp));
895 mon->weapon_check = NO_WEAPON_WANTED;
898 mon->mw = obj; /* wield obj */
899 setmnotwielded(mon, mw_tmp);
900 mon->weapon_check = NEED_WEAPON;
901 if (canseemon(mon)) {
903 pline("%s wields %s!", Monnam(mon), doname(obj));
905 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82µ
\82½
\81I", Monnam(mon), doname(obj));
906 if (mwelded(mw_tmp)) {
908 pline("%s %s to %s %s!", Tobjnam(obj, "weld"),
909 is_plural(obj) ? "themselves" : "itself",
910 s_suffix(mon_nam(mon)), mbodypart(mon, HAND));
912 pline("%s
\82Í
\8f\9f\8eè
\82É%s
\82Ì%s
\82É
\91\95\94õ
\82³
\82ê
\82½
\81I",
914 mon_nam(mon), mbodypart(mon, HAND));
919 if (artifact_light(obj) && !obj->lamplit) {
920 begin_burn(obj, FALSE);
923 pline("%s %s in %s %s!", Tobjnam(obj, "shine"),
924 arti_light_description(obj), s_suffix(mon_nam(mon)),
925 mbodypart(mon, HAND));
927 pline("%s
\82Í%s
\82Ì%s
\82Ì
\92\86\82Å%s
\8bP
\82¢
\82½
\81I",
928 xname(obj), mon_nam(mon),
929 mbodypart(mon, HAND), arti_light_description(obj));
932 obj->owornmask = W_WEP;
935 mon->weapon_check = NEED_WEAPON;
939 /* force monster to stop wielding current weapon, if any */
944 struct obj *mwep = MON_WEP(mon);
947 setmnotwielded(mon, mwep);
948 mon->weapon_check = NEED_WEAPON;
952 /* attack bonus for strength & dexterity */
957 int str = ACURR(A_STR), dex = ACURR(A_DEX);
960 return (adj_lev(&mons[u.umonnum]) - 3);
967 else if (str <= STR18(50))
968 sbon = 1; /* up to 18/50 */
969 else if (str < STR18(100))
974 /* Game tuning kludge: make it a bit easier for a low level character to
976 sbon += (u.ulevel < 3) ? 1 : 0;
987 return (sbon + dex - 14);
990 /* damage bonus for strength */
994 int str = ACURR(A_STR);
1006 return 2; /* up to 18 */
1007 else if (str <= STR18(75))
1008 return 3; /* up to 18/75 */
1009 else if (str <= STR18(90))
1010 return 4; /* up to 18/90 */
1011 else if (str < STR18(100))
1012 return 5; /* up to 18/99 */
1017 /* increase a towel's wetness */
1019 wet_a_towel(obj, amt, verbose)
1021 int amt; /* positive: new value; negative: increment by -amt; zero: no-op */
1024 int newspe = (amt <= 0) ? obj->spe - amt : amt;
1026 /* new state is only reported if it's an increase */
1027 if (newspe > obj->spe) {
1030 const char *wetness = (newspe < 3)
1031 ? (!obj->spe ? "damp" : "damper")
1032 : (!obj->spe ? "wet" : "wetter");
1034 const char *wetness = (newspe < 3)
1035 ? (!obj->spe ? "
\8e¼
\82Á
\82½" : "
\82³
\82ç
\82É
\8e¼
\82Á
\82½")
1036 : (!obj->spe ? "
\94G
\82ê
\82½" : "
\82³
\82ç
\82É
\94G
\82ê
\82½");
1041 pline("%s gets %s.", Yobjnam2(obj, (const char *) 0),
1044 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
1047 else if (mcarried(obj) && canseemon(obj->ocarry))
1049 pline("%s %s gets %s.", s_suffix(Monnam(obj->ocarry)),
1050 xname(obj), wetness);
1052 pline("%s
\82Ì%s
\82Í%s
\81D", Monnam(obj->ocarry),
1053 xname(obj), wetness);
1057 obj->spe = min(newspe, 7);
1059 /* if hero is wielding this towel, don't give "you begin bashing
1060 with your wet towel" message on next attack with it */
1062 unweapon = !is_wet_towel(obj);
1065 /* decrease a towel's wetness */
1067 dry_a_towel(obj, amt, verbose)
1069 int amt; /* positive: new value; negative: decrement by -amt; zero: no-op */
1072 int newspe = (amt <= 0) ? obj->spe + amt : amt;
1074 /* new state is only reported if it's a decrease */
1075 if (newspe < obj->spe) {
1079 pline("%s dries%s.", Yobjnam2(obj, (const char *) 0),
1080 !newspe ? " out" : "");
1082 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
1083 !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
1085 else if (mcarried(obj) && canseemon(obj->ocarry))
1087 pline("%s %s drie%s.", s_suffix(Monnam(obj->ocarry)),
1088 xname(obj), !newspe ? " out" : "");
1090 pline("%s
\82Ì%s
\82Í%s
\81D", Monnam(obj->ocarry),
1091 xname(obj), !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
1095 newspe = min(newspe, 7);
1096 obj->spe = max(newspe, 0);
1098 /* if hero is wielding this towel and it is now dry, give "you begin
1099 bashing with your towel" message on next attack with it */
1101 unweapon = !is_wet_towel(obj);
1104 /* copy the skill level name into the given buffer */
1106 skill_level_name(skill, buf)
1112 switch (P_SKILL(skill)) {
1117 ptr = "
\8f\89\90S
\8eÒ";
1123 ptr = "
\93ü
\96å
\8eÒ";
1129 ptr = "
\8fn
\97û
\8eÒ";
1135 ptr = "
\83G
\83L
\83X
\83p
\81[
\83g";
1137 /* these are for unarmed combat/martial arts only */
1142 ptr = "
\83}
\83X
\83^
\81[";
1144 case P_GRAND_MASTER:
1146 ptr = "Grand Master";
1148 ptr = "
\83O
\83\89\83\93\83h
\83}
\83X
\83^
\81[";
1165 return P_NAME(skill);
1168 /* return the # of slots required to advance the skill */
1170 slots_required(skill)
1173 int tmp = P_SKILL(skill);
1175 /* The more difficult the training, the more slots it takes.
1176 * unskilled -> basic 1
1177 * basic -> skilled 2
1178 * skilled -> expert 3
1180 if (skill <= P_LAST_WEAPON || skill == P_TWO_WEAPON_COMBAT)
1183 /* Fewer slots used up for unarmed or martial.
1184 * unskilled -> basic 1
1185 * basic -> skilled 1
1186 * skilled -> expert 2
1187 * expert -> master 2
1188 * master -> grand master 3
1190 return (tmp + 1) / 2;
1193 /* return true if this skill can be advanced */
1195 can_advance(skill, speedy)
1199 if (P_RESTRICTED(skill)
1200 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1201 || u.skills_advanced >= P_SKILL_LIMIT)
1204 if (wizard && speedy)
1207 return (boolean) ((int) P_ADVANCE(skill)
1208 >= practice_needed_to_advance(P_SKILL(skill))
1209 && u.weapon_slots >= slots_required(skill));
1212 /* return true if this skill could be advanced if more slots were available */
1214 could_advance(skill)
1217 if (P_RESTRICTED(skill)
1218 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1219 || u.skills_advanced >= P_SKILL_LIMIT)
1222 return (boolean) ((int) P_ADVANCE(skill)
1223 >= practice_needed_to_advance(P_SKILL(skill)));
1226 /* return true if this skill has reached its maximum and there's been enough
1227 practice to become eligible for the next step if that had been possible */
1232 if (P_RESTRICTED(skill))
1235 return (boolean) (P_SKILL(skill) >= P_MAX_SKILL(skill)
1236 && ((int) P_ADVANCE(skill)
1237 >= practice_needed_to_advance(P_SKILL(skill))));
1241 skill_advance(skill)
1244 u.weapon_slots -= slots_required(skill);
1246 u.skill_record[u.skills_advanced++] = skill;
1247 /* subtly change the advance message to indicate no more advancement */
1249 You("are now %s skilled in %s.",
1250 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more",
1253 Your("%s
\82Ì
\83X
\83L
\83\8b\82ð%s
\8d\82\82ß
\82½
\81D",
1255 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "
\8dÅ
\8d\82\82É" : "
\82³
\82ç
\82É");
1259 static const struct skill_range {
1262 } skill_ranges[] = {
1264 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "Fighting Skills" },
1266 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "
\90í
\82¢
\82Ì
\83X
\83L
\83\8b" },
1268 { P_FIRST_WEAPON, P_LAST_WEAPON, "Weapon Skills" },
1270 { P_FIRST_WEAPON, P_LAST_WEAPON, "
\95\90\8aí
\82Ì
\83X
\83L
\83\8b" },
1272 { P_FIRST_SPELL, P_LAST_SPELL, "Spellcasting Skills" },
1274 { P_FIRST_SPELL, P_LAST_SPELL, "
\96\82\96@
\82Ì
\83X
\83L
\83\8b" },
1278 * The `#enhance' extended command. What we _really_ would like is
1279 * to keep being able to pick things to advance until we couldn't any
1280 * more. This is currently not possible -- the menu code has no way
1281 * to call us back for instant action. Even if it did, we would also need
1282 * to be able to update the menu since selecting one item could make
1283 * others unselectable.
1286 enhance_weapon_skill()
1288 int pass, i, n, len, longest, to_advance, eventually_advance, maxxed_cnt;
1289 char buf[BUFSZ], sklnambuf[BUFSZ];
1291 menu_item *selected;
1294 boolean speedy = FALSE;
1296 if (wizard && yn("Advance skills without practice?") == 'y')
1300 /* find longest available skill name, count those that can advance */
1301 to_advance = eventually_advance = maxxed_cnt = 0;
1302 for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) {
1303 if (P_RESTRICTED(i))
1305 if ((len = strlen(P_NAME(i))) > longest)
1307 if (can_advance(i, speedy))
1309 else if (could_advance(i))
1310 eventually_advance++;
1311 else if (peaked_skill(i))
1315 win = create_nhwindow(NHW_MENU);
1318 /* start with a legend if any entries will be annotated
1319 with "*" or "#" below */
1320 if (eventually_advance > 0 || maxxed_cnt > 0) {
1322 if (eventually_advance > 0) {
1324 Sprintf(buf, "(Skill%s flagged by \"*\" may be enhanced %s.)",
1325 plur(eventually_advance),
1326 (u.ulevel < MAXULEV)
1327 ? "when you're more experienced"
1328 : "if skill slots become available");
1330 Sprintf(buf, "(\"*\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í%s
\8d\82\82ß
\82ç
\82ê
\82é
\81D)",
1331 (u.ulevel < MAXULEV)
1332 ? "
\82à
\82Á
\82Æ
\8co
\8c±
\82ð
\82Â
\82ß
\82Î"
1333 : "
\83X
\83L
\83\8b\83X
\83\8d\83b
\83g
\82ª
\8eg
\82¦
\82é
\82æ
\82¤
\82É
\82È
\82ê
\82Î");
1335 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1338 if (maxxed_cnt > 0) {
1341 "(Skill%s flagged by \"#\" cannot be enhanced any further.)",
1345 "(\"#\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í
\82±
\82ê
\88È
\8fã
\8d\82\82ß
\82ç
\82ê
\82È
\82¢
\81D)");
1347 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1350 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
1354 /* List the skills, making ones that could be advanced
1355 selectable. List the miscellaneous skills first.
1356 Possible future enhancement: list spell skills before
1357 weapon skills for spellcaster roles. */
1358 for (pass = 0; pass < SIZE(skill_ranges); pass++)
1359 for (i = skill_ranges[pass].first; i <= skill_ranges[pass].last;
1361 /* Print headings for skill types */
1363 if (i == skill_ranges[pass].first)
1364 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
1365 skill_ranges[pass].name, MENU_UNSELECTED);
1367 if (P_RESTRICTED(i))
1370 * Sigh, this assumes a monospaced font unless
1371 * iflags.menu_tab_sep is set in which case it puts
1372 * tabs between columns.
1373 * The 12 is the longest skill level name.
1374 * The " " is room for a selection letter and dash, "a - ".
1376 if (can_advance(i, speedy))
1377 prefix = ""; /* will be preceded by menu choice */
1378 else if (could_advance(i))
1380 else if (peaked_skill(i))
1384 (to_advance + eventually_advance + maxxed_cnt > 0)
1387 (void) skill_level_name(i, sklnambuf);
1389 if (!iflags.menu_tab_sep)
1390 Sprintf(buf, " %s%-*s %-12s %5d(%4d)", prefix,
1391 longest, P_NAME(i), sklnambuf, P_ADVANCE(i),
1392 practice_needed_to_advance(P_SKILL(i)));
1394 Sprintf(buf, " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i),
1395 sklnambuf, P_ADVANCE(i),
1396 practice_needed_to_advance(P_SKILL(i)));
1398 if (!iflags.menu_tab_sep)
1399 Sprintf(buf, " %s %-*s [%s]", prefix, longest,
1400 P_NAME(i), sklnambuf);
1402 Sprintf(buf, " %s%s\t[%s]", prefix, P_NAME(i),
1405 any.a_int = can_advance(i, speedy) ? i + 1 : 0;
1406 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1411 Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:"
1412 : "Current skills:");
1414 Strcpy(buf, (to_advance > 0) ? "
\83X
\83L
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F"
1415 : "
\8c»
\8dÝ
\82Ì
\83X
\83L
\83\8b\81F");
1417 if (wizard && !speedy)
1418 Sprintf(eos(buf), " (%d slot%s available)", u.weapon_slots,
1419 plur(u.weapon_slots));
1421 n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
1422 destroy_nhwindow(win);
1424 n = selected[0].item.a_int - 1; /* get item selected */
1425 free((genericptr_t) selected);
1427 /* check for more skills able to advance, if so then .. */
1428 for (n = i = 0; i < P_NUM_SKILLS; i++) {
1429 if (can_advance(i, speedy)) {
1432 You_feel("you could be more dangerous!");
1434 You("
\82³
\82ç
\82É
\83X
\83L
\83\8b\82ð
\8d\82\82ß
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82»
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I");
1440 } while (speedy && n > 0);
1445 * Change from restricted to unrestricted, allowing P_BASIC as max. This
1446 * function may be called with with P_NONE. Used in pray.c as well as below.
1449 unrestrict_weapon_skill(skill)
1452 if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
1453 P_SKILL(skill) = P_UNSKILLED;
1454 P_MAX_SKILL(skill) = P_BASIC;
1455 P_ADVANCE(skill) = 0;
1460 use_skill(skill, degree)
1464 boolean advance_before;
1466 if (skill != P_NONE && !P_RESTRICTED(skill)) {
1467 advance_before = can_advance(skill, FALSE);
1468 P_ADVANCE(skill) += degree;
1469 if (!advance_before && can_advance(skill, FALSE))
1470 give_may_advance_msg(skill);
1476 int n; /* number of slots to gain; normally one */
1478 int i, before, after;
1480 for (i = 0, before = 0; i < P_NUM_SKILLS; i++)
1481 if (can_advance(i, FALSE))
1483 u.weapon_slots += n;
1484 for (i = 0, after = 0; i < P_NUM_SKILLS; i++)
1485 if (can_advance(i, FALSE))
1488 give_may_advance_msg(P_NONE);
1492 lose_weapon_skill(n)
1493 int n; /* number of slots to lose; normally one */
1498 /* deduct first from unused slots then from last placed one, if any */
1499 if (u.weapon_slots) {
1501 } else if (u.skills_advanced) {
1502 skill = u.skill_record[--u.skills_advanced];
1503 if (P_SKILL(skill) <= P_UNSKILLED)
1504 panic("lose_weapon_skill (%d)", skill);
1505 P_SKILL(skill)--; /* drop skill one level */
1506 /* Lost skill might have taken more than one slot; refund rest. */
1507 u.weapon_slots = slots_required(skill) - 1;
1508 /* It might now be possible to advance some other pending
1509 skill by using the refunded slots, but giving a message
1510 to that effect would seem pretty confusing.... */
1519 /* KMH -- now uses the object table */
1523 return P_BARE_HANDED_COMBAT; /* Not using a weapon */
1524 if (obj->oclass != WEAPON_CLASS && obj->oclass != TOOL_CLASS
1525 && obj->oclass != GEM_CLASS)
1526 return P_NONE; /* Not a weapon, weapon-tool, or ammo */
1527 type = objects[obj->otyp].oc_skill;
1528 return (type < 0) ? -type : type;
1535 return P_TWO_WEAPON_COMBAT;
1536 return weapon_type(uwep);
1540 * Return hit bonus/penalty based on skill of weapon.
1541 * Treat restricted weapons as unskilled.
1544 weapon_hit_bonus(weapon)
1547 int type, wep_type, skill, bonus = 0;
1548 static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
1550 wep_type = weapon_type(weapon);
1551 /* use two weapon skill only if attacking with one of the wielded weapons
1553 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1554 ? P_TWO_WEAPON_COMBAT
1556 if (type == P_NONE) {
1558 } else if (type <= P_LAST_WEAPON) {
1559 switch (P_SKILL(type)) {
1561 impossible(bad_skill, P_SKILL(type)); /* fall through */
1562 case P_ISRESTRICTED:
1576 } else if (type == P_TWO_WEAPON_COMBAT) {
1577 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1578 if (P_SKILL(wep_type) < skill)
1579 skill = P_SKILL(wep_type);
1582 impossible(bad_skill, skill); /* fall through */
1583 case P_ISRESTRICTED:
1597 } else if (type == P_BARE_HANDED_COMBAT) {
1607 bonus = P_SKILL(type);
1608 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1609 bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2;
1612 /* KMH -- It's harder to hit while you are riding */
1614 switch (P_SKILL(P_RIDING)) {
1615 case P_ISRESTRICTED:
1635 * Return damage bonus/penalty based on skill of weapon.
1636 * Treat restricted weapons as unskilled.
1639 weapon_dam_bonus(weapon)
1642 int type, wep_type, skill, bonus = 0;
1644 wep_type = weapon_type(weapon);
1645 /* use two weapon skill only if attacking with one of the wielded weapons
1647 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1648 ? P_TWO_WEAPON_COMBAT
1650 if (type == P_NONE) {
1652 } else if (type <= P_LAST_WEAPON) {
1653 switch (P_SKILL(type)) {
1655 impossible("weapon_dam_bonus: bad skill %d", P_SKILL(type));
1657 case P_ISRESTRICTED:
1671 } else if (type == P_TWO_WEAPON_COMBAT) {
1672 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1673 if (P_SKILL(wep_type) < skill)
1674 skill = P_SKILL(wep_type);
1677 case P_ISRESTRICTED:
1691 } else if (type == P_BARE_HANDED_COMBAT) {
1701 bonus = P_SKILL(type);
1702 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1703 bonus = ((bonus + 1) * (martial_bonus() ? 3 : 1)) / 2;
1706 /* KMH -- Riding gives some thrusting damage */
1707 if (u.usteed && type != P_TWO_WEAPON_COMBAT) {
1708 switch (P_SKILL(P_RIDING)) {
1709 case P_ISRESTRICTED:
1727 * Initialize weapon skill array for the game. Start by setting all
1728 * skills to restricted, then set the skill for every weapon the
1729 * hero is holding, finally reading the given array that sets
1733 skill_init(class_skill)
1734 const struct def_skill *class_skill;
1739 /* initialize skill array; by default, everything is restricted */
1740 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1741 P_SKILL(skill) = P_ISRESTRICTED;
1742 P_MAX_SKILL(skill) = P_ISRESTRICTED;
1743 P_ADVANCE(skill) = 0;
1746 /* Set skill for all weapons in inventory to be basic */
1747 for (obj = invent; obj; obj = obj->nobj) {
1748 /* don't give skill just because of carried ammo, wait until
1749 we see the relevant launcher (prevents an archeologist's
1750 touchstone from inadvertently providing skill in sling) */
1754 skill = weapon_type(obj);
1755 if (skill != P_NONE)
1756 P_SKILL(skill) = P_BASIC;
1759 /* set skills for magic */
1760 if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
1761 P_SKILL(P_HEALING_SPELL) = P_BASIC;
1762 } else if (Role_if(PM_PRIEST)) {
1763 P_SKILL(P_CLERIC_SPELL) = P_BASIC;
1764 } else if (Role_if(PM_WIZARD)) {
1765 P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1766 P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
1769 /* walk through array to set skill maximums */
1770 for (; class_skill->skill != P_NONE; class_skill++) {
1771 skmax = class_skill->skmax;
1772 skill = class_skill->skill;
1774 P_MAX_SKILL(skill) = skmax;
1775 if (P_SKILL(skill) == P_ISRESTRICTED) /* skill pre-set */
1776 P_SKILL(skill) = P_UNSKILLED;
1779 /* High potential fighters already know how to use their hands. */
1780 if (P_MAX_SKILL(P_BARE_HANDED_COMBAT) > P_EXPERT)
1781 P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
1783 /* Roles that start with a horse know how to ride it */
1784 if (urole.petnum == PM_PONY)
1785 P_SKILL(P_RIDING) = P_BASIC;
1788 * Make sure we haven't missed setting the max on a skill
1791 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1792 if (!P_RESTRICTED(skill)) {
1793 if (P_MAX_SKILL(skill) < P_SKILL(skill)) {
1794 impossible("skill_init: curr > max: %s", P_NAME(skill));
1795 P_MAX_SKILL(skill) = P_SKILL(skill);
1797 P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill) - 1);
1801 /* each role has a special spell; allow at least basic for its type
1802 (despite the function name, this works for spell skills too) */
1803 unrestrict_weapon_skill(spell_skilltype(urole.spelspec));
1807 setmnotwielded(mon, obj)
1808 register struct monst *mon;
1809 register struct obj *obj;
1813 if (artifact_light(obj) && obj->lamplit) {
1814 end_burn(obj, FALSE);
1817 pline("%s in %s %s %s shining.", The(xname(obj)),
1818 s_suffix(mon_nam(mon)), mbodypart(mon, HAND),
1819 otense(obj, "stop"));
1821 pline("%s
\82ª
\8e\9d\82Â%s
\82Ì
\8bP
\82«
\82ª
\8fÁ
\82¦
\82½
\81D",
1822 mon_nam(mon), xname(obj));
1825 if (MON_WEP(mon) == obj)
1827 obj->owornmask &= ~W_WEP;