1 /* NetHack 3.6 weapon.c $NHDT-Date: 1559998716 2019/06/08 12:58:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.70 $ */
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-2020 */
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;
480 char rings[20]; /* plenty of room for "rings" */
482 int ltyp = ((uleft && (silverhit & W_RINGL) != 0L)
483 ? uleft->otyp : STRANGE_OBJECT),
484 rtyp = ((uright && (silverhit & W_RINGR) != 0L)
485 ? uright->otyp : STRANGE_OBJECT);
487 l_ag = (objects[ltyp].oc_material == SILVER && uleft->dknown),
488 r_ag = (objects[rtyp].oc_material == SILVER && uright->dknown);
490 if ((silverhit & (W_RINGL | W_RINGR)) != 0L) {
491 /* plural if both the same type (so not multi_claw and both rings
492 are non-Null) and either both known or neither known, or both
493 silver (in case there is ever more than one type of silver ring)
494 and both known; singular if multi_claw (where one of ltyp or
495 rtyp will always be STRANGE_OBJECT) even if both rings are known
496 silver [see hmonas(uhitm.c) for explanation of 'multi_claw'] */
497 both = ((ltyp == rtyp && uleft->dknown == uright->dknown)
500 Sprintf(rings, "ring%s", both ? "s" : "");
502 (l_ag || r_ag) ? "silver "
504 : ((silverhit & W_RINGL) != 0L) ? "left "
506 rings, vtense(rings, "sear"), mon_nam(mdef));
508 Your("%s
\8ew
\97Ö
\82ª%s
\82ð
\8fÄ
\82¢
\82½
\81I",
509 (l_ag || r_ag) ? "
\8bâ
\82Ì"
511 : ((silverhit & W_RINGL) != 0L) ? "
\8d¶
\82Ì"
518 STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int));
520 if ((otmp = oselect(mtmp, x)) != 0) \
523 STATIC_OVL struct obj *
530 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
532 /* never select non-cockatrice corpses */
533 && !((x == CORPSE || x == EGG)
534 && !touch_petrifies(&mons[otmp->corpsenm]))
535 && (!otmp->oartifact || touch_artifact(otmp, mtmp)))
538 return (struct obj *) 0;
541 /* TODO: have monsters use aklys' throw-and-return */
542 static NEARDATA const int rwep[] = {
543 DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
544 SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
545 CROSSBOW_BOLT, SILVER_DAGGER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE,
546 FLINT, ROCK, LOADSTONE, LUCKSTONE, DART,
547 /* BOOMERANG, */ CREAM_PIE
550 static NEARDATA const int pwep[] = { HALBERD, BARDICHE, SPETUM,
551 BILL_GUISARME, VOULGE, RANSEUR,
552 GUISARME, GLAIVE, LUCERN_HAMMER,
553 BEC_DE_CORBIN, FAUCHARD, PARTISAN,
556 static struct obj *propellor;
558 /* select a ranged weapon for the monster */
561 register struct monst *mtmp;
563 register struct obj *otmp;
568 char mlet = mtmp->data->mlet;
570 propellor = (struct obj *) &zeroobj;
571 Oselect(EGG); /* cockatrice egg */
572 if (mlet == S_KOP) /* pies are first choice for Kops */
574 if (throws_rocks(mtmp->data)) /* ...boulders for giants */
577 /* Select polearms first; they do more damage and aren't expendable.
578 But don't pick one if monster's weapon is welded, because then
579 we'd never have a chance to throw non-wielding missiles. */
580 /* The limit of 13 here is based on the monster polearm range limit
581 * (defined as 5 in mthrowu.c). 5 corresponds to a distance of 2 in
582 * one direction and 1 in another; one space beyond that would be 3 in
583 * one direction and 2 in another; 3^2+2^2=13.
585 mwep = MON_WEP(mtmp);
586 /* NO_WEAPON_WANTED means we already tried to wield and failed */
587 mweponly = (mwelded(mwep) && mtmp->weapon_check == NO_WEAPON_WANTED);
588 if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 13
589 && couldsee(mtmp->mx, mtmp->my)) {
590 for (i = 0; i < SIZE(pwep); i++) {
591 /* Only strong monsters can wield big (esp. long) weapons.
592 * Big weapon is basically the same as bimanual.
593 * All monsters can wield the remaining weapons.
595 if (((strongmonst(mtmp->data)
596 && (mtmp->misc_worn_check & W_ARMS) == 0)
597 || !objects[pwep[i]].oc_bimanual)
598 && (objects[pwep[i]].oc_material != SILVER
599 || !mon_hates_silver(mtmp))) {
600 if ((otmp = oselect(mtmp, pwep[i])) != 0
601 && (otmp == mwep || !mweponly)) {
602 propellor = otmp; /* force the monster to wield it */
610 * other than these two specific cases, always select the
611 * most potent ranged weapon to hand.
613 for (i = 0; i < SIZE(rwep); i++) {
616 /* shooting gems from slings; this goes just before the darts */
617 /* (shooting rocks is already handled via the rwep[] ordering) */
618 if (rwep[i] == DART && !likes_gems(mtmp->data)
619 && m_carrying(mtmp, SLING)) { /* propellor */
620 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
621 if (otmp->oclass == GEM_CLASS
622 && (otmp->otyp != LOADSTONE || !otmp->cursed)) {
623 propellor = m_carrying(mtmp, SLING);
628 /* KMH -- This belongs here so darts will work */
629 propellor = (struct obj *) &zeroobj;
631 prop = objects[rwep[i]].oc_skill;
635 propellor = oselect(mtmp, YUMI);
637 propellor = oselect(mtmp, ELVEN_BOW);
639 propellor = oselect(mtmp, BOW);
641 propellor = oselect(mtmp, ORCISH_BOW);
644 propellor = oselect(mtmp, SLING);
647 propellor = oselect(mtmp, CROSSBOW);
649 if ((otmp = MON_WEP(mtmp)) && mwelded(otmp) && otmp != propellor
650 && mtmp->weapon_check == NO_WEAPON_WANTED)
653 /* propellor = obj, propellor to use
654 * propellor = &zeroobj, doesn't need a propellor
655 * propellor = 0, needed one and didn't have one
657 if (propellor != 0) {
658 /* Note: cannot use m_carrying for loadstones, since it will
659 * always select the first object of a type, and maybe the
660 * monster is carrying two but only the first is unthrowable.
662 if (rwep[i] != LOADSTONE) {
663 /* Don't throw a cursed weapon-in-hand or an artifact */
664 if ((otmp = oselect(mtmp, rwep[i])) && !otmp->oartifact
665 && !(otmp == MON_WEP(mtmp) && mwelded(otmp)))
668 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
669 if (otmp->otyp == LOADSTONE && !otmp->cursed)
676 return (struct obj *) 0;
679 /* is 'obj' a type of weapon that any monster knows how to throw? */
681 monmightthrowwep(obj)
686 for (idx = 0; idx < SIZE(rwep); ++idx)
687 if (obj->otyp == rwep[idx])
692 /* Weapons in order of preference */
693 static const NEARDATA short hwep[] = {
694 CORPSE, /* cockatrice corpse */
695 TSURUGI, RUNESWORD, DWARVISH_MATTOCK, TWO_HANDED_SWORD, BATTLE_AXE,
696 KATANA, UNICORN_HORN, CRYSKNIFE, TRIDENT, LONG_SWORD, ELVEN_BROADSWORD,
697 BROADSWORD, SCIMITAR, SILVER_SABER, MORNING_STAR, ELVEN_SHORT_SWORD,
698 DWARVISH_SHORT_SWORD, SHORT_SWORD, ORCISH_SHORT_SWORD, MACE, AXE,
699 DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, FLAIL,
700 BULLWHIP, QUARTERSTAFF, JAVELIN, AKLYS, CLUB, PICK_AXE, RUBBER_HOSE,
701 WAR_HAMMER, SILVER_DAGGER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, ATHAME,
702 SCALPEL, KNIFE, WORM_TOOTH
705 /* select a hand to hand weapon for the monster */
708 register struct monst *mtmp;
710 register struct obj *otmp;
712 boolean strong = strongmonst(mtmp->data);
713 boolean wearing_shield = (mtmp->misc_worn_check & W_ARMS) != 0;
715 /* prefer artifacts to everything else */
716 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
717 if (otmp->oclass == WEAPON_CLASS && otmp->oartifact
718 && touch_artifact(otmp, mtmp)
719 && ((strong && !wearing_shield)
720 || !objects[otmp->otyp].oc_bimanual))
724 if (is_giant(mtmp->data)) /* giants just love to use clubs */
727 /* only strong monsters can wield big (esp. long) weapons */
728 /* big weapon is basically the same as bimanual */
729 /* all monsters can wield the remaining weapons */
730 for (i = 0; i < SIZE(hwep); i++) {
731 if (hwep[i] == CORPSE && !(mtmp->misc_worn_check & W_ARMG)
732 && !resists_ston(mtmp))
734 if (((strong && !wearing_shield) || !objects[hwep[i]].oc_bimanual)
735 && (objects[hwep[i]].oc_material != SILVER
736 || !mon_hates_silver(mtmp)))
741 return (struct obj *) 0;
744 /* Called after polymorphing a monster, robbing it, etc.... Monsters
745 * otherwise never unwield stuff on their own. Might print message.
748 possibly_unwield(mon, polyspot)
752 struct obj *obj, *mw_tmp;
754 if (!(mw_tmp = MON_WEP(mon)))
756 for (obj = mon->minvent; obj; obj = obj->nobj)
759 if (!obj) { /* The weapon was stolen or destroyed */
761 mon->weapon_check = NEED_WEAPON;
764 if (!attacktype(mon->data, AT_WEAP)) {
765 setmnotwielded(mon, mw_tmp);
766 mon->weapon_check = NO_WEAPON_WANTED;
767 obj_extract_self(obj);
768 if (cansee(mon->mx, mon->my)) {
770 pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
772 pline("%s
\82Í%s
\82ð
\92u
\82¢
\82½
\81D", Monnam(mon), distant_name(obj, doname));
773 newsym(mon->mx, mon->my);
775 /* might be dropping object into water or lava */
777 if (!flooreffects(obj, mon->mx, mon->my, "drop")) {
779 if (!flooreffects(obj, mon->mx, mon->my, "
\97\8e\82¿
\82é")) {
782 place_object(obj, mon->mx, mon->my);
787 /* The remaining case where there is a change is where a monster
788 * is polymorphed into a stronger/weaker monster with a different
789 * choice of weapons. This has no parallel for players. It can
790 * be handled by waiting until mon_wield_item is actually called.
791 * Though the monster still wields the wrong weapon until then,
792 * this is OK since the player can't see it. (FIXME: Not okay since
793 * probing can reveal it.)
794 * Note that if there is no change, setting the check to NEED_WEAPON
796 * Possible problem: big monster with big cursed weapon gets
797 * polymorphed into little monster. But it's not quite clear how to
798 * handle this anyway....
800 if (!(mwelded(mw_tmp) && mon->weapon_check == NO_WEAPON_WANTED))
801 mon->weapon_check = NEED_WEAPON;
805 /* Let a monster try to wield a weapon, based on mon->weapon_check.
806 * Returns 1 if the monster took time to do it, 0 if it did not.
810 register struct monst *mon;
814 /* This case actually should never happen */
815 if (mon->weapon_check == NO_WEAPON_WANTED)
817 switch (mon->weapon_check) {
818 case NEED_HTH_WEAPON:
819 obj = select_hwep(mon);
821 case NEED_RANGED_WEAPON:
822 (void) select_rwep(mon);
826 obj = m_carrying(mon, PICK_AXE);
827 /* KMH -- allow other picks */
828 if (!obj && !which_armor(mon, W_ARMS))
829 obj = m_carrying(mon, DWARVISH_MATTOCK);
832 /* currently, only 2 types of axe */
833 obj = m_carrying(mon, BATTLE_AXE);
834 if (!obj || which_armor(mon, W_ARMS))
835 obj = m_carrying(mon, AXE);
837 case NEED_PICK_OR_AXE:
838 /* prefer pick for fewer switches on most levels */
839 obj = m_carrying(mon, DWARVISH_MATTOCK);
841 obj = m_carrying(mon, BATTLE_AXE);
842 if (!obj || which_armor(mon, W_ARMS)) {
843 obj = m_carrying(mon, PICK_AXE);
845 obj = m_carrying(mon, AXE);
849 impossible("weapon_check %d for %s?", mon->weapon_check,
853 if (obj && obj != &zeroobj) {
854 struct obj *mw_tmp = MON_WEP(mon);
856 if (mw_tmp && mw_tmp->otyp == obj->otyp) {
857 /* already wielding it */
858 mon->weapon_check = NEED_WEAPON;
861 /* Actually, this isn't necessary--as soon as the monster
862 * wields the weapon, the weapon welds itself, so the monster
863 * can know it's cursed and needn't even bother trying.
866 if (mw_tmp && mwelded(mw_tmp)) {
867 if (canseemon(mon)) {
869 char welded_buf[BUFSZ];
871 const char *mon_hand = mbodypart(mon, HAND);
873 if (bimanual(mw_tmp))
874 mon_hand = makeplural(mon_hand);
876 Sprintf(welded_buf, "%s welded to %s %s",
877 otense(mw_tmp, "are"), mhis(mon), mon_hand);
880 if (obj->otyp == PICK_AXE) {
882 pline("Since %s weapon%s %s,", s_suffix(mon_nam(mon)),
883 plur(mw_tmp->quan), welded_buf);
885 pline("%s
\82Í
\95\90\8aí
\82ð
\8eè
\82É
\82µ
\82æ
\82¤
\82Æ
\82µ
\82½
\82ª
\81C", mon_nam(mon));
888 pline("%s cannot wield that %s.", mon_nam(mon),
891 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82Å
\82«
\82È
\82©
\82Á
\82½
\81D", mon_nam(mon),
896 pline("%s tries to wield %s.", Monnam(mon), doname(obj));
898 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82µ
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", Monnam(mon), doname(obj));
900 pline("%s %s!", Yname2(mw_tmp), welded_buf);
902 pline("%s
\82Í%s
\82ð
\8eè
\82É
\82µ
\82½
\81I", Monnam(mon), xname(mw_tmp));
906 mon->weapon_check = NO_WEAPON_WANTED;
909 mon->mw = obj; /* wield obj */
910 setmnotwielded(mon, mw_tmp);
911 mon->weapon_check = NEED_WEAPON;
912 if (canseemon(mon)) {
913 boolean newly_welded;
916 pline("%s wields %s!", Monnam(mon), doname(obj));
918 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82µ
\82½
\81I", Monnam(mon), doname(obj));
919 /* 3.6.3: mwelded() predicate expects the object to have its
920 W_WEP bit set in owormmask, but the pline here and for
921 artifact_light don't want that because they'd have '(weapon
922 in hand/claw)' appended; so we set it for the mwelded test
923 and then clear it, until finally setting it for good below */
924 obj->owornmask |= W_WEP;
925 newly_welded = mwelded(obj);
926 obj->owornmask &= ~W_WEP;
929 pline("%s %s to %s %s!", Tobjnam(obj, "weld"),
930 is_plural(obj) ? "themselves" : "itself",
931 s_suffix(mon_nam(mon)), mbodypart(mon, HAND));
933 pline("%s
\82Í
\8f\9f\8eè
\82É%s
\82Ì%s
\82É
\91\95\94õ
\82³
\82ê
\82½
\81I",
935 mon_nam(mon), mbodypart(mon, HAND));
940 if (artifact_light(obj) && !obj->lamplit) {
941 begin_burn(obj, FALSE);
944 pline("%s %s in %s %s!", Tobjnam(obj, "shine"),
945 arti_light_description(obj), s_suffix(mon_nam(mon)),
946 mbodypart(mon, HAND));
948 pline("%s
\82Í%s
\82Ì%s
\82Ì
\92\86\82Å%s
\8bP
\82¢
\82½
\81I",
949 xname(obj), mon_nam(mon),
950 mbodypart(mon, HAND), arti_light_description(obj));
952 /* 3.6.3: artifact might be getting wielded by invisible monst */
953 else if (cansee(mon->mx, mon->my))
955 pline("Light begins shining %s.",
956 (distu(mon->mx, mon->my) <= 5 * 5)
958 : "in the distance");
960 pline("
\96¾
\82©
\82è
\82ª%s
\82Å
\8bP
\82«
\82Í
\82¶
\82ß
\82½
\81D",
961 (distu(mon->mx, mon->my) <= 5 * 5)
966 obj->owornmask = W_WEP;
969 mon->weapon_check = NEED_WEAPON;
973 /* force monster to stop wielding current weapon, if any */
978 struct obj *mwep = MON_WEP(mon);
981 setmnotwielded(mon, mwep);
982 mon->weapon_check = NEED_WEAPON;
986 /* attack bonus for strength & dexterity */
991 int str = ACURR(A_STR), dex = ACURR(A_DEX);
994 return (adj_lev(&mons[u.umonnum]) - 3);
1001 else if (str <= STR18(50))
1002 sbon = 1; /* up to 18/50 */
1003 else if (str < STR18(100))
1008 /* Game tuning kludge: make it a bit easier for a low level character to
1010 sbon += (u.ulevel < 3) ? 1 : 0;
1021 return (sbon + dex - 14);
1024 /* damage bonus for strength */
1028 int str = ACURR(A_STR);
1040 return 2; /* up to 18 */
1041 else if (str <= STR18(75))
1042 return 3; /* up to 18/75 */
1043 else if (str <= STR18(90))
1044 return 4; /* up to 18/90 */
1045 else if (str < STR18(100))
1046 return 5; /* up to 18/99 */
1051 /* increase a towel's wetness */
1053 wet_a_towel(obj, amt, verbose)
1055 int amt; /* positive: new value; negative: increment by -amt; zero: no-op */
1058 int newspe = (amt <= 0) ? obj->spe - amt : amt;
1060 /* new state is only reported if it's an increase */
1061 if (newspe > obj->spe) {
1064 const char *wetness = (newspe < 3)
1065 ? (!obj->spe ? "damp" : "damper")
1066 : (!obj->spe ? "wet" : "wetter");
1068 const char *wetness = (newspe < 3)
1069 ? (!obj->spe ? "
\8e¼
\82Á
\82½" : "
\82³
\82ç
\82É
\8e¼
\82Á
\82½")
1070 : (!obj->spe ? "
\94G
\82ê
\82½" : "
\82³
\82ç
\82É
\94G
\82ê
\82½");
1075 pline("%s gets %s.", Yobjnam2(obj, (const char *) 0),
1078 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
1081 else if (mcarried(obj) && canseemon(obj->ocarry))
1083 pline("%s %s gets %s.", s_suffix(Monnam(obj->ocarry)),
1084 xname(obj), wetness);
1086 pline("%s
\82Ì%s
\82Í%s
\81D", Monnam(obj->ocarry),
1087 xname(obj), wetness);
1091 obj->spe = min(newspe, 7);
1093 /* if hero is wielding this towel, don't give "you begin bashing
1094 with your wet towel" message on next attack with it */
1096 unweapon = !is_wet_towel(obj);
1099 /* decrease a towel's wetness */
1101 dry_a_towel(obj, amt, verbose)
1103 int amt; /* positive: new value; negative: decrement by -amt; zero: no-op */
1106 int newspe = (amt <= 0) ? obj->spe + amt : amt;
1108 /* new state is only reported if it's a decrease */
1109 if (newspe < obj->spe) {
1113 pline("%s dries%s.", Yobjnam2(obj, (const char *) 0),
1114 !newspe ? " out" : "");
1116 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
1117 !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
1119 else if (mcarried(obj) && canseemon(obj->ocarry))
1121 pline("%s %s drie%s.", s_suffix(Monnam(obj->ocarry)),
1122 xname(obj), !newspe ? " out" : "");
1124 pline("%s
\82Ì%s
\82Í%s
\81D", Monnam(obj->ocarry),
1125 xname(obj), !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
1129 newspe = min(newspe, 7);
1130 obj->spe = max(newspe, 0);
1132 /* if hero is wielding this towel and it is now dry, give "you begin
1133 bashing with your towel" message on next attack with it */
1135 unweapon = !is_wet_towel(obj);
1138 /* copy the skill level name into the given buffer */
1140 skill_level_name(skill, buf)
1146 switch (P_SKILL(skill)) {
1151 ptr = "
\8f\89\90S
\8eÒ";
1157 ptr = "
\93ü
\96å
\8eÒ";
1163 ptr = "
\8fn
\97û
\8eÒ";
1169 ptr = "
\83G
\83L
\83X
\83p
\81[
\83g";
1171 /* these are for unarmed combat/martial arts only */
1176 ptr = "
\83}
\83X
\83^
\81[";
1178 case P_GRAND_MASTER:
1180 ptr = "Grand Master";
1182 ptr = "
\83O
\83\89\83\93\83h
\83}
\83X
\83^
\81[";
1199 return P_NAME(skill);
1202 /* return the # of slots required to advance the skill */
1204 slots_required(skill)
1207 int tmp = P_SKILL(skill);
1209 /* The more difficult the training, the more slots it takes.
1210 * unskilled -> basic 1
1211 * basic -> skilled 2
1212 * skilled -> expert 3
1214 if (skill <= P_LAST_WEAPON || skill == P_TWO_WEAPON_COMBAT)
1217 /* Fewer slots used up for unarmed or martial.
1218 * unskilled -> basic 1
1219 * basic -> skilled 1
1220 * skilled -> expert 2
1221 * expert -> master 2
1222 * master -> grand master 3
1224 return (tmp + 1) / 2;
1227 /* return true if this skill can be advanced */
1229 can_advance(skill, speedy)
1233 if (P_RESTRICTED(skill)
1234 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1235 || u.skills_advanced >= P_SKILL_LIMIT)
1238 if (wizard && speedy)
1241 return (boolean) ((int) P_ADVANCE(skill)
1242 >= practice_needed_to_advance(P_SKILL(skill))
1243 && u.weapon_slots >= slots_required(skill));
1246 /* return true if this skill could be advanced if more slots were available */
1248 could_advance(skill)
1251 if (P_RESTRICTED(skill)
1252 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1253 || u.skills_advanced >= P_SKILL_LIMIT)
1256 return (boolean) ((int) P_ADVANCE(skill)
1257 >= practice_needed_to_advance(P_SKILL(skill)));
1260 /* return true if this skill has reached its maximum and there's been enough
1261 practice to become eligible for the next step if that had been possible */
1266 if (P_RESTRICTED(skill))
1269 return (boolean) (P_SKILL(skill) >= P_MAX_SKILL(skill)
1270 && ((int) P_ADVANCE(skill)
1271 >= practice_needed_to_advance(P_SKILL(skill))));
1275 skill_advance(skill)
1278 u.weapon_slots -= slots_required(skill);
1280 u.skill_record[u.skills_advanced++] = skill;
1281 /* subtly change the advance message to indicate no more advancement */
1283 You("are now %s skilled in %s.",
1284 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more",
1287 Your("%s
\82Ì
\83X
\83L
\83\8b\82ð%s
\8d\82\82ß
\82½
\81D",
1289 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "
\8dÅ
\8d\82\82É" : "
\82³
\82ç
\82É");
1293 static const struct skill_range {
1296 } skill_ranges[] = {
1298 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "Fighting Skills" },
1300 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "
\90í
\82¢
\82Ì
\83X
\83L
\83\8b" },
1302 { P_FIRST_WEAPON, P_LAST_WEAPON, "Weapon Skills" },
1304 { P_FIRST_WEAPON, P_LAST_WEAPON, "
\95\90\8aí
\82Ì
\83X
\83L
\83\8b" },
1306 { P_FIRST_SPELL, P_LAST_SPELL, "Spellcasting Skills" },
1308 { P_FIRST_SPELL, P_LAST_SPELL, "
\96\82\96@
\82Ì
\83X
\83L
\83\8b" },
1312 * The `#enhance' extended command. What we _really_ would like is
1313 * to keep being able to pick things to advance until we couldn't any
1314 * more. This is currently not possible -- the menu code has no way
1315 * to call us back for instant action. Even if it did, we would also need
1316 * to be able to update the menu since selecting one item could make
1317 * others unselectable.
1320 enhance_weapon_skill()
1322 int pass, i, n, len, longest, to_advance, eventually_advance, maxxed_cnt;
1323 char buf[BUFSZ], sklnambuf[BUFSZ];
1325 menu_item *selected;
1328 boolean speedy = FALSE;
1330 if (wizard && yn("Advance skills without practice?") == 'y')
1334 /* find longest available skill name, count those that can advance */
1335 to_advance = eventually_advance = maxxed_cnt = 0;
1336 for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) {
1337 if (P_RESTRICTED(i))
1339 if ((len = strlen(P_NAME(i))) > longest)
1341 if (can_advance(i, speedy))
1343 else if (could_advance(i))
1344 eventually_advance++;
1345 else if (peaked_skill(i))
1349 win = create_nhwindow(NHW_MENU);
1352 /* start with a legend if any entries will be annotated
1353 with "*" or "#" below */
1354 if (eventually_advance > 0 || maxxed_cnt > 0) {
1356 if (eventually_advance > 0) {
1358 Sprintf(buf, "(Skill%s flagged by \"*\" may be enhanced %s.)",
1359 plur(eventually_advance),
1360 (u.ulevel < MAXULEV)
1361 ? "when you're more experienced"
1362 : "if skill slots become available");
1364 Sprintf(buf, "(\"*\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í%s
\8d\82\82ß
\82ç
\82ê
\82é
\81D)",
1365 (u.ulevel < MAXULEV)
1366 ? "
\82à
\82Á
\82Æ
\8co
\8c±
\82ð
\82Â
\82ß
\82Î"
1367 : "
\83X
\83L
\83\8b\83X
\83\8d\83b
\83g
\82ª
\8eg
\82¦
\82é
\82æ
\82¤
\82É
\82È
\82ê
\82Î");
1369 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1372 if (maxxed_cnt > 0) {
1375 "(Skill%s flagged by \"#\" cannot be enhanced any further.)",
1379 "(\"#\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í
\82±
\82ê
\88È
\8fã
\8d\82\82ß
\82ç
\82ê
\82È
\82¢
\81D)");
1381 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1384 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
1388 /* List the skills, making ones that could be advanced
1389 selectable. List the miscellaneous skills first.
1390 Possible future enhancement: list spell skills before
1391 weapon skills for spellcaster roles. */
1392 for (pass = 0; pass < SIZE(skill_ranges); pass++)
1393 for (i = skill_ranges[pass].first; i <= skill_ranges[pass].last;
1395 /* Print headings for skill types */
1397 if (i == skill_ranges[pass].first)
1398 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
1399 skill_ranges[pass].name, MENU_UNSELECTED);
1401 if (P_RESTRICTED(i))
1404 * Sigh, this assumes a monospaced font unless
1405 * iflags.menu_tab_sep is set in which case it puts
1406 * tabs between columns.
1407 * The 12 is the longest skill level name.
1408 * The " " is room for a selection letter and dash, "a - ".
1410 if (can_advance(i, speedy))
1411 prefix = ""; /* will be preceded by menu choice */
1412 else if (could_advance(i))
1414 else if (peaked_skill(i))
1418 (to_advance + eventually_advance + maxxed_cnt > 0)
1421 (void) skill_level_name(i, sklnambuf);
1423 if (!iflags.menu_tab_sep)
1424 Sprintf(buf, " %s%-*s %-12s %5d(%4d)", prefix,
1425 longest, P_NAME(i), sklnambuf, P_ADVANCE(i),
1426 practice_needed_to_advance(P_SKILL(i)));
1428 Sprintf(buf, " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i),
1429 sklnambuf, P_ADVANCE(i),
1430 practice_needed_to_advance(P_SKILL(i)));
1432 if (!iflags.menu_tab_sep)
1433 Sprintf(buf, " %s %-*s [%s]", prefix, longest,
1434 P_NAME(i), sklnambuf);
1436 Sprintf(buf, " %s%s\t[%s]", prefix, P_NAME(i),
1439 any.a_int = can_advance(i, speedy) ? i + 1 : 0;
1440 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1445 Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:"
1446 : "Current skills:");
1448 Strcpy(buf, (to_advance > 0) ? "
\83X
\83L
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F"
1449 : "
\8c»
\8dÝ
\82Ì
\83X
\83L
\83\8b\81F");
1451 if (wizard && !speedy)
1452 Sprintf(eos(buf), " (%d slot%s available)", u.weapon_slots,
1453 plur(u.weapon_slots));
1455 n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
1456 destroy_nhwindow(win);
1458 n = selected[0].item.a_int - 1; /* get item selected */
1459 free((genericptr_t) selected);
1461 /* check for more skills able to advance, if so then .. */
1462 for (n = i = 0; i < P_NUM_SKILLS; i++) {
1463 if (can_advance(i, speedy)) {
1466 You_feel("you could be more dangerous!");
1468 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");
1474 } while (speedy && n > 0);
1479 * Change from restricted to unrestricted, allowing P_BASIC as max. This
1480 * function may be called with with P_NONE. Used in pray.c as well as below.
1483 unrestrict_weapon_skill(skill)
1486 if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
1487 P_SKILL(skill) = P_UNSKILLED;
1488 P_MAX_SKILL(skill) = P_BASIC;
1489 P_ADVANCE(skill) = 0;
1494 use_skill(skill, degree)
1498 boolean advance_before;
1500 if (skill != P_NONE && !P_RESTRICTED(skill)) {
1501 advance_before = can_advance(skill, FALSE);
1502 P_ADVANCE(skill) += degree;
1503 if (!advance_before && can_advance(skill, FALSE))
1504 give_may_advance_msg(skill);
1510 int n; /* number of slots to gain; normally one */
1512 int i, before, after;
1514 for (i = 0, before = 0; i < P_NUM_SKILLS; i++)
1515 if (can_advance(i, FALSE))
1517 u.weapon_slots += n;
1518 for (i = 0, after = 0; i < P_NUM_SKILLS; i++)
1519 if (can_advance(i, FALSE))
1522 give_may_advance_msg(P_NONE);
1526 lose_weapon_skill(n)
1527 int n; /* number of slots to lose; normally one */
1532 /* deduct first from unused slots then from last placed one, if any */
1533 if (u.weapon_slots) {
1535 } else if (u.skills_advanced) {
1536 skill = u.skill_record[--u.skills_advanced];
1537 if (P_SKILL(skill) <= P_UNSKILLED)
1538 panic("lose_weapon_skill (%d)", skill);
1539 P_SKILL(skill)--; /* drop skill one level */
1540 /* Lost skill might have taken more than one slot; refund rest. */
1541 u.weapon_slots = slots_required(skill) - 1;
1542 /* It might now be possible to advance some other pending
1543 skill by using the refunded slots, but giving a message
1544 to that effect would seem pretty confusing.... */
1553 /* KMH -- now uses the object table */
1557 return P_BARE_HANDED_COMBAT; /* Not using a weapon */
1558 if (obj->oclass != WEAPON_CLASS && obj->oclass != TOOL_CLASS
1559 && obj->oclass != GEM_CLASS)
1560 return P_NONE; /* Not a weapon, weapon-tool, or ammo */
1561 type = objects[obj->otyp].oc_skill;
1562 return (type < 0) ? -type : type;
1569 return P_TWO_WEAPON_COMBAT;
1570 return weapon_type(uwep);
1574 * Return hit bonus/penalty based on skill of weapon.
1575 * Treat restricted weapons as unskilled.
1578 weapon_hit_bonus(weapon)
1581 int type, wep_type, skill, bonus = 0;
1582 static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
1584 wep_type = weapon_type(weapon);
1585 /* use two weapon skill only if attacking with one of the wielded weapons
1587 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1588 ? P_TWO_WEAPON_COMBAT
1590 if (type == P_NONE) {
1592 } else if (type <= P_LAST_WEAPON) {
1593 switch (P_SKILL(type)) {
1595 impossible(bad_skill, P_SKILL(type)); /* fall through */
1596 case P_ISRESTRICTED:
1610 } else if (type == P_TWO_WEAPON_COMBAT) {
1611 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1612 if (P_SKILL(wep_type) < skill)
1613 skill = P_SKILL(wep_type);
1616 impossible(bad_skill, skill); /* fall through */
1617 case P_ISRESTRICTED:
1631 } else if (type == P_BARE_HANDED_COMBAT) {
1641 bonus = P_SKILL(type);
1642 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1643 bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2;
1646 /* KMH -- It's harder to hit while you are riding */
1648 switch (P_SKILL(P_RIDING)) {
1649 case P_ISRESTRICTED:
1669 * Return damage bonus/penalty based on skill of weapon.
1670 * Treat restricted weapons as unskilled.
1673 weapon_dam_bonus(weapon)
1676 int type, wep_type, skill, bonus = 0;
1678 wep_type = weapon_type(weapon);
1679 /* use two weapon skill only if attacking with one of the wielded weapons
1681 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1682 ? P_TWO_WEAPON_COMBAT
1684 if (type == P_NONE) {
1686 } else if (type <= P_LAST_WEAPON) {
1687 switch (P_SKILL(type)) {
1689 impossible("weapon_dam_bonus: bad skill %d", P_SKILL(type));
1691 case P_ISRESTRICTED:
1705 } else if (type == P_TWO_WEAPON_COMBAT) {
1706 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1707 if (P_SKILL(wep_type) < skill)
1708 skill = P_SKILL(wep_type);
1711 case P_ISRESTRICTED:
1725 } else if (type == P_BARE_HANDED_COMBAT) {
1735 bonus = P_SKILL(type);
1736 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1737 bonus = ((bonus + 1) * (martial_bonus() ? 3 : 1)) / 2;
1740 /* KMH -- Riding gives some thrusting damage */
1741 if (u.usteed && type != P_TWO_WEAPON_COMBAT) {
1742 switch (P_SKILL(P_RIDING)) {
1743 case P_ISRESTRICTED:
1761 * Initialize weapon skill array for the game. Start by setting all
1762 * skills to restricted, then set the skill for every weapon the
1763 * hero is holding, finally reading the given array that sets
1767 skill_init(class_skill)
1768 const struct def_skill *class_skill;
1773 /* initialize skill array; by default, everything is restricted */
1774 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1775 P_SKILL(skill) = P_ISRESTRICTED;
1776 P_MAX_SKILL(skill) = P_ISRESTRICTED;
1777 P_ADVANCE(skill) = 0;
1780 /* Set skill for all weapons in inventory to be basic */
1781 for (obj = invent; obj; obj = obj->nobj) {
1782 /* don't give skill just because of carried ammo, wait until
1783 we see the relevant launcher (prevents an archeologist's
1784 touchstone from inadvertently providing skill in sling) */
1788 skill = weapon_type(obj);
1789 if (skill != P_NONE)
1790 P_SKILL(skill) = P_BASIC;
1793 /* set skills for magic */
1794 if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
1795 P_SKILL(P_HEALING_SPELL) = P_BASIC;
1796 } else if (Role_if(PM_PRIEST)) {
1797 P_SKILL(P_CLERIC_SPELL) = P_BASIC;
1798 } else if (Role_if(PM_WIZARD)) {
1799 P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1800 P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
1803 /* walk through array to set skill maximums */
1804 for (; class_skill->skill != P_NONE; class_skill++) {
1805 skmax = class_skill->skmax;
1806 skill = class_skill->skill;
1808 P_MAX_SKILL(skill) = skmax;
1809 if (P_SKILL(skill) == P_ISRESTRICTED) /* skill pre-set */
1810 P_SKILL(skill) = P_UNSKILLED;
1813 /* High potential fighters already know how to use their hands. */
1814 if (P_MAX_SKILL(P_BARE_HANDED_COMBAT) > P_EXPERT)
1815 P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
1817 /* Roles that start with a horse know how to ride it */
1818 if (urole.petnum == PM_PONY)
1819 P_SKILL(P_RIDING) = P_BASIC;
1822 * Make sure we haven't missed setting the max on a skill
1825 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1826 if (!P_RESTRICTED(skill)) {
1827 if (P_MAX_SKILL(skill) < P_SKILL(skill)) {
1828 impossible("skill_init: curr > max: %s", P_NAME(skill));
1829 P_MAX_SKILL(skill) = P_SKILL(skill);
1831 P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill) - 1);
1835 /* each role has a special spell; allow at least basic for its type
1836 (despite the function name, this works for spell skills too) */
1837 unrestrict_weapon_skill(spell_skilltype(urole.spelspec));
1841 setmnotwielded(mon, obj)
1842 register struct monst *mon;
1843 register struct obj *obj;
1847 if (artifact_light(obj) && obj->lamplit) {
1848 end_burn(obj, FALSE);
1851 pline("%s in %s %s %s shining.", The(xname(obj)),
1852 s_suffix(mon_nam(mon)), mbodypart(mon, HAND),
1853 otense(obj, "stop"));
1855 pline("%s
\82ª
\8e\9d\82Â%s
\82Ì
\8bP
\82«
\82ª
\8fÁ
\82¦
\82½
\81D",
1856 mon_nam(mon), xname(obj));
1859 if (MON_WEP(mon) == obj)
1861 obj->owornmask &= ~W_WEP;