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-2022 */
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;
928 const char *mon_hand = mbodypart(mon, HAND);
931 mon_hand = makeplural(mon_hand);
933 pline("%s %s to %s %s!", Tobjnam(obj, "weld"),
934 is_plural(obj) ? "themselves" : "itself",
935 s_suffix(mon_nam(mon)), mon_hand);
937 pline("%s
\82Í
\8f\9f\8eè
\82É%s
\82Ì%s
\82É
\91\95\94õ
\82³
\82ê
\82½
\81I",
939 mon_nam(mon), mon_hand);
944 if (artifact_light(obj) && !obj->lamplit) {
945 begin_burn(obj, FALSE);
948 pline("%s %s in %s %s!", Tobjnam(obj, "shine"),
949 arti_light_description(obj), s_suffix(mon_nam(mon)),
950 mbodypart(mon, HAND));
952 pline("%s
\82Í%s
\82Ì%s
\82Ì
\92\86\82Å%s
\8bP
\82¢
\82½
\81I",
953 xname(obj), mon_nam(mon),
954 mbodypart(mon, HAND), arti_light_description(obj));
956 /* 3.6.3: artifact might be getting wielded by invisible monst */
957 else if (cansee(mon->mx, mon->my))
959 pline("Light begins shining %s.",
960 (distu(mon->mx, mon->my) <= 5 * 5)
962 : "in the distance");
964 pline("
\96¾
\82©
\82è
\82ª%s
\82Å
\8bP
\82«
\82Í
\82¶
\82ß
\82½
\81D",
965 (distu(mon->mx, mon->my) <= 5 * 5)
970 obj->owornmask = W_WEP;
973 mon->weapon_check = NEED_WEAPON;
977 /* force monster to stop wielding current weapon, if any */
982 struct obj *mwep = MON_WEP(mon);
985 setmnotwielded(mon, mwep);
986 mon->weapon_check = NEED_WEAPON;
990 /* attack bonus for strength & dexterity */
995 int str = ACURR(A_STR), dex = ACURR(A_DEX);
998 return (adj_lev(&mons[u.umonnum]) - 3);
1005 else if (str <= STR18(50))
1006 sbon = 1; /* up to 18/50 */
1007 else if (str < STR18(100))
1012 /* Game tuning kludge: make it a bit easier for a low level character to
1014 sbon += (u.ulevel < 3) ? 1 : 0;
1025 return (sbon + dex - 14);
1028 /* damage bonus for strength */
1032 int str = ACURR(A_STR);
1044 return 2; /* up to 18 */
1045 else if (str <= STR18(75))
1046 return 3; /* up to 18/75 */
1047 else if (str <= STR18(90))
1048 return 4; /* up to 18/90 */
1049 else if (str < STR18(100))
1050 return 5; /* up to 18/99 */
1055 /* increase a towel's wetness */
1057 wet_a_towel(obj, amt, verbose)
1059 int amt; /* positive: new value; negative: increment by -amt; zero: no-op */
1062 int newspe = (amt <= 0) ? obj->spe - amt : amt;
1064 /* new state is only reported if it's an increase */
1065 if (newspe > obj->spe) {
1068 const char *wetness = (newspe < 3)
1069 ? (!obj->spe ? "damp" : "damper")
1070 : (!obj->spe ? "wet" : "wetter");
1072 const char *wetness = (newspe < 3)
1073 ? (!obj->spe ? "
\8e¼
\82Á
\82½" : "
\82³
\82ç
\82É
\8e¼
\82Á
\82½")
1074 : (!obj->spe ? "
\94G
\82ê
\82½" : "
\82³
\82ç
\82É
\94G
\82ê
\82½");
1079 pline("%s gets %s.", Yobjnam2(obj, (const char *) 0),
1082 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
1085 else if (mcarried(obj) && canseemon(obj->ocarry))
1087 pline("%s %s gets %s.", s_suffix(Monnam(obj->ocarry)),
1088 xname(obj), wetness);
1090 pline("%s
\82Ì%s
\82Í%s
\81D", Monnam(obj->ocarry),
1091 xname(obj), wetness);
1095 obj->spe = min(newspe, 7);
1097 /* if hero is wielding this towel, don't give "you begin bashing
1098 with your wet towel" message on next attack with it */
1100 unweapon = !is_wet_towel(obj);
1103 /* decrease a towel's wetness */
1105 dry_a_towel(obj, amt, verbose)
1107 int amt; /* positive: new value; negative: decrement by -amt; zero: no-op */
1110 int newspe = (amt <= 0) ? obj->spe + amt : amt;
1112 /* new state is only reported if it's a decrease */
1113 if (newspe < obj->spe) {
1117 pline("%s dries%s.", Yobjnam2(obj, (const char *) 0),
1118 !newspe ? " out" : "");
1120 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
1121 !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
1123 else if (mcarried(obj) && canseemon(obj->ocarry))
1125 pline("%s %s drie%s.", s_suffix(Monnam(obj->ocarry)),
1126 xname(obj), !newspe ? " out" : "");
1128 pline("%s
\82Ì%s
\82Í%s
\81D", Monnam(obj->ocarry),
1129 xname(obj), !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
1133 newspe = min(newspe, 7);
1134 obj->spe = max(newspe, 0);
1136 /* if hero is wielding this towel and it is now dry, give "you begin
1137 bashing with your towel" message on next attack with it */
1139 unweapon = !is_wet_towel(obj);
1142 /* copy the skill level name into the given buffer */
1144 skill_level_name(skill, buf)
1150 switch (P_SKILL(skill)) {
1155 ptr = "
\8f\89\90S
\8eÒ";
1161 ptr = "
\93ü
\96å
\8eÒ";
1167 ptr = "
\8fn
\97û
\8eÒ";
1173 ptr = "
\83G
\83L
\83X
\83p
\81[
\83g";
1175 /* these are for unarmed combat/martial arts only */
1180 ptr = "
\83}
\83X
\83^
\81[";
1182 case P_GRAND_MASTER:
1184 ptr = "Grand Master";
1186 ptr = "
\83O
\83\89\83\93\83h
\83}
\83X
\83^
\81[";
1203 return P_NAME(skill);
1206 /* return the # of slots required to advance the skill */
1208 slots_required(skill)
1211 int tmp = P_SKILL(skill);
1213 /* The more difficult the training, the more slots it takes.
1214 * unskilled -> basic 1
1215 * basic -> skilled 2
1216 * skilled -> expert 3
1218 if (skill <= P_LAST_WEAPON || skill == P_TWO_WEAPON_COMBAT)
1221 /* Fewer slots used up for unarmed or martial.
1222 * unskilled -> basic 1
1223 * basic -> skilled 1
1224 * skilled -> expert 2
1225 * expert -> master 2
1226 * master -> grand master 3
1228 return (tmp + 1) / 2;
1231 /* return true if this skill can be advanced */
1233 can_advance(skill, speedy)
1237 if (P_RESTRICTED(skill)
1238 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1239 || u.skills_advanced >= P_SKILL_LIMIT)
1242 if (wizard && speedy)
1245 return (boolean) ((int) P_ADVANCE(skill)
1246 >= practice_needed_to_advance(P_SKILL(skill))
1247 && u.weapon_slots >= slots_required(skill));
1250 /* return true if this skill could be advanced if more slots were available */
1252 could_advance(skill)
1255 if (P_RESTRICTED(skill)
1256 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1257 || u.skills_advanced >= P_SKILL_LIMIT)
1260 return (boolean) ((int) P_ADVANCE(skill)
1261 >= practice_needed_to_advance(P_SKILL(skill)));
1264 /* return true if this skill has reached its maximum and there's been enough
1265 practice to become eligible for the next step if that had been possible */
1270 if (P_RESTRICTED(skill))
1273 return (boolean) (P_SKILL(skill) >= P_MAX_SKILL(skill)
1274 && ((int) P_ADVANCE(skill)
1275 >= practice_needed_to_advance(P_SKILL(skill))));
1279 skill_advance(skill)
1282 u.weapon_slots -= slots_required(skill);
1284 u.skill_record[u.skills_advanced++] = skill;
1285 /* subtly change the advance message to indicate no more advancement */
1287 You("are now %s skilled in %s.",
1288 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more",
1291 Your("%s
\82Ì
\83X
\83L
\83\8b\82ð%s
\8d\82\82ß
\82½
\81D",
1293 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "
\8dÅ
\8d\82\82É" : "
\82³
\82ç
\82É");
1297 static const struct skill_range {
1300 } skill_ranges[] = {
1302 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "Fighting Skills" },
1304 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "
\90í
\82¢
\82Ì
\83X
\83L
\83\8b" },
1306 { P_FIRST_WEAPON, P_LAST_WEAPON, "Weapon Skills" },
1308 { P_FIRST_WEAPON, P_LAST_WEAPON, "
\95\90\8aí
\82Ì
\83X
\83L
\83\8b" },
1310 { P_FIRST_SPELL, P_LAST_SPELL, "Spellcasting Skills" },
1312 { P_FIRST_SPELL, P_LAST_SPELL, "
\96\82\96@
\82Ì
\83X
\83L
\83\8b" },
1316 * The `#enhance' extended command. What we _really_ would like is
1317 * to keep being able to pick things to advance until we couldn't any
1318 * more. This is currently not possible -- the menu code has no way
1319 * to call us back for instant action. Even if it did, we would also need
1320 * to be able to update the menu since selecting one item could make
1321 * others unselectable.
1324 enhance_weapon_skill()
1326 int pass, i, n, len, longest, to_advance, eventually_advance, maxxed_cnt;
1327 char buf[BUFSZ], sklnambuf[BUFSZ];
1329 menu_item *selected;
1332 boolean speedy = FALSE;
1334 if (wizard && yn("Advance skills without practice?") == 'y')
1338 /* find longest available skill name, count those that can advance */
1339 to_advance = eventually_advance = maxxed_cnt = 0;
1340 for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) {
1341 if (P_RESTRICTED(i))
1343 if ((len = strlen(P_NAME(i))) > longest)
1345 if (can_advance(i, speedy))
1347 else if (could_advance(i))
1348 eventually_advance++;
1349 else if (peaked_skill(i))
1353 win = create_nhwindow(NHW_MENU);
1356 /* start with a legend if any entries will be annotated
1357 with "*" or "#" below */
1358 if (eventually_advance > 0 || maxxed_cnt > 0) {
1360 if (eventually_advance > 0) {
1362 Sprintf(buf, "(Skill%s flagged by \"*\" may be enhanced %s.)",
1363 plur(eventually_advance),
1364 (u.ulevel < MAXULEV)
1365 ? "when you're more experienced"
1366 : "if skill slots become available");
1368 Sprintf(buf, "(\"*\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í%s
\8d\82\82ß
\82ç
\82ê
\82é
\81D)",
1369 (u.ulevel < MAXULEV)
1370 ? "
\82à
\82Á
\82Æ
\8co
\8c±
\82ð
\82Â
\82ß
\82Î"
1371 : "
\83X
\83L
\83\8b\83X
\83\8d\83b
\83g
\82ª
\8eg
\82¦
\82é
\82æ
\82¤
\82É
\82È
\82ê
\82Î");
1373 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1376 if (maxxed_cnt > 0) {
1379 "(Skill%s flagged by \"#\" cannot be enhanced any further.)",
1383 "(\"#\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í
\82±
\82ê
\88È
\8fã
\8d\82\82ß
\82ç
\82ê
\82È
\82¢
\81D)");
1385 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1388 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
1392 /* List the skills, making ones that could be advanced
1393 selectable. List the miscellaneous skills first.
1394 Possible future enhancement: list spell skills before
1395 weapon skills for spellcaster roles. */
1396 for (pass = 0; pass < SIZE(skill_ranges); pass++)
1397 for (i = skill_ranges[pass].first; i <= skill_ranges[pass].last;
1399 /* Print headings for skill types */
1401 if (i == skill_ranges[pass].first)
1402 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
1403 skill_ranges[pass].name, MENU_UNSELECTED);
1405 if (P_RESTRICTED(i))
1408 * Sigh, this assumes a monospaced font unless
1409 * iflags.menu_tab_sep is set in which case it puts
1410 * tabs between columns.
1411 * The 12 is the longest skill level name.
1412 * The " " is room for a selection letter and dash, "a - ".
1414 if (can_advance(i, speedy))
1415 prefix = ""; /* will be preceded by menu choice */
1416 else if (could_advance(i))
1418 else if (peaked_skill(i))
1422 (to_advance + eventually_advance + maxxed_cnt > 0)
1425 (void) skill_level_name(i, sklnambuf);
1427 if (!iflags.menu_tab_sep)
1428 Sprintf(buf, " %s%-*s %-12s %5d(%4d)", prefix,
1429 longest, P_NAME(i), sklnambuf, P_ADVANCE(i),
1430 practice_needed_to_advance(P_SKILL(i)));
1432 Sprintf(buf, " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i),
1433 sklnambuf, P_ADVANCE(i),
1434 practice_needed_to_advance(P_SKILL(i)));
1436 if (!iflags.menu_tab_sep)
1437 Sprintf(buf, " %s %-*s [%s]", prefix, longest,
1438 P_NAME(i), sklnambuf);
1440 Sprintf(buf, " %s%s\t[%s]", prefix, P_NAME(i),
1443 any.a_int = can_advance(i, speedy) ? i + 1 : 0;
1444 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1449 Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:"
1450 : "Current skills:");
1452 Strcpy(buf, (to_advance > 0) ? "
\83X
\83L
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F"
1453 : "
\8c»
\8dÝ
\82Ì
\83X
\83L
\83\8b\81F");
1455 if (wizard && !speedy)
1456 Sprintf(eos(buf), " (%d slot%s available)", u.weapon_slots,
1457 plur(u.weapon_slots));
1459 n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
1460 destroy_nhwindow(win);
1462 n = selected[0].item.a_int - 1; /* get item selected */
1463 free((genericptr_t) selected);
1465 /* check for more skills able to advance, if so then .. */
1466 for (n = i = 0; i < P_NUM_SKILLS; i++) {
1467 if (can_advance(i, speedy)) {
1470 You_feel("you could be more dangerous!");
1472 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");
1478 } while (speedy && n > 0);
1483 * Change from restricted to unrestricted, allowing P_BASIC as max. This
1484 * function may be called with with P_NONE. Used in pray.c as well as below.
1487 unrestrict_weapon_skill(skill)
1490 if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
1491 P_SKILL(skill) = P_UNSKILLED;
1492 P_MAX_SKILL(skill) = P_BASIC;
1493 P_ADVANCE(skill) = 0;
1498 use_skill(skill, degree)
1502 boolean advance_before;
1504 if (skill != P_NONE && !P_RESTRICTED(skill)) {
1505 advance_before = can_advance(skill, FALSE);
1506 P_ADVANCE(skill) += degree;
1507 if (!advance_before && can_advance(skill, FALSE))
1508 give_may_advance_msg(skill);
1514 int n; /* number of slots to gain; normally one */
1516 int i, before, after;
1518 for (i = 0, before = 0; i < P_NUM_SKILLS; i++)
1519 if (can_advance(i, FALSE))
1521 u.weapon_slots += n;
1522 for (i = 0, after = 0; i < P_NUM_SKILLS; i++)
1523 if (can_advance(i, FALSE))
1526 give_may_advance_msg(P_NONE);
1530 lose_weapon_skill(n)
1531 int n; /* number of slots to lose; normally one */
1536 /* deduct first from unused slots then from last placed one, if any */
1537 if (u.weapon_slots) {
1539 } else if (u.skills_advanced) {
1540 skill = u.skill_record[--u.skills_advanced];
1541 if (P_SKILL(skill) <= P_UNSKILLED)
1542 panic("lose_weapon_skill (%d)", skill);
1543 P_SKILL(skill)--; /* drop skill one level */
1544 /* Lost skill might have taken more than one slot; refund rest. */
1545 u.weapon_slots = slots_required(skill) - 1;
1546 /* It might now be possible to advance some other pending
1547 skill by using the refunded slots, but giving a message
1548 to that effect would seem pretty confusing.... */
1557 /* KMH -- now uses the object table */
1561 return P_BARE_HANDED_COMBAT; /* Not using a weapon */
1562 if (obj->oclass != WEAPON_CLASS && obj->oclass != TOOL_CLASS
1563 && obj->oclass != GEM_CLASS)
1564 return P_NONE; /* Not a weapon, weapon-tool, or ammo */
1565 type = objects[obj->otyp].oc_skill;
1566 return (type < 0) ? -type : type;
1573 return P_TWO_WEAPON_COMBAT;
1574 return weapon_type(uwep);
1578 * Return hit bonus/penalty based on skill of weapon.
1579 * Treat restricted weapons as unskilled.
1582 weapon_hit_bonus(weapon)
1585 int type, wep_type, skill, bonus = 0;
1586 static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
1588 wep_type = weapon_type(weapon);
1589 /* use two weapon skill only if attacking with one of the wielded weapons
1591 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1592 ? P_TWO_WEAPON_COMBAT
1594 if (type == P_NONE) {
1596 } else if (type <= P_LAST_WEAPON) {
1597 switch (P_SKILL(type)) {
1599 impossible(bad_skill, P_SKILL(type)); /* fall through */
1600 case P_ISRESTRICTED:
1614 } else if (type == P_TWO_WEAPON_COMBAT) {
1615 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1616 if (P_SKILL(wep_type) < skill)
1617 skill = P_SKILL(wep_type);
1620 impossible(bad_skill, skill); /* fall through */
1621 case P_ISRESTRICTED:
1635 } else if (type == P_BARE_HANDED_COMBAT) {
1645 bonus = P_SKILL(type);
1646 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1647 bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2;
1650 /* KMH -- It's harder to hit while you are riding */
1652 switch (P_SKILL(P_RIDING)) {
1653 case P_ISRESTRICTED:
1673 * Return damage bonus/penalty based on skill of weapon.
1674 * Treat restricted weapons as unskilled.
1677 weapon_dam_bonus(weapon)
1680 int type, wep_type, skill, bonus = 0;
1682 wep_type = weapon_type(weapon);
1683 /* use two weapon skill only if attacking with one of the wielded weapons
1685 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1686 ? P_TWO_WEAPON_COMBAT
1688 if (type == P_NONE) {
1690 } else if (type <= P_LAST_WEAPON) {
1691 switch (P_SKILL(type)) {
1693 impossible("weapon_dam_bonus: bad skill %d", P_SKILL(type));
1695 case P_ISRESTRICTED:
1709 } else if (type == P_TWO_WEAPON_COMBAT) {
1710 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1711 if (P_SKILL(wep_type) < skill)
1712 skill = P_SKILL(wep_type);
1715 case P_ISRESTRICTED:
1729 } else if (type == P_BARE_HANDED_COMBAT) {
1739 bonus = P_SKILL(type);
1740 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1741 bonus = ((bonus + 1) * (martial_bonus() ? 3 : 1)) / 2;
1744 /* KMH -- Riding gives some thrusting damage */
1745 if (u.usteed && type != P_TWO_WEAPON_COMBAT) {
1746 switch (P_SKILL(P_RIDING)) {
1747 case P_ISRESTRICTED:
1765 * Initialize weapon skill array for the game. Start by setting all
1766 * skills to restricted, then set the skill for every weapon the
1767 * hero is holding, finally reading the given array that sets
1771 skill_init(class_skill)
1772 const struct def_skill *class_skill;
1777 /* initialize skill array; by default, everything is restricted */
1778 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1779 P_SKILL(skill) = P_ISRESTRICTED;
1780 P_MAX_SKILL(skill) = P_ISRESTRICTED;
1781 P_ADVANCE(skill) = 0;
1784 /* Set skill for all weapons in inventory to be basic */
1785 for (obj = invent; obj; obj = obj->nobj) {
1786 /* don't give skill just because of carried ammo, wait until
1787 we see the relevant launcher (prevents an archeologist's
1788 touchstone from inadvertently providing skill in sling) */
1792 skill = weapon_type(obj);
1793 if (skill != P_NONE)
1794 P_SKILL(skill) = P_BASIC;
1797 /* set skills for magic */
1798 if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
1799 P_SKILL(P_HEALING_SPELL) = P_BASIC;
1800 } else if (Role_if(PM_PRIEST)) {
1801 P_SKILL(P_CLERIC_SPELL) = P_BASIC;
1802 } else if (Role_if(PM_WIZARD)) {
1803 P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1804 P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
1807 /* walk through array to set skill maximums */
1808 for (; class_skill->skill != P_NONE; class_skill++) {
1809 skmax = class_skill->skmax;
1810 skill = class_skill->skill;
1812 P_MAX_SKILL(skill) = skmax;
1813 if (P_SKILL(skill) == P_ISRESTRICTED) /* skill pre-set */
1814 P_SKILL(skill) = P_UNSKILLED;
1817 /* High potential fighters already know how to use their hands. */
1818 if (P_MAX_SKILL(P_BARE_HANDED_COMBAT) > P_EXPERT)
1819 P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
1821 /* Roles that start with a horse know how to ride it */
1822 if (urole.petnum == PM_PONY)
1823 P_SKILL(P_RIDING) = P_BASIC;
1826 * Make sure we haven't missed setting the max on a skill
1829 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1830 if (!P_RESTRICTED(skill)) {
1831 if (P_MAX_SKILL(skill) < P_SKILL(skill)) {
1832 impossible("skill_init: curr > max: %s", P_NAME(skill));
1833 P_MAX_SKILL(skill) = P_SKILL(skill);
1835 P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill) - 1);
1839 /* each role has a special spell; allow at least basic for its type
1840 (despite the function name, this works for spell skills too) */
1841 unrestrict_weapon_skill(spell_skilltype(urole.spelspec));
1845 setmnotwielded(mon, obj)
1846 register struct monst *mon;
1847 register struct obj *obj;
1851 if (artifact_light(obj) && obj->lamplit) {
1852 end_burn(obj, FALSE);
1855 pline("%s in %s %s %s shining.", The(xname(obj)),
1856 s_suffix(mon_nam(mon)), mbodypart(mon, HAND),
1857 otense(obj, "stop"));
1859 pline("%s
\82ª
\8e\9d\82Â%s
\82Ì
\8bP
\82«
\82ª
\8fÁ
\82¦
\82½
\81D",
1860 mon_nam(mon), xname(obj));
1863 if (MON_WEP(mon) == obj)
1865 obj->owornmask &= ~W_WEP;