1 /* NetHack 3.6 weapon.c $NHDT-Date: 1446078767 2015/10/29 00:32:47 $ $NHDT-Branch: master $:$NHDT-Revision: 1.55 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
11 * This module contains code for calculation of "to hit" and damage
12 * bonuses for any given weapon used, as well as weapons selection
18 /* Categories whose names don't come from OBJ_NAME(objects[type])
20 #define PN_BARE_HANDED (-1) /* includes martial arts */
21 #define PN_TWO_WEAPONS (-2)
22 #define PN_RIDING (-3)
23 #define PN_POLEARMS (-4)
25 #define PN_HAMMER (-6)
27 #define PN_ATTACK_SPELL (-8)
28 #define PN_HEALING_SPELL (-9)
29 #define PN_DIVINATION_SPELL (-10)
30 #define PN_ENCHANTMENT_SPELL (-11)
31 #define PN_CLERIC_SPELL (-12)
32 #define PN_ESCAPE_SPELL (-13)
33 #define PN_MATTER_SPELL (-14)
35 STATIC_DCL void FDECL(give_may_advance_msg, (int));
37 STATIC_VAR NEARDATA const short skill_names_indices[P_NUM_SKILLS] = {
38 0, DAGGER, KNIFE, AXE, PICK_AXE, SHORT_SWORD, BROADSWORD, LONG_SWORD,
39 TWO_HANDED_SWORD, SCIMITAR, PN_SABER, CLUB, MACE, MORNING_STAR, FLAIL,
40 PN_HAMMER, QUARTERSTAFF, PN_POLEARMS, SPEAR, TRIDENT, LANCE, BOW, SLING,
41 CROSSBOW, DART, SHURIKEN, BOOMERANG, PN_WHIP, UNICORN_HORN,
42 PN_ATTACK_SPELL, PN_HEALING_SPELL, PN_DIVINATION_SPELL,
43 PN_ENCHANTMENT_SPELL, PN_CLERIC_SPELL, PN_ESCAPE_SPELL, PN_MATTER_SPELL,
44 PN_BARE_HANDED, PN_TWO_WEAPONS, PN_RIDING
47 /* note: entry [0] isn't used */
48 STATIC_VAR NEARDATA const char *const odd_skill_names[] = {
49 "no skill", "bare hands", /* use barehands_or_martial[] instead */
50 "two weapon combat", "riding", "polearms", "saber", "hammer", "whip",
51 "attack spells", "healing spells", "divination spells",
52 "enchantment spells", "clerical spells", "escape spells", "matter spells",
54 /* indexed vis `is_martial() */
55 STATIC_VAR NEARDATA const char *const barehands_or_martial[] = {
56 "bare handed combat", "martial arts"
60 give_may_advance_msg(skill)
64 You_feel("more confident in your %sskills.",
65 skill == P_NONE ? "" : skill <= P_LAST_WEAPON
67 : skill <= P_LAST_SPELL
71 You("%s
\83X
\83L
\83\8b\82ð
\8d\82\82ß
\82é
\8e©
\90M
\82ª
\97N
\82¢
\82Ä
\82«
\82½
\81D",
72 skill == P_NONE ? "" : skill <= P_LAST_WEAPON
74 : skill <= P_LAST_SPELL
80 STATIC_DCL boolean FDECL(can_advance, (int, BOOLEAN_P));
81 STATIC_DCL boolean FDECL(could_advance, (int));
82 STATIC_DCL boolean FDECL(peaked_skill, (int));
83 STATIC_DCL int FDECL(slots_required, (int));
84 STATIC_DCL char *FDECL(skill_level_name, (int, char *));
85 STATIC_DCL void FDECL(skill_advance, (int));
87 #define P_NAME(type) \
88 ((skill_names_indices[type] > 0) \
89 ? OBJ_NAME(objects[skill_names_indices[type]]) \
90 : (type == P_BARE_HANDED_COMBAT) \
91 ? barehands_or_martial[martial_bonus()] \
92 : odd_skill_names[-skill_names_indices[type]])
94 static NEARDATA const char kebabable[] = { S_XORN, S_DRAGON, S_JABBERWOCK,
95 S_NAGA, S_GIANT, '\0' };
97 /* weapon's skill category name for use as generalized description of weapon;
98 mostly used to shorten "you drop your <weapon>" messages when slippery
99 fingers or polymorph causes hero to involuntarily drop wielded weapon(s) */
104 int skill = weapon_type(obj);
105 const char *descr = P_NAME(skill);
107 /* assorted special cases */
110 /* not a weapon or weptool: use item class name;
111 override class name "food" for corpses, tins, and eggs,
112 "large rock" for statues and boulders, and "tool" for towels */
113 descr = (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG
114 || obj->otyp == STATUE || obj->otyp == BOULDER
115 || obj->otyp == TOWEL)
116 ? OBJ_NAME(objects[obj->otyp])
117 : def_oc_syms[(int) obj->oclass].name;
121 descr = (obj->otyp == ROCK || is_graystone(obj))
126 /* avoid "rock"; what about known glass? */
127 : (obj->oclass == GEM_CLASS)
132 /* in case somebody adds odd sling ammo */
133 : def_oc_syms[(int) obj->oclass].name;
147 descr = "
\83{
\83\8b\83g";
150 if (obj->otyp == GRAPPLING_HOOK)
154 descr = "
\83t
\83b
\83N";
157 /* even if "dwarvish mattock" hasn't been discovered yet */
158 if (obj->otyp == DWARVISH_MATTOCK)
162 descr = "
\82Â
\82é
\82Í
\82µ";
167 return makesingular(descr);
171 * hitval returns an integer representing the "to hit" bonuses
172 * of "otmp" against the monster.
180 struct permonst *ptr = mon->data;
181 boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
186 /* Put weapon specific "to hit" bonuses in below: */
187 tmp += objects[otmp->otyp].oc_hitbon;
189 /* Put weapon vs. monster type "to hit" bonuses in below: */
191 /* Blessed weapons used against undead or demons */
192 if (Is_weapon && otmp->blessed
193 && (is_demon(ptr) || is_undead(ptr) || is_vampshifter(mon)))
196 if (is_spear(otmp) && index(kebabable, ptr->mlet))
199 /* trident is highly effective against swimmers */
200 if (otmp->otyp == TRIDENT && is_swimmer(ptr)) {
201 if (is_pool(mon->mx, mon->my))
203 else if (ptr->mlet == S_EEL || ptr->mlet == S_SNAKE)
207 /* Picks used against xorns and earth elementals */
208 if (is_pick(otmp) && (passes_walls(ptr) && thick_skinned(ptr)))
211 /* Check specially named weapon "to hit" bonuses */
213 tmp += spec_abon(otmp, mon);
218 /* Historical note: The original versions of Hack used a range of damage
219 * which was similar to, but not identical to the damage used in Advanced
220 * Dungeons and Dragons. I figured that since it was so close, I may as well
221 * make it exactly the same as AD&D, adding some more weapons in the process.
222 * This has the advantage that it is at least possible that the player would
223 * already know the damage of at least some of the weapons. This was circa
224 * 1987 and I used the table from Unearthed Arcana until I got tired of typing
225 * them in (leading to something of an imbalance towards weapons early in
226 * alphabetical order). The data structure still doesn't include fields that
227 * fully allow the appropriate damage to be described (there's no way to say
228 * 3d6 or 1d6+1) so we add on the extra damage in dmgval() if the weapon
229 * doesn't do an exact die of damage.
231 * Of course new weapons were added later in the development of Nethack. No
232 * AD&D consistency was kept, but most of these don't exist in AD&D anyway.
234 * Second edition AD&D came out a few years later; luckily it used the same
235 * table. As of this writing (1999), third edition is in progress but not
236 * released. Let's see if the weapon table stays the same. --KAA
237 * October 2000: It didn't. Oh, well.
241 * dmgval returns an integer representing the damage bonuses
242 * of "otmp" against the monster.
249 int tmp = 0, otyp = otmp->otyp;
250 struct permonst *ptr = mon->data;
251 boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
253 if (otyp == CREAM_PIE)
257 if (objects[otyp].oc_wldam)
258 tmp = rnd(objects[otyp].oc_wldam);
265 case ELVEN_BROADSWORD:
289 case DWARVISH_MATTOCK:
290 case TWO_HANDED_SWORD:
295 if (objects[otyp].oc_wsdam)
296 tmp = rnd(objects[otyp].oc_wsdam);
316 case ELVEN_BROADSWORD:
329 /* negative enchantment mustn't produce negative damage */
334 if (objects[otyp].oc_material <= LEATHER && thick_skinned(ptr))
335 /* thick skinned/scaled creatures don't feel it */
337 if (ptr == &mons[PM_SHADE] && !shade_glare(otmp))
340 /* "very heavy iron ball"; weight increase is in increments of 160 */
341 if (otyp == HEAVY_IRON_BALL && tmp > 0) {
342 int wt = (int) objects[HEAVY_IRON_BALL].oc_weight;
344 if ((int) otmp->owt > wt) {
345 wt = ((int) otmp->owt - wt) / 160;
348 tmp = 25; /* objects[].oc_wldam */
352 /* Put weapon vs. monster type damage bonuses in below: */
353 if (Is_weapon || otmp->oclass == GEM_CLASS || otmp->oclass == BALL_CLASS
354 || otmp->oclass == CHAIN_CLASS) {
358 && (is_undead(ptr) || is_demon(ptr) || is_vampshifter(mon)))
360 if (is_axe(otmp) && is_wooden(ptr))
362 if (objects[otyp].oc_material == SILVER && mon_hates_silver(mon))
365 /* if the weapon is going to get a double damage bonus, adjust
366 this bonus so that effectively it's added after the doubling */
367 if (bonus > 1 && otmp->oartifact && spec_dbon(otmp, mon, 25) >= 25)
368 bonus = (bonus + 1) / 2;
374 /* It's debatable whether a rusted blunt instrument
375 should do less damage than a pristine one, since
376 it will hit with essentially the same impact, but
377 there ought to some penalty for using damaged gear
378 so always subtract erosion even for blunt weapons. */
379 tmp -= greatest_erosion(otmp);
387 STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int));
389 if ((otmp = oselect(mtmp, x)) != 0) \
392 STATIC_OVL struct obj *
399 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
401 /* never select non-cockatrice corpses */
402 && !((x == CORPSE || x == EGG)
403 && !touch_petrifies(&mons[otmp->corpsenm]))
404 && (!otmp->oartifact || touch_artifact(otmp, mtmp)))
407 return (struct obj *) 0;
410 static NEARDATA const int rwep[] = {
411 DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
412 SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
413 CROSSBOW_BOLT, SILVER_DAGGER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE,
414 FLINT, ROCK, LOADSTONE, LUCKSTONE, DART,
415 /* BOOMERANG, */ CREAM_PIE
418 static NEARDATA const int pwep[] = { HALBERD, BARDICHE, SPETUM,
419 BILL_GUISARME, VOULGE, RANSEUR,
420 GUISARME, GLAIVE, LUCERN_HAMMER,
421 BEC_DE_CORBIN, FAUCHARD, PARTISAN,
424 static struct obj *propellor;
426 /* select a ranged weapon for the monster */
429 register struct monst *mtmp;
431 register struct obj *otmp;
436 char mlet = mtmp->data->mlet;
438 propellor = &zeroobj;
439 Oselect(EGG); /* cockatrice egg */
440 if (mlet == S_KOP) /* pies are first choice for Kops */
442 if (throws_rocks(mtmp->data)) /* ...boulders for giants */
445 /* Select polearms first; they do more damage and aren't expendable.
446 But don't pick one if monster's weapon is welded, because then
447 we'd never have a chance to throw non-wielding missiles. */
448 /* The limit of 13 here is based on the monster polearm range limit
449 * (defined as 5 in mthrowu.c). 5 corresponds to a distance of 2 in
450 * one direction and 1 in another; one space beyond that would be 3 in
451 * one direction and 2 in another; 3^2+2^2=13.
453 mwep = MON_WEP(mtmp);
454 /* NO_WEAPON_WANTED means we already tried to wield and failed */
455 mweponly = (mwelded(mwep) && mtmp->weapon_check == NO_WEAPON_WANTED);
456 if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 13
457 && couldsee(mtmp->mx, mtmp->my)) {
458 for (i = 0; i < SIZE(pwep); i++) {
459 /* Only strong monsters can wield big (esp. long) weapons.
460 * Big weapon is basically the same as bimanual.
461 * All monsters can wield the remaining weapons.
463 if (((strongmonst(mtmp->data)
464 && (mtmp->misc_worn_check & W_ARMS) == 0)
465 || !objects[pwep[i]].oc_bimanual)
466 && (objects[pwep[i]].oc_material != SILVER
467 || !mon_hates_silver(mtmp))) {
468 if ((otmp = oselect(mtmp, pwep[i])) != 0
469 && (otmp == mwep || !mweponly)) {
470 propellor = otmp; /* force the monster to wield it */
478 * other than these two specific cases, always select the
479 * most potent ranged weapon to hand.
481 for (i = 0; i < SIZE(rwep); i++) {
484 /* shooting gems from slings; this goes just before the darts */
485 /* (shooting rocks is already handled via the rwep[] ordering) */
486 if (rwep[i] == DART && !likes_gems(mtmp->data)
487 && m_carrying(mtmp, SLING)) { /* propellor */
488 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
489 if (otmp->oclass == GEM_CLASS
490 && (otmp->otyp != LOADSTONE || !otmp->cursed)) {
491 propellor = m_carrying(mtmp, SLING);
496 /* KMH -- This belongs here so darts will work */
497 propellor = &zeroobj;
499 prop = (objects[rwep[i]]).oc_skill;
503 propellor = (oselect(mtmp, YUMI));
505 propellor = (oselect(mtmp, ELVEN_BOW));
507 propellor = (oselect(mtmp, BOW));
509 propellor = (oselect(mtmp, ORCISH_BOW));
512 propellor = (oselect(mtmp, SLING));
515 propellor = (oselect(mtmp, CROSSBOW));
517 if ((otmp = MON_WEP(mtmp)) && mwelded(otmp) && otmp != propellor
518 && mtmp->weapon_check == NO_WEAPON_WANTED)
521 /* propellor = obj, propellor to use
522 * propellor = &zeroobj, doesn't need a propellor
523 * propellor = 0, needed one and didn't have one
525 if (propellor != 0) {
526 /* Note: cannot use m_carrying for loadstones, since it will
527 * always select the first object of a type, and maybe the
528 * monster is carrying two but only the first is unthrowable.
530 if (rwep[i] != LOADSTONE) {
531 /* Don't throw a cursed weapon-in-hand or an artifact */
532 if ((otmp = oselect(mtmp, rwep[i])) && !otmp->oartifact
533 && !(otmp == MON_WEP(mtmp) && mwelded(otmp)))
536 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
537 if (otmp->otyp == LOADSTONE && !otmp->cursed)
544 return (struct obj *) 0;
547 /* Weapons in order of preference */
548 static const NEARDATA short hwep[] = {
549 CORPSE, /* cockatrice corpse */
550 TSURUGI, RUNESWORD, DWARVISH_MATTOCK, TWO_HANDED_SWORD, BATTLE_AXE,
551 KATANA, UNICORN_HORN, CRYSKNIFE, TRIDENT, LONG_SWORD, ELVEN_BROADSWORD,
552 BROADSWORD, SCIMITAR, SILVER_SABER, MORNING_STAR, ELVEN_SHORT_SWORD,
553 DWARVISH_SHORT_SWORD, SHORT_SWORD, ORCISH_SHORT_SWORD, MACE, AXE,
554 DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, FLAIL,
555 BULLWHIP, QUARTERSTAFF, JAVELIN, AKLYS, CLUB, PICK_AXE, RUBBER_HOSE,
556 WAR_HAMMER, SILVER_DAGGER, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, ATHAME,
557 SCALPEL, KNIFE, WORM_TOOTH
560 /* select a hand to hand weapon for the monster */
563 register struct monst *mtmp;
565 register struct obj *otmp;
567 boolean strong = strongmonst(mtmp->data);
568 boolean wearing_shield = (mtmp->misc_worn_check & W_ARMS) != 0;
570 /* prefer artifacts to everything else */
571 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
572 if (otmp->oclass == WEAPON_CLASS && otmp->oartifact
573 && touch_artifact(otmp, mtmp)
574 && ((strong && !wearing_shield)
575 || !objects[otmp->otyp].oc_bimanual))
579 if (is_giant(mtmp->data)) /* giants just love to use clubs */
582 /* only strong monsters can wield big (esp. long) weapons */
583 /* big weapon is basically the same as bimanual */
584 /* all monsters can wield the remaining weapons */
585 for (i = 0; i < SIZE(hwep); i++) {
586 if (hwep[i] == CORPSE && !(mtmp->misc_worn_check & W_ARMG)
587 && !resists_ston(mtmp))
589 if (((strong && !wearing_shield) || !objects[hwep[i]].oc_bimanual)
590 && (objects[hwep[i]].oc_material != SILVER
591 || !mon_hates_silver(mtmp)))
596 return (struct obj *) 0;
599 /* Called after polymorphing a monster, robbing it, etc.... Monsters
600 * otherwise never unwield stuff on their own. Might print message.
603 possibly_unwield(mon, polyspot)
607 struct obj *obj, *mw_tmp;
609 if (!(mw_tmp = MON_WEP(mon)))
611 for (obj = mon->minvent; obj; obj = obj->nobj)
614 if (!obj) { /* The weapon was stolen or destroyed */
616 mon->weapon_check = NEED_WEAPON;
619 if (!attacktype(mon->data, AT_WEAP)) {
620 setmnotwielded(mon, mw_tmp);
621 mon->weapon_check = NO_WEAPON_WANTED;
622 obj_extract_self(obj);
623 if (cansee(mon->mx, mon->my)) {
625 pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
627 pline("%s
\82Í%s
\82ð
\92u
\82¢
\82½
\81D", Monnam(mon), distant_name(obj, doname));
628 newsym(mon->mx, mon->my);
630 /* might be dropping object into water or lava */
632 if (!flooreffects(obj, mon->mx, mon->my, "drop")) {
634 if (!flooreffects(obj, mon->mx, mon->my, "
\97\8e\82¿
\82é")) {
637 place_object(obj, mon->mx, mon->my);
642 /* The remaining case where there is a change is where a monster
643 * is polymorphed into a stronger/weaker monster with a different
644 * choice of weapons. This has no parallel for players. It can
645 * be handled by waiting until mon_wield_item is actually called.
646 * Though the monster still wields the wrong weapon until then,
647 * this is OK since the player can't see it. (FIXME: Not okay since
648 * probing can reveal it.)
649 * Note that if there is no change, setting the check to NEED_WEAPON
651 * Possible problem: big monster with big cursed weapon gets
652 * polymorphed into little monster. But it's not quite clear how to
653 * handle this anyway....
655 if (!(mwelded(mw_tmp) && mon->weapon_check == NO_WEAPON_WANTED))
656 mon->weapon_check = NEED_WEAPON;
660 /* Let a monster try to wield a weapon, based on mon->weapon_check.
661 * Returns 1 if the monster took time to do it, 0 if it did not.
665 register struct monst *mon;
669 /* This case actually should never happen */
670 if (mon->weapon_check == NO_WEAPON_WANTED)
672 switch (mon->weapon_check) {
673 case NEED_HTH_WEAPON:
674 obj = select_hwep(mon);
676 case NEED_RANGED_WEAPON:
677 (void) select_rwep(mon);
681 obj = m_carrying(mon, PICK_AXE);
682 /* KMH -- allow other picks */
683 if (!obj && !which_armor(mon, W_ARMS))
684 obj = m_carrying(mon, DWARVISH_MATTOCK);
687 /* currently, only 2 types of axe */
688 obj = m_carrying(mon, BATTLE_AXE);
689 if (!obj || which_armor(mon, W_ARMS))
690 obj = m_carrying(mon, AXE);
692 case NEED_PICK_OR_AXE:
693 /* prefer pick for fewer switches on most levels */
694 obj = m_carrying(mon, DWARVISH_MATTOCK);
696 obj = m_carrying(mon, BATTLE_AXE);
697 if (!obj || which_armor(mon, W_ARMS)) {
698 obj = m_carrying(mon, PICK_AXE);
700 obj = m_carrying(mon, AXE);
704 impossible("weapon_check %d for %s?", mon->weapon_check,
708 if (obj && obj != &zeroobj) {
709 struct obj *mw_tmp = MON_WEP(mon);
710 if (mw_tmp && mw_tmp->otyp == obj->otyp) {
711 /* already wielding it */
712 mon->weapon_check = NEED_WEAPON;
715 /* Actually, this isn't necessary--as soon as the monster
716 * wields the weapon, the weapon welds itself, so the monster
717 * can know it's cursed and needn't even bother trying.
720 if (mw_tmp && mwelded(mw_tmp)) {
721 if (canseemon(mon)) {
722 char welded_buf[BUFSZ];
723 const char *mon_hand = mbodypart(mon, HAND);
725 if (bimanual(mw_tmp))
726 mon_hand = makeplural(mon_hand);
728 Sprintf(welded_buf, "%s welded to %s %s",
729 otense(mw_tmp, "are"), mhis(mon), mon_hand);
732 if (obj->otyp == PICK_AXE) {
734 pline("Since %s weapon%s %s,", s_suffix(mon_nam(mon)),
735 plur(mw_tmp->quan), welded_buf);
737 pline("%s
\82Í
\95\90\8aí
\82ð
\8eè
\82É
\82µ
\82æ
\82¤
\82Æ
\82µ
\82½
\82ª
\81C", mon_nam(mon));
740 pline("%s cannot wield that %s.", mon_nam(mon),
743 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82Å
\82«
\82È
\82©
\82Á
\82½
\81D", mon_nam(mon),
748 pline("%s tries to wield %s.", Monnam(mon), doname(obj));
750 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82µ
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", Monnam(mon), doname(obj));
752 pline("%s %s!", Yname2(mw_tmp), welded_buf);
754 pline("%s
\82Í%s
\82ð
\8eè
\82É
\82µ
\82½
\81I", Monnam(mon), xname(mw_tmp));
758 mon->weapon_check = NO_WEAPON_WANTED;
761 mon->mw = obj; /* wield obj */
762 setmnotwielded(mon, mw_tmp);
763 mon->weapon_check = NEED_WEAPON;
764 if (canseemon(mon)) {
766 pline("%s wields %s!", Monnam(mon), doname(obj));
768 pline("%s
\82Í%s
\82ð
\91\95\94õ
\82µ
\82½
\81I", Monnam(mon), doname(obj));
769 if (mwelded(mw_tmp)) {
771 pline("%s %s to %s %s!", Tobjnam(obj, "weld"),
772 is_plural(obj) ? "themselves" : "itself",
773 s_suffix(mon_nam(mon)), mbodypart(mon, HAND));
775 pline("%s
\82Í
\8f\9f\8eè
\82É%s
\82Ì%s
\82É
\91\95\94õ
\82³
\82ê
\82½
\81I",
777 mon_nam(mon), mbodypart(mon, HAND));
782 if (artifact_light(obj) && !obj->lamplit) {
783 begin_burn(obj, FALSE);
786 pline("%s %s in %s %s!", Tobjnam(obj, "shine"),
787 arti_light_description(obj), s_suffix(mon_nam(mon)),
788 mbodypart(mon, HAND));
790 pline("%s
\82Í%s
\82Ì%s
\82Ì
\92\86\82Å%s
\8bP
\82¢
\82½
\81I",
791 xname(obj), mon_nam(mon),
792 mbodypart(mon, HAND), arti_light_description(obj));
795 obj->owornmask = W_WEP;
798 mon->weapon_check = NEED_WEAPON;
802 /* force monster to stop wielding current weapon, if any */
807 struct obj *mwep = MON_WEP(mon);
810 setmnotwielded(mon, mwep);
811 mon->weapon_check = NEED_WEAPON;
815 /* attack bonus for strength & dexterity */
820 int str = ACURR(A_STR), dex = ACURR(A_DEX);
823 return (adj_lev(&mons[u.umonnum]) - 3);
830 else if (str <= STR18(50))
831 sbon = 1; /* up to 18/50 */
832 else if (str < STR18(100))
837 /* Game tuning kludge: make it a bit easier for a low level character to
839 sbon += (u.ulevel < 3) ? 1 : 0;
850 return (sbon + dex - 14);
853 /* damage bonus for strength */
857 int str = ACURR(A_STR);
869 return 2; /* up to 18 */
870 else if (str <= STR18(75))
871 return 3; /* up to 18/75 */
872 else if (str <= STR18(90))
873 return 4; /* up to 18/90 */
874 else if (str < STR18(100))
875 return 5; /* up to 18/99 */
880 /* increase a towel's wetness */
882 wet_a_towel(obj, amt, verbose)
884 int amt; /* positive: new value; negative: increment by -amt; zero: no-op */
887 int newspe = (amt <= 0) ? obj->spe - amt : amt;
889 /* new state is only reported if it's an increase */
890 if (newspe > obj->spe) {
893 const char *wetness = (newspe < 3)
894 ? (!obj->spe ? "damp" : "damper")
895 : (!obj->spe ? "wet" : "wetter");
897 const char *wetness = (newspe < 3)
898 ? (!obj->spe ? "
\8e¼
\82Á
\82½" : "
\82³
\82ç
\82É
\8e¼
\82Á
\82½")
899 : (!obj->spe ? "
\94G
\82ê
\82½" : "
\82³
\82ç
\82É
\94G
\82ê
\82½");
904 pline("%s gets %s.", Yobjnam2(obj, (const char *) 0),
907 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
910 else if (mcarried(obj) && canseemon(obj->ocarry))
912 pline("%s %s gets %s.", s_suffix(Monnam(obj->ocarry)),
913 xname(obj), wetness);
915 pline("%s%s
\82Í%s
\81D", s_suffix(Monnam(obj->ocarry)),
916 xname(obj), wetness);
920 obj->spe = min(newspe, 7);
922 /* if hero is wielding this towel, don't give "you begin bashing
923 with your wet towel" message on next attack with it */
925 unweapon = !is_wet_towel(obj);
928 /* decrease a towel's wetness */
930 dry_a_towel(obj, amt, verbose)
932 int amt; /* positive: new value; negative: decrement by -amt; zero: no-op */
935 int newspe = (amt <= 0) ? obj->spe + amt : amt;
937 /* new state is only reported if it's a decrease */
938 if (newspe < obj->spe) {
942 pline("%s dries%s.", Yobjnam2(obj, (const char *) 0),
943 !newspe ? " out" : "");
945 pline("%s
\82Í%s
\81D", Yobjnam2(obj, (const char *) 0),
946 !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
948 else if (mcarried(obj) && canseemon(obj->ocarry))
950 pline("%s %s drie%s.", s_suffix(Monnam(obj->ocarry)),
951 xname(obj), !newspe ? " out" : "");
953 pline("%s%s
\82Í%s
\81D", s_suffix(Monnam(obj->ocarry)),
954 xname(obj), !newspe ? "
\8a£
\82«
\82«
\82Á
\82½" : "
\8a£
\82¢
\82½");
958 newspe = min(newspe, 7);
959 obj->spe = max(newspe, 0);
961 /* if hero is wielding this towel and it is now dry, give "you begin
962 bashing with your towel" message on next attack with it */
964 unweapon = !is_wet_towel(obj);
967 /* copy the skill level name into the given buffer */
969 skill_level_name(skill, buf)
975 switch (P_SKILL(skill)) {
980 ptr = "
\8f\89\90S
\8eÒ";
986 ptr = "
\93ü
\96å
\8eÒ";
992 ptr = "
\8fn
\97û
\8eÒ";
998 ptr = "
\83G
\83L
\83X
\83p
\81[
\83g";
1000 /* these are for unarmed combat/martial arts only */
1005 ptr = "
\83}
\83X
\83^
\81[";
1007 case P_GRAND_MASTER:
1009 ptr = "Grand Master";
1011 ptr = "
\83O
\83\89\83\93\83h
\83}
\83X
\83^
\81[";
1024 /* return the # of slots required to advance the skill */
1026 slots_required(skill)
1029 int tmp = P_SKILL(skill);
1031 /* The more difficult the training, the more slots it takes.
1032 * unskilled -> basic 1
1033 * basic -> skilled 2
1034 * skilled -> expert 3
1036 if (skill <= P_LAST_WEAPON || skill == P_TWO_WEAPON_COMBAT)
1039 /* Fewer slots used up for unarmed or martial.
1040 * unskilled -> basic 1
1041 * basic -> skilled 1
1042 * skilled -> expert 2
1043 * expert -> master 2
1044 * master -> grand master 3
1046 return (tmp + 1) / 2;
1049 /* return true if this skill can be advanced */
1052 can_advance(skill, speedy)
1056 if (P_RESTRICTED(skill)
1057 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1058 || u.skills_advanced >= P_SKILL_LIMIT)
1061 if (wizard && speedy)
1064 return (boolean) ((int) P_ADVANCE(skill)
1065 >= practice_needed_to_advance(P_SKILL(skill))
1066 && u.weapon_slots >= slots_required(skill));
1069 /* return true if this skill could be advanced if more slots were available */
1071 could_advance(skill)
1074 if (P_RESTRICTED(skill)
1075 || P_SKILL(skill) >= P_MAX_SKILL(skill)
1076 || u.skills_advanced >= P_SKILL_LIMIT)
1079 return (boolean) ((int) P_ADVANCE(skill)
1080 >= practice_needed_to_advance(P_SKILL(skill)));
1083 /* return true if this skill has reached its maximum and there's been enough
1084 practice to become eligible for the next step if that had been possible */
1089 if (P_RESTRICTED(skill))
1092 return (boolean) (P_SKILL(skill) >= P_MAX_SKILL(skill)
1093 && ((int) P_ADVANCE(skill)
1094 >= practice_needed_to_advance(P_SKILL(skill))));
1098 skill_advance(skill)
1101 u.weapon_slots -= slots_required(skill);
1103 u.skill_record[u.skills_advanced++] = skill;
1104 /* subtly change the advance message to indicate no more advancement */
1106 You("are now %s skilled in %s.",
1107 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more",
1110 Your("%s
\82Ì
\83X
\83L
\83\8b\82ð%s
\8d\82\82ß
\82½
\81D",
1112 P_SKILL(skill) >= P_MAX_SKILL(skill) ? "
\8dÅ
\8d\82\82É" : "
\82³
\82ç
\82É");
1116 static const struct skill_range {
1119 } skill_ranges[] = {
1121 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "Fighting Skills" },
1123 { P_FIRST_H_TO_H, P_LAST_H_TO_H, "
\90í
\82¢
\82Ì
\83X
\83L
\83\8b" },
1125 { P_FIRST_WEAPON, P_LAST_WEAPON, "Weapon Skills" },
1127 { P_FIRST_WEAPON, P_LAST_WEAPON, "
\95\90\8aí
\82Ì
\83X
\83L
\83\8b" },
1129 { P_FIRST_SPELL, P_LAST_SPELL, "Spellcasting Skills" },
1131 { P_FIRST_SPELL, P_LAST_SPELL, "
\96\82\96@
\82Ì
\83X
\83L
\83\8b" },
1135 * The `#enhance' extended command. What we _really_ would like is
1136 * to keep being able to pick things to advance until we couldn't any
1137 * more. This is currently not possible -- the menu code has no way
1138 * to call us back for instant action. Even if it did, we would also need
1139 * to be able to update the menu since selecting one item could make
1140 * others unselectable.
1143 enhance_weapon_skill()
1145 int pass, i, n, len, longest, to_advance, eventually_advance, maxxed_cnt;
1146 char buf[BUFSZ], sklnambuf[BUFSZ];
1148 menu_item *selected;
1151 boolean speedy = FALSE;
1153 if (wizard && yn("Advance skills without practice?") == 'y')
1157 /* find longest available skill name, count those that can advance */
1158 to_advance = eventually_advance = maxxed_cnt = 0;
1159 for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) {
1160 if (P_RESTRICTED(i))
1162 if ((len = strlen(P_NAME(i))) > longest)
1164 if (can_advance(i, speedy))
1166 else if (could_advance(i))
1167 eventually_advance++;
1168 else if (peaked_skill(i))
1172 win = create_nhwindow(NHW_MENU);
1175 /* start with a legend if any entries will be annotated
1176 with "*" or "#" below */
1177 if (eventually_advance > 0 || maxxed_cnt > 0) {
1179 if (eventually_advance > 0) {
1181 Sprintf(buf, "(Skill%s flagged by \"*\" may be enhanced %s.)",
1182 plur(eventually_advance),
1183 (u.ulevel < MAXULEV)
1184 ? "when you're more experienced"
1185 : "if skill slots become available");
1187 Sprintf(buf, "(\"*\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í%s
\8d\82\82ß
\82ç
\82ê
\82é
\81D)",
1188 (u.ulevel < MAXULEV)
1189 ? "
\82à
\82Á
\82Æ
\8co
\8c±
\82ð
\82Â
\82ß
\82Î"
1190 : "
\83X
\83L
\83\8b\83X
\83\8d\83b
\83g
\82ª
\8eg
\82¦
\82é
\82æ
\82¤
\82É
\82È
\82ê
\82Î");
1192 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1195 if (maxxed_cnt > 0) {
1198 "(Skill%s flagged by \"#\" cannot be enhanced any further.)",
1202 "(\"#\"
\82ª
\82Â
\82¢
\82Ä
\82¢
\82é
\83X
\83L
\83\8b\82Í
\82±
\82ê
\88È
\8fã
\8d\82\82ß
\82ç
\82ê
\82È
\82¢
\81D)");
1204 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1207 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
1211 /* List the skills, making ones that could be advanced
1212 selectable. List the miscellaneous skills first.
1213 Possible future enhancement: list spell skills before
1214 weapon skills for spellcaster roles. */
1215 for (pass = 0; pass < SIZE(skill_ranges); pass++)
1216 for (i = skill_ranges[pass].first; i <= skill_ranges[pass].last;
1218 /* Print headings for skill types */
1220 if (i == skill_ranges[pass].first)
1221 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
1222 skill_ranges[pass].name, MENU_UNSELECTED);
1224 if (P_RESTRICTED(i))
1227 * Sigh, this assumes a monospaced font unless
1228 * iflags.menu_tab_sep is set in which case it puts
1229 * tabs between columns.
1230 * The 12 is the longest skill level name.
1231 * The " " is room for a selection letter and dash, "a - ".
1233 if (can_advance(i, speedy))
1234 prefix = ""; /* will be preceded by menu choice */
1235 else if (could_advance(i))
1237 else if (peaked_skill(i))
1241 (to_advance + eventually_advance + maxxed_cnt > 0)
1244 (void) skill_level_name(i, sklnambuf);
1246 if (!iflags.menu_tab_sep)
1247 Sprintf(buf, " %s%-*s %-12s %5d(%4d)", prefix,
1248 longest, P_NAME(i), sklnambuf, P_ADVANCE(i),
1249 practice_needed_to_advance(P_SKILL(i)));
1251 Sprintf(buf, " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i),
1252 sklnambuf, P_ADVANCE(i),
1253 practice_needed_to_advance(P_SKILL(i)));
1255 if (!iflags.menu_tab_sep)
1256 Sprintf(buf, " %s %-*s [%s]", prefix, longest,
1257 P_NAME(i), sklnambuf);
1259 Sprintf(buf, " %s%s\t[%s]", prefix, P_NAME(i),
1262 any.a_int = can_advance(i, speedy) ? i + 1 : 0;
1263 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
1268 Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:"
1269 : "Current skills:");
1271 Strcpy(buf, (to_advance > 0) ? "
\83X
\83L
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F"
1272 : "
\8c»
\8dÝ
\82Ì
\83X
\83L
\83\8b\81F");
1274 if (wizard && !speedy)
1275 Sprintf(eos(buf), " (%d slot%s available)", u.weapon_slots,
1276 plur(u.weapon_slots));
1278 n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
1279 destroy_nhwindow(win);
1281 n = selected[0].item.a_int - 1; /* get item selected */
1282 free((genericptr_t) selected);
1284 /* check for more skills able to advance, if so then .. */
1285 for (n = i = 0; i < P_NUM_SKILLS; i++) {
1286 if (can_advance(i, speedy)) {
1289 You_feel("you could be more dangerous!");
1291 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");
1297 } while (speedy && n > 0);
1302 * Change from restricted to unrestricted, allowing P_BASIC as max. This
1303 * function may be called with with P_NONE. Used in pray.c.
1306 unrestrict_weapon_skill(skill)
1309 if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
1310 P_SKILL(skill) = P_UNSKILLED;
1311 P_MAX_SKILL(skill) = P_BASIC;
1312 P_ADVANCE(skill) = 0;
1317 use_skill(skill, degree)
1321 boolean advance_before;
1323 if (skill != P_NONE && !P_RESTRICTED(skill)) {
1324 advance_before = can_advance(skill, FALSE);
1325 P_ADVANCE(skill) += degree;
1326 if (!advance_before && can_advance(skill, FALSE))
1327 give_may_advance_msg(skill);
1333 int n; /* number of slots to gain; normally one */
1335 int i, before, after;
1337 for (i = 0, before = 0; i < P_NUM_SKILLS; i++)
1338 if (can_advance(i, FALSE))
1340 u.weapon_slots += n;
1341 for (i = 0, after = 0; i < P_NUM_SKILLS; i++)
1342 if (can_advance(i, FALSE))
1345 give_may_advance_msg(P_NONE);
1349 lose_weapon_skill(n)
1350 int n; /* number of slots to lose; normally one */
1355 /* deduct first from unused slots then from last placed one, if any */
1356 if (u.weapon_slots) {
1358 } else if (u.skills_advanced) {
1359 skill = u.skill_record[--u.skills_advanced];
1360 if (P_SKILL(skill) <= P_UNSKILLED)
1361 panic("lose_weapon_skill (%d)", skill);
1362 P_SKILL(skill)--; /* drop skill one level */
1363 /* Lost skill might have taken more than one slot; refund rest. */
1364 u.weapon_slots = slots_required(skill) - 1;
1365 /* It might now be possible to advance some other pending
1366 skill by using the refunded slots, but giving a message
1367 to that effect would seem pretty confusing.... */
1376 /* KMH -- now uses the object table */
1380 return P_BARE_HANDED_COMBAT; /* Not using a weapon */
1381 if (obj->oclass != WEAPON_CLASS && obj->oclass != TOOL_CLASS
1382 && obj->oclass != GEM_CLASS)
1383 return P_NONE; /* Not a weapon, weapon-tool, or ammo */
1384 type = objects[obj->otyp].oc_skill;
1385 return (type < 0) ? -type : type;
1392 return P_TWO_WEAPON_COMBAT;
1393 return weapon_type(uwep);
1397 * Return hit bonus/penalty based on skill of weapon.
1398 * Treat restricted weapons as unskilled.
1401 weapon_hit_bonus(weapon)
1404 int type, wep_type, skill, bonus = 0;
1405 static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
1407 wep_type = weapon_type(weapon);
1408 /* use two weapon skill only if attacking with one of the wielded weapons
1410 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1411 ? P_TWO_WEAPON_COMBAT
1413 if (type == P_NONE) {
1415 } else if (type <= P_LAST_WEAPON) {
1416 switch (P_SKILL(type)) {
1418 impossible(bad_skill, P_SKILL(type)); /* fall through */
1419 case P_ISRESTRICTED:
1433 } else if (type == P_TWO_WEAPON_COMBAT) {
1434 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1435 if (P_SKILL(wep_type) < skill)
1436 skill = P_SKILL(wep_type);
1439 impossible(bad_skill, skill); /* fall through */
1440 case P_ISRESTRICTED:
1454 } else if (type == P_BARE_HANDED_COMBAT) {
1464 bonus = P_SKILL(type);
1465 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1466 bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2;
1469 /* KMH -- It's harder to hit while you are riding */
1471 switch (P_SKILL(P_RIDING)) {
1472 case P_ISRESTRICTED:
1492 * Return damage bonus/penalty based on skill of weapon.
1493 * Treat restricted weapons as unskilled.
1496 weapon_dam_bonus(weapon)
1499 int type, wep_type, skill, bonus = 0;
1501 wep_type = weapon_type(weapon);
1502 /* use two weapon skill only if attacking with one of the wielded weapons
1504 type = (u.twoweap && (weapon == uwep || weapon == uswapwep))
1505 ? P_TWO_WEAPON_COMBAT
1507 if (type == P_NONE) {
1509 } else if (type <= P_LAST_WEAPON) {
1510 switch (P_SKILL(type)) {
1512 impossible("weapon_dam_bonus: bad skill %d", P_SKILL(type));
1514 case P_ISRESTRICTED:
1528 } else if (type == P_TWO_WEAPON_COMBAT) {
1529 skill = P_SKILL(P_TWO_WEAPON_COMBAT);
1530 if (P_SKILL(wep_type) < skill)
1531 skill = P_SKILL(wep_type);
1534 case P_ISRESTRICTED:
1548 } else if (type == P_BARE_HANDED_COMBAT) {
1558 bonus = P_SKILL(type);
1559 bonus = max(bonus, P_UNSKILLED) - 1; /* unskilled => 0 */
1560 bonus = ((bonus + 1) * (martial_bonus() ? 3 : 1)) / 2;
1563 /* KMH -- Riding gives some thrusting damage */
1564 if (u.usteed && type != P_TWO_WEAPON_COMBAT) {
1565 switch (P_SKILL(P_RIDING)) {
1566 case P_ISRESTRICTED:
1584 * Initialize weapon skill array for the game. Start by setting all
1585 * skills to restricted, then set the skill for every weapon the
1586 * hero is holding, finally reading the given array that sets
1590 skill_init(class_skill)
1591 const struct def_skill *class_skill;
1596 /* initialize skill array; by default, everything is restricted */
1597 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1598 P_SKILL(skill) = P_ISRESTRICTED;
1599 P_MAX_SKILL(skill) = P_ISRESTRICTED;
1600 P_ADVANCE(skill) = 0;
1603 /* Set skill for all weapons in inventory to be basic */
1604 for (obj = invent; obj; obj = obj->nobj) {
1605 /* don't give skill just because of carried ammo, wait until
1606 we see the relevant launcher (prevents an archeologist's
1607 touchstone from inadvertently providing skill in sling) */
1611 skill = weapon_type(obj);
1612 if (skill != P_NONE)
1613 P_SKILL(skill) = P_BASIC;
1616 /* set skills for magic */
1617 if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
1618 P_SKILL(P_HEALING_SPELL) = P_BASIC;
1619 } else if (Role_if(PM_PRIEST)) {
1620 P_SKILL(P_CLERIC_SPELL) = P_BASIC;
1621 } else if (Role_if(PM_WIZARD)) {
1622 P_SKILL(P_ATTACK_SPELL) = P_BASIC;
1623 P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
1626 /* walk through array to set skill maximums */
1627 for (; class_skill->skill != P_NONE; class_skill++) {
1628 skmax = class_skill->skmax;
1629 skill = class_skill->skill;
1631 P_MAX_SKILL(skill) = skmax;
1632 if (P_SKILL(skill) == P_ISRESTRICTED) /* skill pre-set */
1633 P_SKILL(skill) = P_UNSKILLED;
1636 /* High potential fighters already know how to use their hands. */
1637 if (P_MAX_SKILL(P_BARE_HANDED_COMBAT) > P_EXPERT)
1638 P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
1640 /* Roles that start with a horse know how to ride it */
1641 if (urole.petnum == PM_PONY)
1642 P_SKILL(P_RIDING) = P_BASIC;
1645 * Make sure we haven't missed setting the max on a skill
1648 for (skill = 0; skill < P_NUM_SKILLS; skill++) {
1649 if (!P_RESTRICTED(skill)) {
1650 if (P_MAX_SKILL(skill) < P_SKILL(skill)) {
1651 impossible("skill_init: curr > max: %s", P_NAME(skill));
1652 P_MAX_SKILL(skill) = P_SKILL(skill);
1654 P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill) - 1);
1660 setmnotwielded(mon, obj)
1661 register struct monst *mon;
1662 register struct obj *obj;
1666 if (artifact_light(obj) && obj->lamplit) {
1667 end_burn(obj, FALSE);
1670 pline("%s in %s %s %s shining.", The(xname(obj)),
1671 s_suffix(mon_nam(mon)), mbodypart(mon, HAND),
1672 otense(obj, "stop"));
1674 pline("%s
\82ª
\8e\9d\82Â%s
\82Ì
\8bP
\82«
\82ª
\8fÁ
\82¦
\82½
\81D",
1675 mon_nam(mon), xname(obj));
1678 if (MON_WEP(mon) == obj)
1680 obj->owornmask &= ~W_WEP;