OSDN Git Service

37dc7f9d113eb1eb0e3feb3ecfeb5dfc6dc286d1
[hengbandforosx/hengbandosx.git] / src / player / player-status.cpp
1 #include "player/player-status.h"
2 #include "artifact/fixed-art-types.h"
3 #include "autopick/autopick-reader-writer.h"
4 #include "autopick/autopick.h"
5 #include "avatar/avatar.h"
6 #include "cmd-action/cmd-pet.h"
7 #include "cmd-action/cmd-spell.h"
8 #include "cmd-io/cmd-dump.h"
9 #include "cmd-item/cmd-magiceat.h"
10 #include "combat/attack-power-table.h"
11 #include "core/asking-player.h"
12 #include "core/player-redraw-types.h"
13 #include "core/player-update-types.h"
14 #include "core/stuff-handler.h"
15 #include "core/window-redrawer.h"
16 #include "dungeon/dungeon-flag-types.h"
17 #include "dungeon/dungeon.h"
18 #include "effect/effect-characteristics.h"
19 #include "floor/cave.h"
20 #include "floor/floor-events.h"
21 #include "floor/floor-leaver.h"
22 #include "floor/floor-save.h"
23 #include "floor/floor-util.h"
24 #include "game-option/birth-options.h"
25 #include "grid/feature.h"
26 #include "grid/grid.h"
27 #include "inventory/inventory-object.h"
28 #include "io/input-key-acceptor.h"
29 #include "io/write-diary.h"
30 #include "main/sound-definitions-table.h"
31 #include "main/sound-of-music.h"
32 #include "market/arena-info-table.h"
33 #include "mind/mind-force-trainer.h"
34 #include "mind/mind-ninja.h"
35 #include "monster-floor/monster-lite.h"
36 #include "monster-floor/monster-remover.h"
37 #include "monster-race/monster-race-hook.h"
38 #include "monster-race/monster-race.h"
39 #include "monster-race/race-flags1.h"
40 #include "monster-race/race-flags2.h"
41 #include "monster-race/race-flags7.h"
42 #include "monster/monster-update.h"
43 #include "monster/smart-learn-types.h"
44 #include "mutation/mutation-calculator.h"
45 #include "mutation/mutation-flag-types.h"
46 #include "mutation/mutation-investor-remover.h"
47 #include "object-enchant/object-ego.h"
48 #include "object-enchant/special-object-flags.h"
49 #include "object-enchant/tr-types.h"
50 #include "object-enchant/trc-types.h"
51 #include "object-hook/hook-armor.h"
52 #include "object/object-flags.h"
53 #include "object/object-info.h"
54 #include "object/object-mark-types.h"
55 #include "perception/object-perception.h"
56 #include "pet/pet-util.h"
57 #include "player-ability/player-charisma.h"
58 #include "player-ability/player-constitution.h"
59 #include "player-ability/player-dexterity.h"
60 #include "player-ability/player-intelligence.h"
61 #include "player-ability/player-strength.h"
62 #include "player-ability/player-wisdom.h"
63 #include "player-base/player-class.h"
64 #include "player-base/player-race.h"
65 #include "player-info/alignment.h"
66 #include "player-info/class-info.h"
67 #include "player-info/equipment-info.h"
68 #include "player-info/mimic-info-table.h"
69 #include "player-info/monk-data-type.h"
70 #include "player-info/samurai-data-type.h"
71 #include "player-info/sniper-data-type.h"
72 #include "player-status/player-basic-statistics.h"
73 #include "player-status/player-hand-types.h"
74 #include "player-status/player-infravision.h"
75 #include "player-status/player-speed.h"
76 #include "player-status/player-stealth.h"
77 #include "player/attack-defense-types.h"
78 #include "player/digestion-processor.h"
79 #include "player/patron.h"
80 #include "player/player-damage.h"
81 #include "player/player-move.h"
82 #include "player/player-personality-types.h"
83 #include "player/player-personality.h"
84 #include "player/player-skill.h"
85 #include "player/player-status-flags.h"
86 #include "player/player-status-table.h"
87 #include "player/player-view.h"
88 #include "player/race-info-table.h"
89 #include "player/special-defense-types.h"
90 #include "realm/realm-hex-numbers.h"
91 #include "realm/realm-names-table.h"
92 #include "realm/realm-song-numbers.h"
93 #include "specific-object/bow.h"
94 #include "specific-object/torch.h"
95 #include "spell-realm/spells-hex.h"
96 #include "spell-realm/spells-song.h"
97 #include "spell/range-calc.h"
98 #include "spell/spells-describer.h"
99 #include "spell/spells-execution.h"
100 #include "spell/spells-status.h"
101 #include "spell/technic-info-table.h"
102 #include "status/action-setter.h"
103 #include "status/base-status.h"
104 #include "sv-definition/sv-lite-types.h"
105 #include "sv-definition/sv-weapon-types.h"
106 #include "system/floor-type-definition.h"
107 #include "system/grid-type-definition.h"
108 #include "system/monster-race-definition.h"
109 #include "system/monster-type-definition.h"
110 #include "system/object-type-definition.h"
111 #include "system/player-type-definition.h"
112 #include "term/screen-processor.h"
113 #include "timed-effect/player-acceleration.h"
114 #include "timed-effect/player-stun.h"
115 #include "timed-effect/timed-effects.h"
116 #include "util/bit-flags-calculator.h"
117 #include "util/enum-converter.h"
118 #include "util/quarks.h"
119 #include "util/string-processor.h"
120 #include "view/display-messages.h"
121 #include "world/world.h"
122
123 static const int extra_magic_glove_reduce_mana = 1;
124
125 static bool is_martial_arts_mode(PlayerType *player_ptr);
126
127 static ACTION_SKILL_POWER calc_disarming(PlayerType *player_ptr);
128 static ACTION_SKILL_POWER calc_device_ability(PlayerType *player_ptr);
129 static ACTION_SKILL_POWER calc_saving_throw(PlayerType *player_ptr);
130 static ACTION_SKILL_POWER calc_search(PlayerType *player_ptr);
131 static ACTION_SKILL_POWER calc_search_freq(PlayerType *player_ptr);
132 static ACTION_SKILL_POWER calc_to_hit_melee(PlayerType *player_ptr);
133 static ACTION_SKILL_POWER calc_to_hit_shoot(PlayerType *player_ptr);
134 static ACTION_SKILL_POWER calc_to_hit_throw(PlayerType *player_ptr);
135 static ACTION_SKILL_POWER calc_skill_dig(PlayerType *player_ptr);
136 static bool is_heavy_wield(PlayerType *player_ptr, int i);
137 static int16_t calc_num_blow(PlayerType *player_ptr, int i);
138 static int16_t calc_to_magic_chance(PlayerType *player_ptr);
139 static ARMOUR_CLASS calc_base_ac(PlayerType *player_ptr);
140 static ARMOUR_CLASS calc_to_ac(PlayerType *player_ptr, bool is_real_value);
141 static int16_t calc_double_weapon_penalty(PlayerType *player_ptr, INVENTORY_IDX slot);
142 static bool is_riding_two_hands(PlayerType *player_ptr);
143 static int16_t calc_riding_bow_penalty(PlayerType *player_ptr);
144 static void put_equipment_warning(PlayerType *player_ptr);
145
146 static short calc_to_damage(PlayerType *player_ptr, INVENTORY_IDX slot, bool is_real_value);
147 static int16_t calc_to_hit(PlayerType *player_ptr, INVENTORY_IDX slot, bool is_real_value);
148
149 static int16_t calc_to_hit_bow(PlayerType *player_ptr, bool is_real_value);
150
151 static int16_t calc_to_damage_misc(PlayerType *player_ptr);
152 static int16_t calc_to_hit_misc(PlayerType *player_ptr);
153
154 static DICE_NUMBER calc_to_weapon_dice_num(PlayerType *player_ptr, INVENTORY_IDX slot);
155 static player_hand main_attack_hand(PlayerType *player_ptr);
156
157 /*** Player information ***/
158
159 /*!
160  * @brief 遅延描画更新 / Delayed visual update
161  * @details update_view(), update_lite(), update_mon_lite() においてのみ更新すること / Only used if update_view(), update_lite() or update_mon_lite() was called
162  * @param player_ptr 主観となるプレイヤー構造体参照ポインタ
163  * @todo 将来独自インターフェース実装にはz-term系に追い出すべきか?
164  */
165 static void delayed_visual_update(PlayerType *player_ptr)
166 {
167     auto *floor_ptr = player_ptr->current_floor_ptr;
168     for (int i = 0; i < floor_ptr->redraw_n; i++) {
169         POSITION y = floor_ptr->redraw_y[i];
170         POSITION x = floor_ptr->redraw_x[i];
171         grid_type *g_ptr;
172         g_ptr = &floor_ptr->grid_array[y][x];
173         if (none_bits(g_ptr->info, CAVE_REDRAW)) {
174             continue;
175         }
176
177         if (any_bits(g_ptr->info, CAVE_NOTE)) {
178             note_spot(player_ptr, y, x);
179         }
180
181         lite_spot(player_ptr, y, x);
182         if (g_ptr->m_idx) {
183             update_monster(player_ptr, g_ptr->m_idx, false);
184         }
185
186         reset_bits(g_ptr->info, (CAVE_NOTE | CAVE_REDRAW));
187     }
188
189     floor_ptr->redraw_n = 0;
190 }
191
192 /*!
193  * @brief 射撃武器がプレイヤーにとって重すぎるかどうかの判定 /
194  * @param o_ptr 判定する射撃武器のアイテム情報参照ポインタ
195  * @return 重すぎるならばTRUE
196  */
197 static bool is_heavy_shoot(PlayerType *player_ptr, ObjectType *o_ptr)
198 {
199     return calc_bow_weight_limit(player_ptr) < (o_ptr->weight / 10);
200 }
201
202 /*!
203  * @brief 所持品総重量を計算する
204  * @param player_ptr プレイヤーへの参照ポインタ
205  * @return 総重量
206  */
207 WEIGHT calc_inventory_weight(PlayerType *player_ptr)
208 {
209     WEIGHT weight = 0;
210
211     ObjectType *o_ptr;
212     for (int i = 0; i < INVEN_TOTAL; i++) {
213         o_ptr = &player_ptr->inventory_list[i];
214         if (!o_ptr->k_idx) {
215             continue;
216         }
217         weight += o_ptr->weight * o_ptr->number;
218     }
219     return weight;
220 }
221
222 static void update_ability_scores(PlayerType *player_ptr)
223 {
224     PlayerStrength player_str(player_ptr);
225     PlayerIntelligence player_int(player_ptr);
226     PlayerWisdom player_wis(player_ptr);
227     PlayerDexterity player_dex(player_ptr);
228     PlayerConstitution player_con(player_ptr);
229     PlayerCharisma player_chr(player_ptr);
230     PlayerBasicStatistics *player_stats[] = { &player_str, &player_int, &player_wis, &player_dex, &player_con, &player_chr };
231     for (auto i = 0; i < A_MAX; ++i) {
232         player_ptr->stat_add[i] = player_stats[i]->modification_value();
233         player_stats[i]->update_value();
234     }
235 }
236
237 /*!
238  * @brief プレイヤーの全ステータスを更新する /
239  * Calculate the players current "state", taking into account
240  * not only race/class intrinsics, but also objects being worn
241  * and temporary spell effects.
242  * @details
243  * <pre>
244  * See also update_max_mana() and update_max_hitpoints().
245  *
246  * Take note of the new "speed code", in particular, a very strong
247  * player will start slowing down as soon as he reaches 150 pounds,
248  * but not until he reaches 450 pounds will he be half as fast as
249  * a normal kobold.  This both hurts and helps the player, hurts
250  * because in the old days a player could just avoid 300 pounds,
251  * and helps because now carrying 300 pounds is not very painful.
252  *
253  * The "weapon" and "bow" do *not* add to the bonuses to hit or to
254  * damage, since that would affect non-combat things.  These values
255  * are actually added in later, at the appropriate place.
256  *
257  * This function induces various "status" messages.
258  * </pre>
259  * @todo ここで計算していた各値は一部の状態変化メッセージ処理を除き、今後必要な時に適示計算する形に移行するためほぼすべて削られる。
260  */
261 static void update_bonuses(PlayerType *player_ptr)
262 {
263     auto empty_hands_status = empty_hands(player_ptr, true);
264     ObjectType *o_ptr;
265
266     /* Save the old vision stuff */
267     BIT_FLAGS old_telepathy = player_ptr->telepathy;
268     BIT_FLAGS old_esp_animal = player_ptr->esp_animal;
269     BIT_FLAGS old_esp_undead = player_ptr->esp_undead;
270     BIT_FLAGS old_esp_demon = player_ptr->esp_demon;
271     BIT_FLAGS old_esp_orc = player_ptr->esp_orc;
272     BIT_FLAGS old_esp_troll = player_ptr->esp_troll;
273     BIT_FLAGS old_esp_giant = player_ptr->esp_giant;
274     BIT_FLAGS old_esp_dragon = player_ptr->esp_dragon;
275     BIT_FLAGS old_esp_human = player_ptr->esp_human;
276     BIT_FLAGS old_esp_evil = player_ptr->esp_evil;
277     BIT_FLAGS old_esp_good = player_ptr->esp_good;
278     BIT_FLAGS old_esp_nonliving = player_ptr->esp_nonliving;
279     BIT_FLAGS old_esp_unique = player_ptr->esp_unique;
280     BIT_FLAGS old_see_inv = player_ptr->see_inv;
281     BIT_FLAGS old_mighty_throw = player_ptr->mighty_throw;
282     int16_t old_speed = player_ptr->pspeed;
283
284     ARMOUR_CLASS old_dis_ac = player_ptr->dis_ac;
285     ARMOUR_CLASS old_dis_to_a = player_ptr->dis_to_a;
286
287     player_ptr->xtra_might = has_xtra_might(player_ptr);
288     player_ptr->esp_evil = has_esp_evil(player_ptr);
289     player_ptr->esp_animal = has_esp_animal(player_ptr);
290     player_ptr->esp_undead = has_esp_undead(player_ptr);
291     player_ptr->esp_demon = has_esp_demon(player_ptr);
292     player_ptr->esp_orc = has_esp_orc(player_ptr);
293     player_ptr->esp_troll = has_esp_troll(player_ptr);
294     player_ptr->esp_giant = has_esp_giant(player_ptr);
295     player_ptr->esp_dragon = has_esp_dragon(player_ptr);
296     player_ptr->esp_human = has_esp_human(player_ptr);
297     player_ptr->esp_good = has_esp_good(player_ptr);
298     player_ptr->esp_nonliving = has_esp_nonliving(player_ptr);
299     player_ptr->esp_unique = has_esp_unique(player_ptr);
300     player_ptr->telepathy = has_esp_telepathy(player_ptr);
301     player_ptr->bless_blade = has_bless_blade(player_ptr);
302     player_ptr->easy_2weapon = has_easy2_weapon(player_ptr);
303     player_ptr->down_saving = has_down_saving(player_ptr);
304     player_ptr->yoiyami = has_no_ac(player_ptr);
305     player_ptr->mighty_throw = has_mighty_throw(player_ptr);
306     player_ptr->dec_mana = has_dec_mana(player_ptr);
307     player_ptr->see_nocto = has_see_nocto(player_ptr);
308     player_ptr->warning = has_warning(player_ptr);
309     player_ptr->anti_magic = has_anti_magic(player_ptr);
310     player_ptr->anti_tele = has_anti_tele(player_ptr);
311     player_ptr->easy_spell = has_easy_spell(player_ptr);
312     player_ptr->heavy_spell = has_heavy_spell(player_ptr);
313     player_ptr->hold_exp = has_hold_exp(player_ptr);
314     player_ptr->see_inv = has_see_inv(player_ptr);
315     player_ptr->free_act = has_free_act(player_ptr);
316     player_ptr->levitation = has_levitation(player_ptr);
317     player_ptr->can_swim = has_can_swim(player_ptr);
318     player_ptr->slow_digest = has_slow_digest(player_ptr);
319     player_ptr->regenerate = has_regenerate(player_ptr);
320     update_curses(player_ptr);
321     player_ptr->impact = has_impact(player_ptr);
322     player_ptr->earthquake = has_earthquake(player_ptr);
323     update_extra_blows(player_ptr);
324
325     player_ptr->lite = has_lite(player_ptr);
326
327     if (!PlayerClass(player_ptr).monk_stance_is(MonkStanceType::NONE)) {
328         if (none_bits(empty_hands_status, EMPTY_HAND_MAIN)) {
329             set_action(player_ptr, ACTION_NONE);
330         }
331     }
332
333     update_ability_scores(player_ptr);
334     o_ptr = &player_ptr->inventory_list[INVEN_BOW];
335     if (o_ptr->k_idx) {
336         player_ptr->tval_ammo = bow_tval_ammo(o_ptr);
337         player_ptr->num_fire = calc_num_fire(player_ptr, o_ptr);
338     }
339
340     for (int i = 0; i < 2; i++) {
341         player_ptr->is_icky_wield[i] = is_wielding_icky_weapon(player_ptr, i);
342         player_ptr->is_icky_riding_wield[i] = is_wielding_icky_riding_weapon(player_ptr, i);
343         player_ptr->heavy_wield[i] = is_heavy_wield(player_ptr, i);
344         player_ptr->num_blow[i] = calc_num_blow(player_ptr, i);
345         player_ptr->to_dd[i] = calc_to_weapon_dice_num(player_ptr, INVEN_MAIN_HAND + i);
346         player_ptr->to_ds[i] = 0;
347     }
348
349     player_ptr->pspeed = PlayerSpeed(player_ptr).get_value();
350     player_ptr->see_infra = PlayerInfravision(player_ptr).get_value();
351     player_ptr->skill_stl = PlayerStealth(player_ptr).get_value();
352     player_ptr->skill_dis = calc_disarming(player_ptr);
353     player_ptr->skill_dev = calc_device_ability(player_ptr);
354     player_ptr->skill_sav = calc_saving_throw(player_ptr);
355     player_ptr->skill_srh = calc_search(player_ptr);
356     player_ptr->skill_fos = calc_search_freq(player_ptr);
357     player_ptr->skill_thn = calc_to_hit_melee(player_ptr);
358     player_ptr->skill_thb = calc_to_hit_shoot(player_ptr);
359     player_ptr->skill_tht = calc_to_hit_throw(player_ptr);
360     player_ptr->riding_ryoute = is_riding_two_hands(player_ptr);
361     player_ptr->to_d[0] = calc_to_damage(player_ptr, INVEN_MAIN_HAND, true);
362     player_ptr->to_d[1] = calc_to_damage(player_ptr, INVEN_SUB_HAND, true);
363     player_ptr->dis_to_d[0] = calc_to_damage(player_ptr, INVEN_MAIN_HAND, false);
364     player_ptr->dis_to_d[1] = calc_to_damage(player_ptr, INVEN_SUB_HAND, false);
365     player_ptr->to_h[0] = calc_to_hit(player_ptr, INVEN_MAIN_HAND, true);
366     player_ptr->to_h[1] = calc_to_hit(player_ptr, INVEN_SUB_HAND, true);
367     player_ptr->dis_to_h[0] = calc_to_hit(player_ptr, INVEN_MAIN_HAND, false);
368     player_ptr->dis_to_h[1] = calc_to_hit(player_ptr, INVEN_SUB_HAND, false);
369     player_ptr->to_h_b = calc_to_hit_bow(player_ptr, true);
370     player_ptr->dis_to_h_b = calc_to_hit_bow(player_ptr, false);
371     player_ptr->to_d_m = calc_to_damage_misc(player_ptr);
372     player_ptr->to_h_m = calc_to_hit_misc(player_ptr);
373     player_ptr->skill_dig = calc_skill_dig(player_ptr);
374     player_ptr->to_m_chance = calc_to_magic_chance(player_ptr);
375     player_ptr->ac = calc_base_ac(player_ptr);
376     player_ptr->to_a = calc_to_ac(player_ptr, true);
377     player_ptr->dis_ac = calc_base_ac(player_ptr);
378     player_ptr->dis_to_a = calc_to_ac(player_ptr, false);
379
380     if (old_mighty_throw != player_ptr->mighty_throw) {
381         player_ptr->window_flags |= PW_INVEN;
382     }
383
384     if (player_ptr->telepathy != old_telepathy) {
385         set_bits(player_ptr->update, PU_MONSTERS);
386     }
387
388     if ((player_ptr->esp_animal != old_esp_animal) || (player_ptr->esp_undead != old_esp_undead) || (player_ptr->esp_demon != old_esp_demon) || (player_ptr->esp_orc != old_esp_orc) || (player_ptr->esp_troll != old_esp_troll) || (player_ptr->esp_giant != old_esp_giant) || (player_ptr->esp_dragon != old_esp_dragon) || (player_ptr->esp_human != old_esp_human) || (player_ptr->esp_evil != old_esp_evil) || (player_ptr->esp_good != old_esp_good) || (player_ptr->esp_nonliving != old_esp_nonliving) || (player_ptr->esp_unique != old_esp_unique)) {
389         set_bits(player_ptr->update, PU_MONSTERS);
390     }
391
392     if (player_ptr->see_inv != old_see_inv) {
393         set_bits(player_ptr->update, PU_MONSTERS);
394     }
395
396     if (player_ptr->pspeed != old_speed) {
397         set_bits(player_ptr->redraw, PR_SPEED);
398     }
399
400     if ((player_ptr->dis_ac != old_dis_ac) || (player_ptr->dis_to_a != old_dis_to_a)) {
401         set_bits(player_ptr->redraw, PR_ARMOR);
402         set_bits(player_ptr->window_flags, PW_PLAYER);
403     }
404
405     if (w_ptr->character_xtra) {
406         return;
407     }
408
409     put_equipment_warning(player_ptr);
410     check_no_flowed(player_ptr);
411 }
412
413 /*!
414  * @brief プレイヤーの最大HPを更新する /
415  * Update the players maximal hit points
416  * Adjust current hitpoints if necessary
417  * @details
418  */
419 static void update_max_hitpoints(PlayerType *player_ptr)
420 {
421     int bonus = ((int)(adj_con_mhp[player_ptr->stat_index[A_CON]]) - 128) * player_ptr->lev / 4;
422     int mhp = player_ptr->player_hp[player_ptr->lev - 1];
423
424     byte tmp_hitdie;
425     PlayerClass pc(player_ptr);
426     auto is_sorcerer = pc.equals(PlayerClassType::SORCERER);
427     if (player_ptr->mimic_form != MimicKindType::NONE) {
428         auto r_mhp = mimic_info.at(player_ptr->mimic_form).r_mhp;
429         if (is_sorcerer) {
430             tmp_hitdie = r_mhp / 2 + cp_ptr->c_mhp + ap_ptr->a_mhp;
431         } else {
432             tmp_hitdie = r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp;
433         }
434
435         mhp = mhp * tmp_hitdie / player_ptr->hitdie;
436     }
437
438     if (is_sorcerer) {
439         if (player_ptr->lev < 30) {
440             mhp = (mhp * (45 + player_ptr->lev) / 100);
441         } else {
442             mhp = (mhp * 75 / 100);
443         }
444         bonus = (bonus * 65 / 100);
445     }
446
447     mhp += bonus;
448
449     if (pc.equals(PlayerClassType::BERSERKER)) {
450         mhp = mhp * (110 + (((player_ptr->lev + 40) * (player_ptr->lev + 40) - 1550) / 110)) / 100;
451     }
452
453     if (mhp < player_ptr->lev + 1) {
454         mhp = player_ptr->lev + 1;
455     }
456     if (is_hero(player_ptr)) {
457         mhp += 10;
458     }
459     if (is_shero(player_ptr)) {
460         mhp += 30;
461     }
462     if (player_ptr->tsuyoshi) {
463         mhp += 50;
464     }
465     if (SpellHex(player_ptr).is_spelling_specific(HEX_XTRA_MIGHT)) {
466         mhp += 15;
467     }
468     if (SpellHex(player_ptr).is_spelling_specific(HEX_BUILDING)) {
469         mhp += 60;
470     }
471     if (player_ptr->mhp == mhp) {
472         return;
473     }
474
475     if (player_ptr->chp >= mhp) {
476         player_ptr->chp = mhp;
477         player_ptr->chp_frac = 0;
478     }
479
480 #ifdef JP
481     if (player_ptr->level_up_message && (mhp > player_ptr->mhp)) {
482         msg_format("最大ヒット・ポイントが %d 増加した!", (mhp - player_ptr->mhp));
483     }
484 #endif
485     player_ptr->mhp = mhp;
486
487     player_ptr->redraw |= PR_HP;
488     player_ptr->window_flags |= PW_PLAYER;
489 }
490
491 /*!
492  * @brief プレイヤーの現在学習可能な魔法数を計算し、増減に応じて魔法の忘却、再学習を処置する。 /
493  * Calculate number of spells player should have, and forget,
494  * or remember, spells until that number is properly reflected.
495  * @details
496  * Note that this function induces various "status" messages,
497  * which must be bypasses until the character is created.
498  */
499 static void update_num_of_spells(PlayerType *player_ptr)
500 {
501     if ((mp_ptr->spell_book == ItemKindType::NONE) || !w_ptr->character_generated || w_ptr->character_xtra) {
502         return;
503     }
504
505     PlayerClass pc(player_ptr);
506     if (pc.is_every_magic()) {
507         player_ptr->new_spells = 0;
508         return;
509     }
510
511     concptr p = spell_category_name(mp_ptr->spell_book);
512     int levels = player_ptr->lev - mp_ptr->spell_first + 1;
513     if (levels < 0) {
514         levels = 0;
515     }
516
517     int num_allowed = (adj_mag_study[player_ptr->stat_index[mp_ptr->spell_stat]] * levels / 2);
518     int bonus = 0;
519     if (!pc.equals(PlayerClassType::SAMURAI) && (mp_ptr->spell_book != ItemKindType::LIFE_BOOK)) {
520         bonus = 4;
521     }
522
523     if (pc.equals(PlayerClassType::SAMURAI)) {
524         num_allowed = 32;
525     } else if (player_ptr->realm2 == REALM_NONE) {
526         num_allowed = (num_allowed + 1) / 2;
527         if (num_allowed > (32 + bonus)) {
528             num_allowed = 32 + bonus;
529         }
530     } else if (pc.equals(PlayerClassType::MAGE) || pc.equals(PlayerClassType::PRIEST)) {
531         if (num_allowed > (96 + bonus)) {
532             num_allowed = 96 + bonus;
533         }
534     } else {
535         if (num_allowed > (80 + bonus)) {
536             num_allowed = 80 + bonus;
537         }
538     }
539
540     int num_boukyaku = 0;
541     for (int j = 0; j < 64; j++) {
542         if ((j < 32) ? any_bits(player_ptr->spell_forgotten1, (1UL << j)) : any_bits(player_ptr->spell_forgotten2, (1UL << (j - 32)))) {
543             num_boukyaku++;
544         }
545     }
546
547     player_ptr->new_spells = num_allowed + player_ptr->add_spells + num_boukyaku - player_ptr->learned_spells;
548     for (int i = 63; i >= 0; i--) {
549         if (!player_ptr->spell_learned1 && !player_ptr->spell_learned2) {
550             break;
551         }
552
553         int j = player_ptr->spell_order[i];
554         if (j >= 99) {
555             continue;
556         }
557
558         const magic_type *s_ptr;
559         if (!is_magic((j < 32) ? player_ptr->realm1 : player_ptr->realm2)) {
560             if (j < 32) {
561                 s_ptr = &technic_info[player_ptr->realm1 - MIN_TECHNIC][j];
562             } else {
563                 s_ptr = &technic_info[player_ptr->realm2 - MIN_TECHNIC][j % 32];
564             }
565         } else if (j < 32) {
566             s_ptr = &mp_ptr->info[player_ptr->realm1 - 1][j];
567         } else {
568             s_ptr = &mp_ptr->info[player_ptr->realm2 - 1][j % 32];
569         }
570
571         if (s_ptr->slevel <= player_ptr->lev) {
572             continue;
573         }
574
575         bool is_spell_learned = (j < 32) ? any_bits(player_ptr->spell_learned1, (1UL << j)) : any_bits(player_ptr->spell_learned2, (1UL << (j - 32)));
576         if (!is_spell_learned) {
577             continue;
578         }
579
580         int16_t which;
581         if (j < 32) {
582             set_bits(player_ptr->spell_forgotten1, (1UL << j));
583             which = player_ptr->realm1;
584         } else {
585             set_bits(player_ptr->spell_forgotten2, (1UL << (j - 32)));
586             which = player_ptr->realm2;
587         }
588
589         if (j < 32) {
590             reset_bits(player_ptr->spell_learned1, (1UL << j));
591             which = player_ptr->realm1;
592         } else {
593             reset_bits(player_ptr->spell_learned2, (1UL << (j - 32)));
594             which = player_ptr->realm2;
595         }
596
597 #ifdef JP
598         msg_format("%sの%sを忘れてしまった。", exe_spell(player_ptr, which, j % 32, SpellProcessType::NAME), p);
599 #else
600         msg_format("You have forgotten the %s of %s.", p, exe_spell(player_ptr, which, j % 32, SpellProcessType::NAME));
601 #endif
602         player_ptr->new_spells++;
603     }
604
605     /* Forget spells if we know too many spells */
606     for (int i = 63; i >= 0; i--) {
607         if (player_ptr->new_spells >= 0) {
608             break;
609         }
610         if (!player_ptr->spell_learned1 && !player_ptr->spell_learned2) {
611             break;
612         }
613
614         int j = player_ptr->spell_order[i];
615         if (j >= 99) {
616             continue;
617         }
618
619         bool is_spell_learned = (j < 32) ? any_bits(player_ptr->spell_learned1, (1UL << j)) : any_bits(player_ptr->spell_learned2, (1UL << (j - 32)));
620         if (!is_spell_learned) {
621             continue;
622         }
623
624         int16_t which;
625         if (j < 32) {
626             set_bits(player_ptr->spell_forgotten1, (1UL << j));
627             which = player_ptr->realm1;
628         } else {
629             set_bits(player_ptr->spell_forgotten2, (1UL << (j - 32)));
630             which = player_ptr->realm2;
631         }
632
633         if (j < 32) {
634             reset_bits(player_ptr->spell_learned1, (1UL << j));
635             which = player_ptr->realm1;
636         } else {
637             reset_bits(player_ptr->spell_learned2, (1UL << (j - 32)));
638             which = player_ptr->realm2;
639         }
640
641 #ifdef JP
642         msg_format("%sの%sを忘れてしまった。", exe_spell(player_ptr, which, j % 32, SpellProcessType::NAME), p);
643 #else
644         msg_format("You have forgotten the %s of %s.", p, exe_spell(player_ptr, which, j % 32, SpellProcessType::NAME));
645 #endif
646         player_ptr->new_spells++;
647     }
648
649     /* Check for spells to remember */
650     for (int i = 0; i < 64; i++) {
651         if (player_ptr->new_spells <= 0) {
652             break;
653         }
654         if (!player_ptr->spell_forgotten1 && !player_ptr->spell_forgotten2) {
655             break;
656         }
657         int j = player_ptr->spell_order[i];
658         if (j >= 99) {
659             break;
660         }
661
662         const magic_type *s_ptr;
663         if (!is_magic((j < 32) ? player_ptr->realm1 : player_ptr->realm2)) {
664             if (j < 32) {
665                 s_ptr = &technic_info[player_ptr->realm1 - MIN_TECHNIC][j];
666             } else {
667                 s_ptr = &technic_info[player_ptr->realm2 - MIN_TECHNIC][j % 32];
668             }
669         } else if (j < 32) {
670             s_ptr = &mp_ptr->info[player_ptr->realm1 - 1][j];
671         } else {
672             s_ptr = &mp_ptr->info[player_ptr->realm2 - 1][j % 32];
673         }
674
675         if (s_ptr->slevel > player_ptr->lev) {
676             continue;
677         }
678
679         bool is_spell_learned = (j < 32) ? any_bits(player_ptr->spell_forgotten1, (1UL << j)) : any_bits(player_ptr->spell_forgotten2, (1UL << (j - 32)));
680         if (!is_spell_learned) {
681             continue;
682         }
683
684         int16_t which;
685         if (j < 32) {
686             reset_bits(player_ptr->spell_forgotten1, (1UL << j));
687             which = player_ptr->realm1;
688         } else {
689             reset_bits(player_ptr->spell_forgotten2, (1UL << (j - 32)));
690             which = player_ptr->realm2;
691         }
692
693         if (j < 32) {
694             set_bits(player_ptr->spell_learned1, (1UL << j));
695             which = player_ptr->realm1;
696         } else {
697             set_bits(player_ptr->spell_learned2, (1UL << (j - 32)));
698             which = player_ptr->realm2;
699         }
700
701 #ifdef JP
702         msg_format("%sの%sを思い出した。", exe_spell(player_ptr, which, j % 32, SpellProcessType::NAME), p);
703 #else
704         msg_format("You have remembered the %s of %s.", p, exe_spell(player_ptr, which, j % 32, SpellProcessType::NAME));
705 #endif
706         player_ptr->new_spells--;
707     }
708
709     if (player_ptr->realm2 == REALM_NONE) {
710         int k = 0;
711         for (int j = 0; j < 32; j++) {
712             const magic_type *s_ptr;
713             if (!is_magic(player_ptr->realm1)) {
714                 s_ptr = &technic_info[player_ptr->realm1 - MIN_TECHNIC][j];
715             } else {
716                 s_ptr = &mp_ptr->info[player_ptr->realm1 - 1][j];
717             }
718
719             if (s_ptr->slevel > player_ptr->lev) {
720                 continue;
721             }
722
723             if (any_bits(player_ptr->spell_learned1, (1UL << j))) {
724                 continue;
725             }
726
727             k++;
728         }
729
730         if (k > 32) {
731             k = 32;
732         }
733         if ((player_ptr->new_spells > k) && ((mp_ptr->spell_book == ItemKindType::LIFE_BOOK) || (mp_ptr->spell_book == ItemKindType::HISSATSU_BOOK))) {
734             player_ptr->new_spells = (int16_t)k;
735         }
736     }
737
738     if (player_ptr->new_spells < 0) {
739         player_ptr->new_spells = 0;
740     }
741
742     if (player_ptr->old_spells == player_ptr->new_spells) {
743         return;
744     }
745
746     if (player_ptr->new_spells) {
747 #ifdef JP
748         if (player_ptr->new_spells < 10) {
749             msg_format("あと %d つの%sを学べる。", player_ptr->new_spells, p);
750         } else {
751             msg_format("あと %d 個の%sを学べる。", player_ptr->new_spells, p);
752         }
753 #else
754         msg_format("You can learn %d more %s%s.", player_ptr->new_spells, p, (player_ptr->new_spells != 1) ? "s" : "");
755 #endif
756     }
757
758     player_ptr->old_spells = player_ptr->new_spells;
759     set_bits(player_ptr->redraw, PR_STUDY);
760     set_bits(player_ptr->window_flags, PW_OBJECT);
761 }
762
763 /*!
764  * @brief プレイヤーの最大MPを更新する /
765  * Update maximum mana.  You do not need to know any spells.
766  * Note that mana is lowered by heavy (or inappropriate) armor.
767  * @details
768  * This function induces status messages.
769  */
770 static void update_max_mana(PlayerType *player_ptr)
771 {
772     if ((mp_ptr->spell_book == ItemKindType::NONE) && mp_ptr->spell_first == SPELL_FIRST_NO_SPELL) {
773         return;
774     }
775
776     int levels;
777     PlayerClass pc(player_ptr);
778     auto use_direct_level = pc.equals(PlayerClassType::MINDCRAFTER);
779     use_direct_level |= pc.equals(PlayerClassType::MIRROR_MASTER);
780     use_direct_level |= pc.equals(PlayerClassType::BLUE_MAGE);
781     use_direct_level |= pc.equals(PlayerClassType::ELEMENTALIST);
782     if (use_direct_level) {
783         levels = player_ptr->lev;
784     } else {
785         if (mp_ptr->spell_first > player_ptr->lev) {
786             player_ptr->msp = 0;
787             set_bits(player_ptr->redraw, PR_MANA);
788             return;
789         }
790
791         levels = (player_ptr->lev - mp_ptr->spell_first) + 1;
792     }
793
794     int msp;
795     if (pc.equals(PlayerClassType::SAMURAI)) {
796         msp = (adj_mag_mana[player_ptr->stat_index[mp_ptr->spell_stat]] + 10) * 2;
797         if (msp) {
798             msp += (msp * rp_ptr->r_adj[mp_ptr->spell_stat] / 20);
799         }
800     } else {
801         msp = adj_mag_mana[player_ptr->stat_index[mp_ptr->spell_stat]] * (levels + 3) / 4;
802         if (msp) {
803             msp++;
804         }
805         if (msp) {
806             msp += (msp * rp_ptr->r_adj[mp_ptr->spell_stat] / 20);
807         }
808         if (msp && (player_ptr->ppersonality == PERSONALITY_MUNCHKIN)) {
809             msp += msp / 2;
810         }
811         if (msp && pc.equals(PlayerClassType::HIGH_MAGE)) {
812             msp += msp / 4;
813         }
814         if (msp && pc.equals(PlayerClassType::SORCERER)) {
815             msp += msp * (25 + player_ptr->lev) / 100;
816         }
817     }
818
819     if (any_bits(mp_ptr->spell_xtra, extra_magic_glove_reduce_mana)) {
820         player_ptr->cumber_glove = false;
821         ObjectType *o_ptr;
822         o_ptr = &player_ptr->inventory_list[INVEN_ARMS];
823         auto flgs = object_flags(o_ptr);
824         if (o_ptr->k_idx && flgs.has_not(TR_FREE_ACT) && flgs.has_not(TR_DEC_MANA) && flgs.has_not(TR_EASY_SPELL) && !((flgs.has(TR_MAGIC_MASTERY)) && (o_ptr->pval > 0)) && !((flgs.has(TR_DEX)) && (o_ptr->pval > 0))) {
825             player_ptr->cumber_glove = true;
826             msp = (3 * msp) / 4;
827         }
828     }
829
830     player_ptr->cumber_armor = false;
831
832     int cur_wgt = 0;
833     if (player_ptr->inventory_list[INVEN_MAIN_HAND].tval > ItemKindType::SWORD) {
834         cur_wgt += player_ptr->inventory_list[INVEN_MAIN_HAND].weight;
835     }
836     if (player_ptr->inventory_list[INVEN_SUB_HAND].tval > ItemKindType::SWORD) {
837         cur_wgt += player_ptr->inventory_list[INVEN_SUB_HAND].weight;
838     }
839     cur_wgt += player_ptr->inventory_list[INVEN_BODY].weight;
840     cur_wgt += player_ptr->inventory_list[INVEN_HEAD].weight;
841     cur_wgt += player_ptr->inventory_list[INVEN_OUTER].weight;
842     cur_wgt += player_ptr->inventory_list[INVEN_ARMS].weight;
843     cur_wgt += player_ptr->inventory_list[INVEN_FEET].weight;
844
845     switch (player_ptr->pclass) {
846     case PlayerClassType::MAGE:
847     case PlayerClassType::HIGH_MAGE:
848     case PlayerClassType::BLUE_MAGE:
849     case PlayerClassType::MONK:
850     case PlayerClassType::FORCETRAINER:
851     case PlayerClassType::SORCERER:
852     case PlayerClassType::ELEMENTALIST: {
853         if (player_ptr->inventory_list[INVEN_MAIN_HAND].tval <= ItemKindType::SWORD) {
854             cur_wgt += player_ptr->inventory_list[INVEN_MAIN_HAND].weight;
855         }
856         if (player_ptr->inventory_list[INVEN_SUB_HAND].tval <= ItemKindType::SWORD) {
857             cur_wgt += player_ptr->inventory_list[INVEN_SUB_HAND].weight;
858         }
859         break;
860     }
861     case PlayerClassType::PRIEST:
862     case PlayerClassType::BARD:
863     case PlayerClassType::TOURIST: {
864         if (player_ptr->inventory_list[INVEN_MAIN_HAND].tval <= ItemKindType::SWORD) {
865             cur_wgt += player_ptr->inventory_list[INVEN_MAIN_HAND].weight * 2 / 3;
866         }
867         if (player_ptr->inventory_list[INVEN_SUB_HAND].tval <= ItemKindType::SWORD) {
868             cur_wgt += player_ptr->inventory_list[INVEN_SUB_HAND].weight * 2 / 3;
869         }
870         break;
871     }
872     case PlayerClassType::MINDCRAFTER:
873     case PlayerClassType::BEASTMASTER:
874     case PlayerClassType::MIRROR_MASTER: {
875         if (player_ptr->inventory_list[INVEN_MAIN_HAND].tval <= ItemKindType::SWORD) {
876             cur_wgt += player_ptr->inventory_list[INVEN_MAIN_HAND].weight / 2;
877         }
878         if (player_ptr->inventory_list[INVEN_SUB_HAND].tval <= ItemKindType::SWORD) {
879             cur_wgt += player_ptr->inventory_list[INVEN_SUB_HAND].weight / 2;
880         }
881         break;
882     }
883     case PlayerClassType::ROGUE:
884     case PlayerClassType::RANGER:
885     case PlayerClassType::RED_MAGE:
886     case PlayerClassType::WARRIOR_MAGE: {
887         if (player_ptr->inventory_list[INVEN_MAIN_HAND].tval <= ItemKindType::SWORD) {
888             cur_wgt += player_ptr->inventory_list[INVEN_MAIN_HAND].weight / 3;
889         }
890         if (player_ptr->inventory_list[INVEN_SUB_HAND].tval <= ItemKindType::SWORD) {
891             cur_wgt += player_ptr->inventory_list[INVEN_SUB_HAND].weight / 3;
892         }
893         break;
894     }
895     case PlayerClassType::PALADIN:
896     case PlayerClassType::CHAOS_WARRIOR: {
897         if (player_ptr->inventory_list[INVEN_MAIN_HAND].tval <= ItemKindType::SWORD) {
898             cur_wgt += player_ptr->inventory_list[INVEN_MAIN_HAND].weight / 5;
899         }
900         if (player_ptr->inventory_list[INVEN_SUB_HAND].tval <= ItemKindType::SWORD) {
901             cur_wgt += player_ptr->inventory_list[INVEN_SUB_HAND].weight / 5;
902         }
903         break;
904     }
905     default: {
906         break;
907     }
908     }
909
910     int max_wgt = mp_ptr->spell_weight;
911     if ((cur_wgt - max_wgt) > 0) {
912         player_ptr->cumber_armor = true;
913         switch (player_ptr->pclass) {
914         case PlayerClassType::MAGE:
915         case PlayerClassType::HIGH_MAGE:
916         case PlayerClassType::BLUE_MAGE:
917         case PlayerClassType::ELEMENTALIST: {
918             msp -= msp * (cur_wgt - max_wgt) / 600;
919             break;
920         }
921         case PlayerClassType::PRIEST:
922         case PlayerClassType::MINDCRAFTER:
923         case PlayerClassType::BEASTMASTER:
924         case PlayerClassType::BARD:
925         case PlayerClassType::FORCETRAINER:
926         case PlayerClassType::TOURIST:
927         case PlayerClassType::MIRROR_MASTER: {
928             msp -= msp * (cur_wgt - max_wgt) / 800;
929             break;
930         }
931         case PlayerClassType::SORCERER: {
932             msp -= msp * (cur_wgt - max_wgt) / 900;
933             break;
934         }
935         case PlayerClassType::ROGUE:
936         case PlayerClassType::RANGER:
937         case PlayerClassType::MONK:
938         case PlayerClassType::RED_MAGE: {
939             msp -= msp * (cur_wgt - max_wgt) / 1000;
940             break;
941         }
942         case PlayerClassType::PALADIN:
943         case PlayerClassType::CHAOS_WARRIOR:
944         case PlayerClassType::WARRIOR_MAGE: {
945             msp -= msp * (cur_wgt - max_wgt) / 1200;
946             break;
947         }
948         case PlayerClassType::SAMURAI: {
949             player_ptr->cumber_armor = false;
950             break;
951         }
952         default: {
953             msp -= msp * (cur_wgt - max_wgt) / 800;
954             break;
955         }
956         }
957     }
958
959     if (msp < 0) {
960         msp = 0;
961     }
962
963     if (player_ptr->msp != msp) {
964         if ((player_ptr->csp >= msp) && !pc.equals(PlayerClassType::SAMURAI)) {
965             player_ptr->csp = msp;
966             player_ptr->csp_frac = 0;
967         }
968
969 #ifdef JP
970         if (player_ptr->level_up_message && (msp > player_ptr->msp)) {
971             msg_format("最大マジック・ポイントが %d 増加した!", (msp - player_ptr->msp));
972         }
973 #endif
974         player_ptr->msp = msp;
975         set_bits(player_ptr->redraw, PR_MANA);
976         set_bits(player_ptr->window_flags, (PW_PLAYER | PW_SPELL));
977     }
978
979     if (w_ptr->character_xtra) {
980         return;
981     }
982
983     if (player_ptr->old_cumber_glove != player_ptr->cumber_glove) {
984         if (player_ptr->cumber_glove) {
985             msg_print(_("手が覆われて呪文が唱えにくい感じがする。", "Your covered hands feel unsuitable for spellcasting."));
986         } else {
987             msg_print(_("この手の状態なら、ぐっと呪文が唱えやすい感じだ。", "Your hands feel more suitable for spellcasting."));
988         }
989
990         player_ptr->old_cumber_glove = player_ptr->cumber_glove;
991     }
992
993     if (player_ptr->old_cumber_armor == player_ptr->cumber_armor) {
994         return;
995     }
996
997     if (player_ptr->cumber_armor) {
998         msg_print(_("装備の重さで動きが鈍くなってしまっている。", "The weight of your equipment encumbers your movement."));
999     } else {
1000         msg_print(_("ぐっと楽に体を動かせるようになった。", "You feel able to move more freely."));
1001     }
1002
1003     player_ptr->old_cumber_armor = player_ptr->cumber_armor;
1004 }
1005
1006 /*!
1007  * @brief 装備中の射撃武器の威力倍率を返す /
1008  * calcurate the fire rate of target object
1009  * @param o_ptr 計算する射撃武器のアイテム情報参照ポインタ
1010  * @return 射撃倍率の値(100で1.00倍)
1011  */
1012 int16_t calc_num_fire(PlayerType *player_ptr, ObjectType *o_ptr)
1013 {
1014     int extra_shots = 0;
1015
1016     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1017         ObjectType *q_ptr;
1018         q_ptr = &player_ptr->inventory_list[i];
1019         if (!q_ptr->k_idx) {
1020             continue;
1021         }
1022
1023         if (i == INVEN_BOW) {
1024             continue;
1025         }
1026
1027         auto flgs = object_flags(q_ptr);
1028         if (flgs.has(TR_XTRA_SHOTS)) {
1029             extra_shots++;
1030         }
1031     }
1032
1033     auto flgs = object_flags(o_ptr);
1034     if (flgs.has(TR_XTRA_SHOTS)) {
1035         extra_shots++;
1036     }
1037
1038     int num = 0;
1039     if (o_ptr->k_idx == 0) {
1040         return (int16_t)num;
1041     }
1042
1043     num = 100;
1044     num += (extra_shots * 100);
1045
1046     if (is_heavy_shoot(player_ptr, o_ptr)) {
1047         return (int16_t)num;
1048     }
1049
1050     ItemKindType tval_ammo = bow_tval_ammo(o_ptr);
1051     PlayerClass pc(player_ptr);
1052     if (pc.equals(PlayerClassType::RANGER) && (tval_ammo == ItemKindType::ARROW)) {
1053         num += (player_ptr->lev * 4);
1054     }
1055
1056     if (pc.equals(PlayerClassType::CAVALRY) && (tval_ammo == ItemKindType::ARROW)) {
1057         num += (player_ptr->lev * 3);
1058     }
1059
1060     if (pc.equals(PlayerClassType::ARCHER)) {
1061         if (tval_ammo == ItemKindType::ARROW) {
1062             num += ((player_ptr->lev * 5) + 50);
1063         } else if ((tval_ammo == ItemKindType::BOLT) || (tval_ammo == ItemKindType::SHOT)) {
1064             num += (player_ptr->lev * 4);
1065         }
1066     }
1067
1068     if (pc.equals(PlayerClassType::WARRIOR) && (tval_ammo <= ItemKindType::BOLT) && (tval_ammo >= ItemKindType::SHOT)) {
1069         num += (player_ptr->lev * 2);
1070     }
1071
1072     if (pc.equals(PlayerClassType::ROGUE) && (tval_ammo == ItemKindType::SHOT)) {
1073         num += (player_ptr->lev * 4);
1074     }
1075
1076     return (int16_t)num;
1077 }
1078
1079 /*!
1080  * @brief 解除能力計算
1081  * @param player_ptr プレイヤーへの参照ポインタ
1082  * @return 解除能力
1083  * @details
1084  * * 種族/職業/性格による加算
1085  * * 職業と性格とレベルによる追加加算
1086  * * 器用さに応じたadj_dex_disテーブルによる加算
1087  * * 知力に応じたadj_int_disテーブルによる加算
1088  */
1089 static ACTION_SKILL_POWER calc_disarming(PlayerType *player_ptr)
1090 {
1091     ACTION_SKILL_POWER pow;
1092     const player_race_info *tmp_rp_ptr;
1093
1094     if (player_ptr->mimic_form != MimicKindType::NONE) {
1095         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1096     } else {
1097         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1098     }
1099
1100     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1101     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1102
1103     pow = tmp_rp_ptr->r_dis + c_ptr->c_dis + a_ptr->a_dis;
1104     pow += ((cp_ptr->x_dis * player_ptr->lev / 10) + (ap_ptr->a_dis * player_ptr->lev / 50));
1105     pow += adj_dex_dis[player_ptr->stat_index[A_DEX]];
1106     pow += adj_int_dis[player_ptr->stat_index[A_INT]];
1107     return pow;
1108 }
1109
1110 /*!
1111  * @brief 魔道具使用能力計算
1112  * @param player_ptr プレイヤーへの参照ポインタ
1113  * @return 魔道具使用能力
1114  * @details
1115  * * 種族/職業/性格による加算
1116  * * 職業と性格とレベルによる追加加算
1117  * * 装備による加算(TR_MAGIC_MASTERYを持っていたら+pval*8)
1118  * * 知力に応じたadj_int_devテーブルによる加算
1119  * * 狂戦士化による減算(-20)
1120  */
1121 static ACTION_SKILL_POWER calc_device_ability(PlayerType *player_ptr)
1122 {
1123     ACTION_SKILL_POWER pow;
1124     const player_race_info *tmp_rp_ptr;
1125
1126     if (player_ptr->mimic_form != MimicKindType::NONE) {
1127         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1128     } else {
1129         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1130     }
1131
1132     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1133     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1134
1135     pow = tmp_rp_ptr->r_dev + c_ptr->c_dev + a_ptr->a_dev;
1136     pow += ((c_ptr->x_dev * player_ptr->lev / 10) + (ap_ptr->a_dev * player_ptr->lev / 50));
1137
1138     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1139         ObjectType *o_ptr;
1140         o_ptr = &player_ptr->inventory_list[i];
1141         if (!o_ptr->k_idx) {
1142             continue;
1143         }
1144         auto flgs = object_flags(o_ptr);
1145         if (flgs.has(TR_MAGIC_MASTERY)) {
1146             pow += 8 * o_ptr->pval;
1147         }
1148     }
1149
1150     pow += adj_int_dev[player_ptr->stat_index[A_INT]];
1151
1152     if (is_shero(player_ptr)) {
1153         pow -= 20;
1154     }
1155     return pow;
1156 }
1157
1158 /*!
1159  * @brief 魔法防御計算
1160  * @param player_ptr プレイヤーへの参照ポインタ
1161  * @return 魔法防御
1162  * @details
1163  * * 種族/職業/性格による加算
1164  * * 職業と性格とレベルによる追加加算
1165  * * 変異MUT3_MAGIC_RESによる加算(15 + レベル / 5)
1166  * * 呪力耐性の装備による加算(30)
1167  * * 祝福された装備による加算(5 + レベル / 10)
1168  * * 賢さによるadj_wis_savテーブル加算
1169  * * 呪力弱点の装備による減算(-10)
1170  * * 呪力弱点の装備が強力に呪われているときさらに減算(-20)
1171  * * 狂戦士化による減算(-30)
1172  * * 反魔法持ちで大なり上書き(90+レベル未満ならその値に上書き)
1173  * * クターのつぶれ状態なら(10に上書き)
1174  * * 生命の「究極の耐性」や regist_magic,magicdef持ちなら大なり上書き(95+レベル未満ならその値に上書き)
1175  * * 呪いのdown_savingがかかっているなら半減
1176  */
1177 static ACTION_SKILL_POWER calc_saving_throw(PlayerType *player_ptr)
1178 {
1179     ACTION_SKILL_POWER pow;
1180     const player_race_info *tmp_rp_ptr;
1181
1182     if (player_ptr->mimic_form != MimicKindType::NONE) {
1183         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1184     } else {
1185         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1186     }
1187
1188     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1189     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1190
1191     pow = tmp_rp_ptr->r_sav + c_ptr->c_sav + a_ptr->a_sav;
1192     pow += ((cp_ptr->x_sav * player_ptr->lev / 10) + (ap_ptr->a_sav * player_ptr->lev / 50));
1193
1194     if (player_ptr->muta.has(PlayerMutationType::MAGIC_RES)) {
1195         pow += (15 + (player_ptr->lev / 5));
1196     }
1197
1198     if (has_resist_curse(player_ptr)) {
1199         pow += 30;
1200     }
1201
1202     if (player_ptr->bless_blade) {
1203         pow += 6 + (player_ptr->lev - 1) / 10;
1204     }
1205
1206     pow += adj_wis_sav[player_ptr->stat_index[A_WIS]];
1207
1208     if (has_vuln_curse(player_ptr)) {
1209         pow -= 10;
1210     }
1211
1212     if (has_heavy_vuln_curse(player_ptr)) {
1213         pow -= 20;
1214     }
1215
1216     if (is_shero(player_ptr)) {
1217         pow -= 30;
1218     }
1219
1220     if (player_ptr->anti_magic && (pow < (90 + player_ptr->lev))) {
1221         pow = 90 + player_ptr->lev;
1222     }
1223
1224     if (player_ptr->tsubureru) {
1225         pow = 10;
1226     }
1227
1228     if ((player_ptr->ult_res || player_ptr->resist_magic || player_ptr->magicdef) && (pow < (95 + player_ptr->lev))) {
1229         pow = 95 + player_ptr->lev;
1230     }
1231
1232     if (player_ptr->down_saving) {
1233         pow /= 2;
1234     }
1235
1236     return pow;
1237 }
1238
1239 /*!
1240  * @brief 探索深度計算
1241  * @param player_ptr プレイヤーへの参照ポインタ
1242  * @return 探索深度
1243  * @details
1244  * * 種族/職業/性格による加算
1245  * * 職業とレベルによる追加加算
1246  * * 各装備による加算(TR_SEARCHがあれば+pval*5)
1247  * * 狂戦士化による減算(-15)
1248  * * 変異(MUT3_XTRA_EYES)による加算(+15)
1249  */
1250 static ACTION_SKILL_POWER calc_search(PlayerType *player_ptr)
1251 {
1252     ACTION_SKILL_POWER pow;
1253     const player_race_info *tmp_rp_ptr;
1254
1255     if (player_ptr->mimic_form != MimicKindType::NONE) {
1256         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1257     } else {
1258         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1259     }
1260
1261     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1262     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1263
1264     pow = tmp_rp_ptr->r_srh + c_ptr->c_srh + a_ptr->a_srh;
1265     pow += (c_ptr->x_srh * player_ptr->lev / 10);
1266
1267     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1268         ObjectType *o_ptr;
1269         o_ptr = &player_ptr->inventory_list[i];
1270         if (!o_ptr->k_idx) {
1271             continue;
1272         }
1273         auto flgs = object_flags(o_ptr);
1274         if (flgs.has(TR_SEARCH)) {
1275             pow += (o_ptr->pval * 5);
1276         }
1277     }
1278
1279     if (player_ptr->muta.has(PlayerMutationType::XTRA_EYES)) {
1280         pow += 15;
1281     }
1282
1283     if (is_shero(player_ptr)) {
1284         pow -= 15;
1285     }
1286
1287     return pow;
1288 }
1289
1290 /*!
1291  * @brief 探索頻度計算
1292  * @param player_ptr プレイヤーへの参照ポインタ
1293  * @return 探索頻度
1294  * @details
1295  * * 種族/職業/性格による加算
1296  * * 職業とレベルによる追加加算
1297  * * 各装備による加算(TR_SEARCHがあれば+pval*5)
1298  * * 狂戦士化による減算(-15)
1299  * * 変異(MUT3_XTRA_EYES)による加算(+15)
1300  */
1301 static ACTION_SKILL_POWER calc_search_freq(PlayerType *player_ptr)
1302 {
1303     ACTION_SKILL_POWER pow;
1304     const player_race_info *tmp_rp_ptr;
1305
1306     if (player_ptr->mimic_form != MimicKindType::NONE) {
1307         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1308     } else {
1309         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1310     }
1311
1312     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1313     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1314
1315     pow = tmp_rp_ptr->r_fos + c_ptr->c_fos + a_ptr->a_fos;
1316     pow += (c_ptr->x_fos * player_ptr->lev / 10);
1317
1318     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1319         ObjectType *o_ptr;
1320         o_ptr = &player_ptr->inventory_list[i];
1321         if (!o_ptr->k_idx) {
1322             continue;
1323         }
1324         auto flgs = object_flags(o_ptr);
1325         if (flgs.has(TR_SEARCH)) {
1326             pow += (o_ptr->pval * 5);
1327         }
1328     }
1329
1330     if (is_shero(player_ptr)) {
1331         pow -= 15;
1332     }
1333
1334     if (player_ptr->muta.has(PlayerMutationType::XTRA_EYES)) {
1335         pow += 15;
1336     }
1337
1338     return pow;
1339 }
1340
1341 /*!
1342  * @brief 打撃命中能力計算
1343  * @param player_ptr プレイヤーへの参照ポインタ
1344  * @return 打撃命中能力
1345  * @details
1346  * * 種族/職業/性格による加算とレベルによる追加加算
1347  */
1348 static ACTION_SKILL_POWER calc_to_hit_melee(PlayerType *player_ptr)
1349 {
1350     ACTION_SKILL_POWER pow;
1351     const player_race_info *tmp_rp_ptr;
1352     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1353     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1354
1355     if (player_ptr->mimic_form != MimicKindType::NONE) {
1356         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1357     } else {
1358         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1359     }
1360
1361     pow = tmp_rp_ptr->r_thn + c_ptr->c_thn + a_ptr->a_thn;
1362     pow += ((c_ptr->x_thn * player_ptr->lev / 10) + (a_ptr->a_thn * player_ptr->lev / 50));
1363     return pow;
1364 }
1365
1366 /*!
1367  * @brief 射撃命中能力計算
1368  * @param player_ptr プレイヤーへの参照ポインタ
1369  * @return 射撃命中能力
1370  * @details
1371  * * 種族/職業/性格による加算とレベルによる追加加算
1372  */
1373 static ACTION_SKILL_POWER calc_to_hit_shoot(PlayerType *player_ptr)
1374 {
1375     ACTION_SKILL_POWER pow;
1376     const player_race_info *tmp_rp_ptr;
1377     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1378     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1379
1380     if (player_ptr->mimic_form != MimicKindType::NONE) {
1381         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1382     } else {
1383         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1384     }
1385
1386     pow = tmp_rp_ptr->r_thb + c_ptr->c_thb + a_ptr->a_thb;
1387     pow += ((c_ptr->x_thb * player_ptr->lev / 10) + (a_ptr->a_thb * player_ptr->lev / 50));
1388     return pow;
1389 }
1390
1391 /*!
1392  * @brief 投擲命中能力計算
1393  * @param player_ptr プレイヤーへの参照ポインタ
1394  * @return 投擲命中能力
1395  * @details
1396  * * 種族/職業/性格による加算とレベルによる追加加算
1397  * * 狂戦士による減算(-20)
1398  */
1399 static ACTION_SKILL_POWER calc_to_hit_throw(PlayerType *player_ptr)
1400 {
1401     ACTION_SKILL_POWER pow;
1402     const player_race_info *tmp_rp_ptr;
1403     const player_class_info *c_ptr = &class_info[enum2i(player_ptr->pclass)];
1404     const player_personality *a_ptr = &personality_info[player_ptr->ppersonality];
1405
1406     if (player_ptr->mimic_form != MimicKindType::NONE) {
1407         tmp_rp_ptr = &mimic_info.at(player_ptr->mimic_form);
1408     } else {
1409         tmp_rp_ptr = &race_info[enum2i(player_ptr->prace)];
1410     }
1411
1412     pow = tmp_rp_ptr->r_thb + c_ptr->c_thb + a_ptr->a_thb;
1413     pow += ((c_ptr->x_thb * player_ptr->lev / 10) + (a_ptr->a_thb * player_ptr->lev / 50));
1414
1415     if (is_shero(player_ptr)) {
1416         pow -= 20;
1417     }
1418
1419     return pow;
1420 }
1421
1422 /*!
1423  * @brief 掘削能力計算
1424  * @param player_ptr プレイヤーへの参照ポインタ
1425  * @return 掘削能力値
1426  * @details
1427  * * エントが素手の場合のプラス修正
1428  * * 狂戦士化時のプラス修正
1429  * * 腕力によるテーブルプラス修正
1430  * * 職業狂戦士のプラス修正
1431  * * 装備の特性によるプラス修正
1432  * * 武器重量によるプラス修正
1433  * * 最終算出値に1を保証
1434  */
1435 static ACTION_SKILL_POWER calc_skill_dig(PlayerType *player_ptr)
1436 {
1437     ObjectType *o_ptr;
1438
1439     ACTION_SKILL_POWER pow;
1440
1441     pow = 0;
1442
1443     if (PlayerRace(player_ptr).equals(PlayerRaceType::ENT) && !player_ptr->inventory_list[INVEN_MAIN_HAND].k_idx) {
1444         pow += player_ptr->lev * 10;
1445     }
1446
1447     if (is_shero(player_ptr)) {
1448         pow += 30;
1449     }
1450
1451     pow += adj_str_dig[player_ptr->stat_index[A_STR]];
1452
1453     if (PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER)) {
1454         pow += (100 + player_ptr->lev * 8);
1455     }
1456
1457     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1458         o_ptr = &player_ptr->inventory_list[i];
1459         if (!o_ptr->k_idx) {
1460             continue;
1461         }
1462         auto flgs = object_flags(o_ptr);
1463         if (flgs.has(TR_TUNNEL)) {
1464             pow += (o_ptr->pval * 20);
1465         }
1466     }
1467
1468     for (int i = 0; i < 2; i++) {
1469         o_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND + i];
1470         if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND + i) && !player_ptr->heavy_wield[i]) {
1471             pow += (o_ptr->weight / 10);
1472         }
1473     }
1474
1475     if (is_shero(player_ptr)) {
1476         pow += 30;
1477     }
1478
1479     if (pow < 1) {
1480         pow = 1;
1481     }
1482
1483     return pow;
1484 }
1485
1486 static bool is_martial_arts_mode(PlayerType *player_ptr)
1487 {
1488     PlayerClass pc(player_ptr);
1489     auto has_martial_arts = pc.equals(PlayerClassType::MONK);
1490     has_martial_arts |= pc.equals(PlayerClassType::FORCETRAINER);
1491     has_martial_arts |= pc.equals(PlayerClassType::BERSERKER);
1492     return has_martial_arts && any_bits(empty_hands(player_ptr, true), EMPTY_HAND_MAIN) && !can_attack_with_sub_hand(player_ptr);
1493 }
1494
1495 static bool is_heavy_wield(PlayerType *player_ptr, int i)
1496 {
1497     const auto *o_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND + i];
1498
1499     return has_melee_weapon(player_ptr, INVEN_MAIN_HAND + i) && (calc_weapon_weight_limit(player_ptr) < o_ptr->weight / 10);
1500 }
1501
1502 static int16_t calc_num_blow(PlayerType *player_ptr, int i)
1503 {
1504     ObjectType *o_ptr;
1505     int16_t num_blow = 1;
1506
1507     o_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND + i];
1508     auto flgs = object_flags(o_ptr);
1509     PlayerClass pc(player_ptr);
1510     if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND + i)) {
1511         if (o_ptr->k_idx && !player_ptr->heavy_wield[i]) {
1512             int str_index, dex_index;
1513             int num = 0, wgt = 0, mul = 0, div = 0;
1514
1515             auto &info = class_info[enum2i(player_ptr->pclass)];
1516             num = info.num;
1517             wgt = info.wgt;
1518             mul = info.mul;
1519
1520             if (pc.equals(PlayerClassType::CAVALRY) && player_ptr->riding && flgs.has(TR_RIDING)) {
1521                 num = 5;
1522                 wgt = 70;
1523                 mul = 4;
1524             }
1525
1526             if (SpellHex(player_ptr).is_spelling_specific(HEX_XTRA_MIGHT) || SpellHex(player_ptr).is_spelling_specific(HEX_BUILDING)) {
1527                 num++;
1528                 wgt /= 2;
1529                 mul += 2;
1530             }
1531
1532             div = ((o_ptr->weight < wgt) ? wgt : o_ptr->weight);
1533             str_index = (adj_str_blow[player_ptr->stat_index[A_STR]] * mul / div);
1534
1535             if (has_two_handed_weapons(player_ptr) && !has_disable_two_handed_bonus(player_ptr, 0)) {
1536                 str_index += pc.equals(PlayerClassType::WARRIOR) || pc.equals(PlayerClassType::BERSERKER) ? (player_ptr->lev / 23 + 1) : 1;
1537             }
1538             if (pc.equals(PlayerClassType::NINJA)) {
1539                 str_index = std::max(0, str_index - 1);
1540             }
1541             if (str_index > 11) {
1542                 str_index = 11;
1543             }
1544
1545             dex_index = (adj_dex_blow[player_ptr->stat_index[A_DEX]]);
1546             if (dex_index > 11) {
1547                 dex_index = 11;
1548             }
1549
1550             num_blow = blows_table[str_index][dex_index];
1551             if (num_blow > num) {
1552                 num_blow = (int16_t)num;
1553             }
1554
1555             num_blow += (int16_t)player_ptr->extra_blows[i];
1556             if (pc.equals(PlayerClassType::WARRIOR)) {
1557                 num_blow += (player_ptr->lev / 40);
1558             } else if (pc.equals(PlayerClassType::BERSERKER)) {
1559                 num_blow += (player_ptr->lev / 23);
1560             } else if (pc.equals(PlayerClassType::ROGUE) && (o_ptr->weight < 50) && (player_ptr->stat_index[A_DEX] >= 30)) {
1561                 num_blow++;
1562             }
1563
1564             if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::FUUJIN)) {
1565                 num_blow -= 1;
1566             }
1567
1568             if ((o_ptr->tval == ItemKindType::SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) {
1569                 num_blow = 1;
1570             }
1571
1572             if (num_blow < 1) {
1573                 num_blow = 1;
1574             }
1575         }
1576     }
1577
1578     if (i != 0) {
1579         return num_blow;
1580     }
1581     /* Different calculation for monks with empty hands */
1582     if (is_martial_arts_mode(player_ptr)) {
1583         int blow_base = player_ptr->lev + adj_dex_blow[player_ptr->stat_index[A_DEX]];
1584         num_blow = 0;
1585
1586         if (pc.equals(PlayerClassType::FORCETRAINER)) {
1587             if (blow_base > 18) {
1588                 num_blow++;
1589             }
1590             if (blow_base > 31) {
1591                 num_blow++;
1592             }
1593             if (blow_base > 44) {
1594                 num_blow++;
1595             }
1596             if (blow_base > 58) {
1597                 num_blow++;
1598             }
1599         } else {
1600             if (blow_base > 12) {
1601                 num_blow++;
1602             }
1603             if (blow_base > 22) {
1604                 num_blow++;
1605             }
1606             if (blow_base > 31) {
1607                 num_blow++;
1608             }
1609             if (blow_base > 39) {
1610                 num_blow++;
1611             }
1612             if (blow_base > 46) {
1613                 num_blow++;
1614             }
1615             if (blow_base > 53) {
1616                 num_blow++;
1617             }
1618             if (blow_base > 59) {
1619                 num_blow++;
1620             }
1621         }
1622
1623         if (heavy_armor(player_ptr) && !pc.equals(PlayerClassType::BERSERKER)) {
1624             num_blow /= 2;
1625         }
1626
1627         if (pc.monk_stance_is(MonkStanceType::GENBU)) {
1628             num_blow -= 2;
1629             if (pc.equals(PlayerClassType::MONK) && (player_ptr->lev > 42)) {
1630                 num_blow--;
1631             }
1632             if (num_blow < 0) {
1633                 num_blow = 0;
1634             }
1635         } else if (pc.monk_stance_is(MonkStanceType::SUZAKU)) {
1636             num_blow /= 2;
1637         }
1638
1639         num_blow += 1 + player_ptr->extra_blows[0];
1640     }
1641
1642     if (has_not_ninja_weapon(player_ptr, i)) {
1643         num_blow /= 2;
1644         if (num_blow < 1) {
1645             num_blow = 1;
1646         }
1647     }
1648
1649     return num_blow;
1650 }
1651
1652 /*!
1653  * @brief 魔法失敗値計算
1654  * @param player_ptr プレイヤーへの参照ポインタ
1655  * @return 魔法失敗値
1656  * @details
1657  * * 性格なまけものなら加算(+10)
1658  * * 性格きれものなら減算(-3)
1659  * * 性格ちからじまんとがまんづよいなら加算(+1)
1660  * * 性格チャージマンなら加算(+5)
1661  * * 装備品にTRC::HARD_SPELLがあるなら加算(軽い呪いなら+3/重い呪いなら+10)
1662  */
1663 static int16_t calc_to_magic_chance(PlayerType *player_ptr)
1664 {
1665     int16_t chance = 0;
1666
1667     if (player_ptr->ppersonality == PERSONALITY_LAZY) {
1668         chance += 10;
1669     }
1670     if (player_ptr->ppersonality == PERSONALITY_SHREWD) {
1671         chance -= 3;
1672     }
1673     if ((player_ptr->ppersonality == PERSONALITY_PATIENT) || (player_ptr->ppersonality == PERSONALITY_MIGHTY)) {
1674         chance++;
1675     }
1676     if (player_ptr->ppersonality == PERSONALITY_CHARGEMAN) {
1677         chance += 5;
1678     }
1679
1680     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1681         ObjectType *o_ptr;
1682         o_ptr = &player_ptr->inventory_list[i];
1683         if (!o_ptr->k_idx) {
1684             continue;
1685         }
1686
1687         if (o_ptr->curse_flags.has(CurseTraitType::HARD_SPELL)) {
1688             if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
1689                 chance += 10;
1690             } else {
1691                 chance += 3;
1692             }
1693         }
1694     }
1695     return chance;
1696 }
1697
1698 static ARMOUR_CLASS calc_base_ac(PlayerType *player_ptr)
1699 {
1700     ARMOUR_CLASS ac = 0;
1701     if (player_ptr->yoiyami) {
1702         return 0;
1703     }
1704
1705     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1706         ObjectType *o_ptr;
1707         o_ptr = &player_ptr->inventory_list[i];
1708         if (!o_ptr->k_idx) {
1709             continue;
1710         }
1711         ac += o_ptr->ac;
1712     }
1713
1714     const auto o_ptr_mh = &player_ptr->inventory_list[INVEN_MAIN_HAND];
1715     const auto o_ptr_sh = &player_ptr->inventory_list[INVEN_SUB_HAND];
1716     if (o_ptr_mh->is_armour() || o_ptr_sh->is_armour()) {
1717         ac += player_ptr->skill_exp[PlayerSkillKindType::SHIELD] * (1 + player_ptr->lev / 22) / 2000;
1718     }
1719
1720     return ac;
1721 }
1722
1723 static ARMOUR_CLASS calc_to_ac(PlayerType *player_ptr, bool is_real_value)
1724 {
1725     ARMOUR_CLASS ac = 0;
1726     if (player_ptr->yoiyami) {
1727         return 0;
1728     }
1729
1730     ac += ((int)(adj_dex_ta[player_ptr->stat_index[A_DEX]]) - 128);
1731
1732     switch (player_ptr->mimic_form) {
1733     case MimicKindType::NONE:
1734         break;
1735     case MimicKindType::DEMON:
1736         ac += 10;
1737         break;
1738     case MimicKindType::DEMON_LORD:
1739         ac += 20;
1740         break;
1741     case MimicKindType::VAMPIRE:
1742         ac += 10;
1743         break;
1744     }
1745
1746     PlayerClass pc(player_ptr);
1747     if (pc.equals(PlayerClassType::BERSERKER)) {
1748         ac += 10 + player_ptr->lev / 2;
1749     }
1750
1751     if (pc.equals(PlayerClassType::SORCERER)) {
1752         ac -= 50;
1753     }
1754
1755     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
1756         ObjectType *o_ptr;
1757         o_ptr = &player_ptr->inventory_list[i];
1758         auto flags = object_flags(o_ptr);
1759         if (!o_ptr->k_idx) {
1760             continue;
1761         }
1762         if (is_real_value || o_ptr->is_known()) {
1763             ac += o_ptr->to_a;
1764         }
1765
1766         if (o_ptr->curse_flags.has(CurseTraitType::LOW_AC) || object_flags(o_ptr).has(TR_LOW_AC)) {
1767             if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
1768                 if (is_real_value || o_ptr->is_fully_known()) {
1769                     ac -= 30;
1770                 }
1771             } else {
1772                 if (is_real_value || o_ptr->is_fully_known()) {
1773                     ac -= 10;
1774                 }
1775             }
1776         }
1777
1778         if ((i == INVEN_SUB_HAND) && flags.has(TR_SUPPORTIVE)) {
1779             ac += 5;
1780         }
1781     }
1782
1783     PlayerRace pr(player_ptr);
1784     if (pr.equals(PlayerRaceType::GOLEM) || pr.equals(PlayerRaceType::ANDROID)) {
1785         ac += 10 + (player_ptr->lev * 2 / 5);
1786     }
1787
1788     if (set_quick_and_tiny(player_ptr)) {
1789         ac += 10;
1790     }
1791
1792     if (set_musasi(player_ptr)) {
1793         ac += 10;
1794     }
1795
1796     if (set_icing_and_twinkle(player_ptr)) {
1797         ac += 5;
1798     }
1799
1800     if (player_ptr->muta.has(PlayerMutationType::WART_SKIN)) {
1801         ac += 5;
1802     }
1803
1804     if (player_ptr->muta.has(PlayerMutationType::SCALES)) {
1805         ac += 10;
1806     }
1807
1808     if (player_ptr->muta.has(PlayerMutationType::IRON_SKIN)) {
1809         ac += 25;
1810     }
1811
1812     if (pc.is_martial_arts_pro() && !heavy_armor(player_ptr)) {
1813         if (!(player_ptr->inventory_list[INVEN_BODY].k_idx)) {
1814             ac += (player_ptr->lev * 3) / 2;
1815         }
1816         if (!(player_ptr->inventory_list[INVEN_OUTER].k_idx) && (player_ptr->lev > 15)) {
1817             ac += ((player_ptr->lev - 13) / 3);
1818         }
1819         if (!(player_ptr->inventory_list[INVEN_SUB_HAND].k_idx) && (player_ptr->lev > 10)) {
1820             ac += ((player_ptr->lev - 8) / 3);
1821         }
1822         if (!(player_ptr->inventory_list[INVEN_HEAD].k_idx) && (player_ptr->lev > 4)) {
1823             ac += (player_ptr->lev - 2) / 3;
1824         }
1825         if (!(player_ptr->inventory_list[INVEN_ARMS].k_idx)) {
1826             ac += (player_ptr->lev / 2);
1827         }
1828         if (!(player_ptr->inventory_list[INVEN_FEET].k_idx)) {
1829             ac += (player_ptr->lev / 3);
1830         }
1831     }
1832
1833     if (player_ptr->realm1 == REALM_HEX) {
1834         if (SpellHex(player_ptr).is_spelling_specific(HEX_ICE_ARMOR)) {
1835             ac += 30;
1836         }
1837
1838         for (int i = INVEN_MAIN_HAND; i <= INVEN_FEET; i++) {
1839             auto *o_ptr = &player_ptr->inventory_list[i];
1840             if (!o_ptr->k_idx) {
1841                 continue;
1842             }
1843             if (!o_ptr->is_armour()) {
1844                 continue;
1845             }
1846             if (!o_ptr->is_cursed()) {
1847                 continue;
1848             }
1849             if (o_ptr->curse_flags.has(CurseTraitType::CURSED)) {
1850                 ac += 5;
1851             }
1852             if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
1853                 ac += 7;
1854             }
1855             if (o_ptr->curse_flags.has(CurseTraitType::PERMA_CURSE)) {
1856                 ac += 13;
1857             }
1858         }
1859     }
1860
1861     if (pc.monk_stance_is(MonkStanceType::GENBU)) {
1862         ac += (player_ptr->lev * player_ptr->lev) / 50;
1863     } else if (pc.monk_stance_is(MonkStanceType::BYAKKO)) {
1864         ac -= 40;
1865     } else if (pc.monk_stance_is(MonkStanceType::SEIRYU)) {
1866         ac -= 50;
1867     } else if (pc.samurai_stance_is(SamuraiStanceType::KOUKIJIN)) {
1868         ac -= 50;
1869     }
1870
1871     if (player_ptr->ult_res || (pc.samurai_stance_is(SamuraiStanceType::MUSOU))) {
1872         ac += 100;
1873     } else if (player_ptr->tsubureru || player_ptr->shield || player_ptr->magicdef) {
1874         ac += 50;
1875     }
1876
1877     if (is_blessed(player_ptr)) {
1878         ac += 5;
1879     }
1880
1881     if (is_shero(player_ptr)) {
1882         ac -= 10;
1883     }
1884
1885     if (pc.equals(PlayerClassType::NINJA)) {
1886         if ((!player_ptr->inventory_list[INVEN_MAIN_HAND].k_idx || can_attack_with_main_hand(player_ptr)) && (!player_ptr->inventory_list[INVEN_SUB_HAND].k_idx || can_attack_with_sub_hand(player_ptr))) {
1887             ac += player_ptr->lev / 2 + 5;
1888         }
1889     }
1890
1891     return ac;
1892 }
1893
1894 /*!
1895  * @brief 二刀流ペナルティ量計算
1896  * @param player_ptr プレイヤーへの参照ポインタ
1897  * @param slot ペナルティ量を計算する武器スロット
1898  * @return 二刀流ペナルティ量
1899  * @details
1900  * * 二刀流にしていなければ0
1901  * * 特別セットによる軽減
1902  * * EASY2_WEAPONによる軽減
1903  * * SUPPORTIVEを左に装備した場合の軽減
1904  * * 武蔵セットによる免除
1905  * * 竿状武器による増加
1906  */
1907 int16_t calc_double_weapon_penalty(PlayerType *player_ptr, INVENTORY_IDX slot)
1908 {
1909     int penalty = 0;
1910
1911     if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND) && has_melee_weapon(player_ptr, INVEN_SUB_HAND)) {
1912         auto flags = object_flags(&player_ptr->inventory_list[INVEN_SUB_HAND]);
1913
1914         penalty = ((100 - player_ptr->skill_exp[PlayerSkillKindType::TWO_WEAPON] / 160) - (130 - player_ptr->inventory_list[slot].weight) / 8);
1915         if (set_quick_and_tiny(player_ptr) || set_icing_and_twinkle(player_ptr) || set_anubis_and_chariot(player_ptr)) {
1916             penalty = penalty / 2 - 5;
1917         }
1918
1919         for (uint i = FLAG_CAUSE_INVEN_MAIN_HAND; i < FLAG_CAUSE_MAX; i <<= 1) {
1920             if (penalty > 0 && any_bits(player_ptr->easy_2weapon, i)) {
1921                 penalty /= 2;
1922             }
1923         }
1924
1925         if (flags.has(TR_SUPPORTIVE)) {
1926             penalty = std::max(0, penalty - 10);
1927         }
1928
1929         if (set_musasi(player_ptr)) {
1930             penalty = std::min(0, penalty);
1931         }
1932
1933         if (player_ptr->inventory_list[slot].tval == ItemKindType::POLEARM) {
1934             penalty += 10;
1935         }
1936     }
1937     return (int16_t)penalty;
1938 }
1939
1940 static bool is_riding_two_hands(PlayerType *player_ptr)
1941 {
1942     if (!player_ptr->riding) {
1943         return false;
1944     }
1945
1946     if (has_two_handed_weapons(player_ptr) || (empty_hands(player_ptr, false) == EMPTY_HAND_NONE)) {
1947         return true;
1948     } else if (any_bits(player_ptr->pet_extra_flags, PF_TWO_HANDS)) {
1949         switch (player_ptr->pclass) {
1950         case PlayerClassType::MONK:
1951         case PlayerClassType::FORCETRAINER:
1952         case PlayerClassType::BERSERKER:
1953             if ((empty_hands(player_ptr, false) != EMPTY_HAND_NONE) && !has_melee_weapon(player_ptr, INVEN_MAIN_HAND) && !has_melee_weapon(player_ptr, INVEN_SUB_HAND)) {
1954                 return true;
1955             }
1956
1957         default:
1958             break;
1959         }
1960     }
1961
1962     return false;
1963 }
1964
1965 static int16_t calc_riding_bow_penalty(PlayerType *player_ptr)
1966 {
1967     auto *floor_ptr = player_ptr->current_floor_ptr;
1968     if (!player_ptr->riding) {
1969         return 0;
1970     }
1971
1972     int16_t penalty = 0;
1973
1974     if (PlayerClass(player_ptr).is_tamer()) {
1975         if (player_ptr->tval_ammo != ItemKindType::ARROW) {
1976             penalty = 5;
1977         }
1978     } else {
1979         penalty = monraces_info[floor_ptr->m_list[player_ptr->riding].r_idx].level - player_ptr->skill_exp[PlayerSkillKindType::RIDING] / 80;
1980         penalty += 30;
1981         if (penalty < 30) {
1982             penalty = 30;
1983         }
1984     }
1985
1986     if (player_ptr->tval_ammo == ItemKindType::BOLT) {
1987         penalty *= 2;
1988     }
1989
1990     return penalty;
1991 }
1992
1993 void put_equipment_warning(PlayerType *player_ptr)
1994 {
1995     bool heavy_shoot = is_heavy_shoot(player_ptr, &player_ptr->inventory_list[INVEN_BOW]);
1996     if (player_ptr->old_heavy_shoot != heavy_shoot) {
1997         if (heavy_shoot) {
1998             msg_print(_("こんな重い弓を装備しているのは大変だ。", "You have trouble wielding such a heavy bow."));
1999         } else if (player_ptr->inventory_list[INVEN_BOW].k_idx) {
2000             msg_print(_("この弓なら装備していても辛くない。", "You have no trouble wielding your bow."));
2001         } else {
2002             msg_print(_("重い弓を装備からはずして体が楽になった。", "You feel relieved to put down your heavy bow."));
2003         }
2004         player_ptr->old_heavy_shoot = heavy_shoot;
2005     }
2006
2007     for (int i = 0; i < 2; i++) {
2008         if (player_ptr->old_heavy_wield[i] != player_ptr->heavy_wield[i]) {
2009             if (player_ptr->heavy_wield[i]) {
2010                 msg_print(_("こんな重い武器を装備しているのは大変だ。", "You have trouble wielding such a heavy weapon."));
2011             } else if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND + i)) {
2012                 msg_print(_("これなら装備していても辛くない。", "You have no trouble wielding your weapon."));
2013             } else if (player_ptr->heavy_wield[1 - i]) {
2014                 msg_print(_("まだ武器が重い。", "You still have trouble wielding a heavy weapon."));
2015             } else {
2016                 msg_print(_("重い武器を装備からはずして体が楽になった。", "You feel relieved to put down your heavy weapon."));
2017             }
2018
2019             player_ptr->old_heavy_wield[i] = player_ptr->heavy_wield[i];
2020         }
2021
2022         if (player_ptr->old_riding_wield[i] != player_ptr->is_icky_riding_wield[i]) {
2023             if (player_ptr->is_icky_riding_wield[i]) {
2024                 msg_print(_("この武器は乗馬中に使うにはむかないようだ。", "This weapon is not suitable for use while riding."));
2025             } else if (!player_ptr->riding) {
2026                 msg_print(_("この武器は徒歩で使いやすい。", "This weapon is suitable for use on foot."));
2027             } else if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND + i)) {
2028                 msg_print(_("これなら乗馬中にぴったりだ。", "This weapon is suitable for use while riding."));
2029             }
2030
2031             player_ptr->old_riding_wield[i] = player_ptr->is_icky_riding_wield[i];
2032         }
2033
2034         if (player_ptr->old_icky_wield[i] == player_ptr->is_icky_wield[i]) {
2035             continue;
2036         }
2037
2038         if (player_ptr->is_icky_wield[i]) {
2039             msg_print(_("今の装備はどうも自分にふさわしくない気がする。", "You do not feel comfortable with your weapon."));
2040             if (w_ptr->is_loading_now) {
2041                 chg_virtue(player_ptr, V_FAITH, -1);
2042             }
2043         } else if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND + i)) {
2044             msg_print(_("今の装備は自分にふさわしい気がする。", "You feel comfortable with your weapon."));
2045         } else {
2046             msg_print(_("装備をはずしたら随分と気が楽になった。", "You feel more comfortable after removing your weapon."));
2047         }
2048
2049         player_ptr->old_icky_wield[i] = player_ptr->is_icky_wield[i];
2050     }
2051
2052     if (player_ptr->riding && (player_ptr->old_riding_ryoute != player_ptr->riding_ryoute)) {
2053         if (player_ptr->riding_ryoute) {
2054 #ifdef JP
2055             msg_format("%s馬を操れない。", (empty_hands(player_ptr, false) == EMPTY_HAND_NONE) ? "両手がふさがっていて" : "");
2056 #else
2057             msg_print("You are using both hand for fighting, and you can't control the pet you're riding.");
2058 #endif
2059         } else {
2060 #ifdef JP
2061             msg_format("%s馬を操れるようになった。", (empty_hands(player_ptr, false) == EMPTY_HAND_NONE) ? "手が空いて" : "");
2062 #else
2063             msg_print("You began to control the pet you're riding with one hand.");
2064 #endif
2065         }
2066
2067         player_ptr->old_riding_ryoute = player_ptr->riding_ryoute;
2068     }
2069
2070     PlayerClass pc(player_ptr);
2071     if ((pc.is_martial_arts_pro() || pc.equals(PlayerClassType::NINJA)) && (heavy_armor(player_ptr) != player_ptr->monk_notify_aux)) {
2072         if (heavy_armor(player_ptr)) {
2073             msg_print(_("装備が重くてバランスを取れない。", "The weight of your armor disrupts your balance."));
2074             if (w_ptr->is_loading_now) {
2075                 chg_virtue(player_ptr, V_HARMONY, -1);
2076             }
2077         } else {
2078             msg_print(_("バランスがとれるようになった。", "You regain your balance."));
2079         }
2080
2081         player_ptr->monk_notify_aux = heavy_armor(player_ptr);
2082     }
2083 }
2084
2085 static short calc_to_damage(PlayerType *player_ptr, INVENTORY_IDX slot, bool is_real_value)
2086 {
2087     auto *o_ptr = &player_ptr->inventory_list[slot];
2088     auto flgs = object_flags(o_ptr);
2089
2090     player_hand calc_hand = PLAYER_HAND_OTHER;
2091     if (slot == INVEN_MAIN_HAND) {
2092         calc_hand = PLAYER_HAND_MAIN;
2093     }
2094     if (slot == INVEN_SUB_HAND) {
2095         calc_hand = PLAYER_HAND_SUB;
2096     }
2097
2098     auto damage = 0;
2099     damage += ((int)(adj_str_td[player_ptr->stat_index[A_STR]]) - 128);
2100
2101     if (is_shero(player_ptr)) {
2102         damage += 3 + (player_ptr->lev / 5);
2103     }
2104
2105     auto player_stun = player_ptr->effects()->stun();
2106     damage -= player_stun->get_damage_penalty();
2107     PlayerClass pc(player_ptr);
2108     if (pc.equals(PlayerClassType::PRIEST) && (flgs.has_not(TR_BLESSED)) && ((o_ptr->tval == ItemKindType::SWORD) || (o_ptr->tval == ItemKindType::POLEARM))) {
2109         damage -= 2;
2110     } else if (pc.equals(PlayerClassType::BERSERKER)) {
2111         damage += player_ptr->lev / 6;
2112         if (((calc_hand == PLAYER_HAND_MAIN) && !can_attack_with_sub_hand(player_ptr)) || has_two_handed_weapons(player_ptr)) {
2113             damage += player_ptr->lev / 6;
2114         }
2115     } else if (pc.equals(PlayerClassType::SORCERER)) {
2116         if (!((o_ptr->tval == ItemKindType::HAFTED) && ((o_ptr->sval == SV_WIZSTAFF) || (o_ptr->sval == SV_NAMAKE_HAMMER)))) {
2117             damage -= 200;
2118         } else {
2119             damage -= 10;
2120         }
2121     } else if (pc.equals(PlayerClassType::FORCETRAINER)) {
2122         // 練気術師は格闘ダメージに (気)/5 の修正を得る。
2123         if (is_martial_arts_mode(player_ptr) && calc_hand == PLAYER_HAND_MAIN) {
2124             damage += get_current_ki(player_ptr) / 5;
2125         }
2126     }
2127
2128     if ((player_ptr->realm1 == REALM_HEX) && o_ptr->is_cursed()) {
2129         if (SpellHex(player_ptr).is_spelling_specific(HEX_RUNESWORD)) {
2130             if (o_ptr->curse_flags.has(CurseTraitType::CURSED)) {
2131                 damage += 5;
2132             }
2133             if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
2134                 damage += 7;
2135             }
2136             if (o_ptr->curse_flags.has(CurseTraitType::PERMA_CURSE)) {
2137                 damage += 13;
2138             }
2139         }
2140     }
2141
2142     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
2143         int bonus_to_d = 0;
2144         o_ptr = &player_ptr->inventory_list[i];
2145         if (!o_ptr->k_idx || o_ptr->tval == ItemKindType::CAPTURE || (i == INVEN_MAIN_HAND && has_melee_weapon(player_ptr, i)) || (i == INVEN_SUB_HAND && has_melee_weapon(player_ptr, i)) || i == INVEN_BOW) {
2146             continue;
2147         }
2148
2149         if (!o_ptr->is_known() && !is_real_value) {
2150             continue;
2151         }
2152         bonus_to_d = o_ptr->to_d;
2153
2154         if (pc.equals(PlayerClassType::NINJA)) {
2155             if (o_ptr->to_d > 0) {
2156                 bonus_to_d = (o_ptr->to_d + 1) / 2;
2157             }
2158         }
2159
2160         switch (player_melee_type(player_ptr)) {
2161         case MELEE_TYPE_BAREHAND_TWO: /* fall through */
2162         case MELEE_TYPE_WEAPON_TWOHAND:
2163             if (calc_hand == main_attack_hand(player_ptr)) {
2164                 damage += (int16_t)bonus_to_d;
2165             }
2166             break;
2167
2168         case MELEE_TYPE_BAREHAND_MAIN: /* fall through */
2169         case MELEE_TYPE_WEAPON_MAIN:
2170             if ((calc_hand == PLAYER_HAND_MAIN) && (i != INVEN_SUB_RING)) {
2171                 damage += (int16_t)bonus_to_d;
2172             }
2173             break;
2174
2175         case MELEE_TYPE_BAREHAND_SUB: /* fall through */
2176         case MELEE_TYPE_WEAPON_SUB:
2177             if ((calc_hand == PLAYER_HAND_SUB) && (i != INVEN_MAIN_RING)) {
2178                 damage += (int16_t)bonus_to_d;
2179             }
2180             break;
2181
2182         case MELEE_TYPE_WEAPON_DOUBLE:
2183             if (calc_hand == PLAYER_HAND_MAIN) {
2184                 if (i == INVEN_MAIN_RING) {
2185                     damage += (int16_t)bonus_to_d;
2186                 } else if (i != INVEN_SUB_RING) {
2187                     damage += (bonus_to_d > 0) ? (bonus_to_d + 1) / 2 : bonus_to_d;
2188                 }
2189             }
2190             if (calc_hand == PLAYER_HAND_SUB) {
2191                 if (i == INVEN_SUB_RING) {
2192                     damage += (int16_t)bonus_to_d;
2193                 } else if (i != INVEN_MAIN_RING) {
2194                     damage += (bonus_to_d > 0) ? bonus_to_d / 2 : bonus_to_d;
2195                 }
2196             }
2197             break;
2198
2199         case MELEE_TYPE_SHIELD_DOUBLE:
2200             break;
2201
2202         default:
2203             break;
2204         }
2205     }
2206
2207     if (main_attack_hand(player_ptr) == calc_hand) {
2208         if ((is_martial_arts_mode(player_ptr) && empty_hands(player_ptr, false) == (EMPTY_HAND_MAIN | EMPTY_HAND_SUB)) || !has_disable_two_handed_bonus(player_ptr, calc_hand)) {
2209             int bonus_to_d = 0;
2210             bonus_to_d = ((int)(adj_str_td[player_ptr->stat_index[A_STR]]) - 128) / 2;
2211             damage += std::max<int>(bonus_to_d, 1);
2212         }
2213     }
2214
2215     if (is_martial_arts_mode(player_ptr) && (!heavy_armor(player_ptr) || !pc.equals(PlayerClassType::BERSERKER))) {
2216         damage += (player_ptr->lev / 6);
2217     }
2218
2219     // 朱雀の構えをとっているとき、格闘ダメージに -(レベル)/6 の修正を得る。
2220     if (PlayerClass(player_ptr).monk_stance_is(MonkStanceType::SUZAKU)) {
2221         if (is_martial_arts_mode(player_ptr) && calc_hand == PLAYER_HAND_MAIN) {
2222             damage -= (player_ptr->lev / 6);
2223         }
2224     }
2225
2226     return static_cast<short>(damage);
2227 }
2228
2229 /*!
2230  * @brief 武器の命中修正を計算する。 / Calculate hit bonus from a wielded weapon.
2231  * @details
2232  * 'slot' MUST be INVEN_MAIN_HAND or INVEM_SUB_HAND.
2233  */
2234 static short calc_to_hit(PlayerType *player_ptr, INVENTORY_IDX slot, bool is_real_value)
2235 {
2236     auto hit = 0;
2237
2238     /* Base bonuses */
2239     hit += ((int)(adj_dex_th[player_ptr->stat_index[A_DEX]]) - 128);
2240     hit += ((int)(adj_str_th[player_ptr->stat_index[A_STR]]) - 128);
2241
2242     /* Temporary bonuses */
2243     if (is_blessed(player_ptr)) {
2244         hit += 10;
2245     }
2246
2247     if (is_hero(player_ptr)) {
2248         hit += 12;
2249     }
2250
2251     if (is_shero(player_ptr)) {
2252         hit += 12;
2253     }
2254
2255     auto player_stun = player_ptr->effects()->stun();
2256     hit -= player_stun->get_damage_penalty();
2257     player_hand calc_hand = PLAYER_HAND_OTHER;
2258     if (slot == INVEN_MAIN_HAND) {
2259         calc_hand = PLAYER_HAND_MAIN;
2260     }
2261     if (slot == INVEN_SUB_HAND) {
2262         calc_hand = PLAYER_HAND_SUB;
2263     }
2264
2265     /* Default hand bonuses */
2266     if (main_attack_hand(player_ptr) == calc_hand) {
2267         switch (player_melee_type(player_ptr)) {
2268         case MELEE_TYPE_BAREHAND_MAIN:
2269             if (player_ptr->riding) {
2270                 break;
2271             }
2272             /* fall through */
2273         case MELEE_TYPE_BAREHAND_SUB:
2274             if (player_ptr->riding) {
2275                 break;
2276             }
2277             /* fall through */
2278         case MELEE_TYPE_BAREHAND_TWO:
2279             hit += (player_ptr->skill_exp[PlayerSkillKindType::MARTIAL_ARTS] - PlayerSkill::weapon_exp_at(PlayerSkillRank::BEGINNER)) / 200;
2280             break;
2281
2282         default:
2283             break;
2284         }
2285
2286         if ((is_martial_arts_mode(player_ptr) && empty_hands(player_ptr, false) == (EMPTY_HAND_MAIN | EMPTY_HAND_SUB)) || !has_disable_two_handed_bonus(player_ptr, calc_hand)) {
2287             int bonus_to_h = 0;
2288             bonus_to_h = ((int)(adj_str_th[player_ptr->stat_index[A_STR]]) - 128) + ((int)(adj_dex_th[player_ptr->stat_index[A_DEX]]) - 128);
2289             hit += std::max<int>(bonus_to_h, 1);
2290         }
2291     }
2292
2293     /* Bonuses and penalties by weapon */
2294     PlayerClass pc(player_ptr);
2295     if (has_melee_weapon(player_ptr, slot)) {
2296         auto *o_ptr = &player_ptr->inventory_list[slot];
2297         auto flgs = object_flags(o_ptr);
2298
2299         /* Traind bonuses */
2300         hit += (player_ptr->weapon_exp[o_ptr->tval][o_ptr->sval] - PlayerSkill::weapon_exp_at(PlayerSkillRank::BEGINNER)) / 200;
2301
2302         /* Weight penalty */
2303         if (calc_weapon_weight_limit(player_ptr) < o_ptr->weight / 10) {
2304             hit += 2 * (calc_weapon_weight_limit(player_ptr) - o_ptr->weight / 10);
2305         }
2306
2307         /* Low melee penalty */
2308         if ((o_ptr->is_fully_known() || is_real_value) && o_ptr->curse_flags.has(CurseTraitType::LOW_MELEE)) {
2309             if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
2310                 hit -= 15;
2311             } else {
2312                 hit -= 5;
2313             }
2314         }
2315
2316         /* Riding bonus and penalty */
2317         if (player_ptr->riding > 0) {
2318             if (o_ptr->is_lance()) {
2319                 hit += 15;
2320             } else if (flgs.has_not(TR_RIDING)) {
2321                 short penalty;
2322                 if (PlayerClass(player_ptr).is_tamer()) {
2323                     penalty = 5;
2324                 } else {
2325                     penalty = monraces_info[player_ptr->current_floor_ptr->m_list[player_ptr->riding].r_idx].level - player_ptr->skill_exp[PlayerSkillKindType::RIDING] / 80;
2326                     penalty += 30;
2327                     if (penalty < 30) {
2328                         penalty = 30;
2329                     }
2330                 }
2331
2332                 hit -= penalty;
2333             }
2334         }
2335
2336         /* Class penalties */
2337         if (pc.equals(PlayerClassType::PRIEST) && (flgs.has_not(TR_BLESSED)) && ((o_ptr->tval == ItemKindType::SWORD) || (o_ptr->tval == ItemKindType::POLEARM))) {
2338             hit -= 2;
2339         } else if (pc.equals(PlayerClassType::BERSERKER)) {
2340             hit += player_ptr->lev / 5;
2341             if (((calc_hand == PLAYER_HAND_MAIN) && !can_attack_with_sub_hand(player_ptr)) || has_two_handed_weapons(player_ptr)) {
2342                 hit += player_ptr->lev / 5;
2343             }
2344         } else if (pc.equals(PlayerClassType::SORCERER)) {
2345             if (!((o_ptr->tval == ItemKindType::HAFTED) && ((o_ptr->sval == SV_WIZSTAFF) || (o_ptr->sval == SV_NAMAKE_HAMMER)))) {
2346                 hit -= 200;
2347             } else {
2348                 hit -= 30;
2349             }
2350         }
2351
2352         if (has_not_ninja_weapon(player_ptr, (int)calc_hand) || has_not_monk_weapon(player_ptr, (int)calc_hand)) {
2353             hit -= 40;
2354         }
2355
2356         /* Hex realm bonuses */
2357         if ((player_ptr->realm1 == REALM_HEX) && o_ptr->is_cursed()) {
2358             if (o_ptr->curse_flags.has(CurseTraitType::CURSED)) {
2359                 hit += 5;
2360             }
2361             if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
2362                 hit += 7;
2363             }
2364             if (o_ptr->curse_flags.has(CurseTraitType::PERMA_CURSE)) {
2365                 hit += 13;
2366             }
2367             if (o_ptr->curse_flags.has(CurseTraitType::TY_CURSE)) {
2368                 hit += 5;
2369             }
2370         }
2371     }
2372
2373     /* Bonuses from inventory */
2374     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
2375         auto *o_ptr = &player_ptr->inventory_list[i];
2376
2377         /* Ignore empty hands, handed weapons, bows and capture balls */
2378         if (!o_ptr->k_idx || o_ptr->tval == ItemKindType::CAPTURE || (i == INVEN_MAIN_HAND && has_melee_weapon(player_ptr, i)) || (i == INVEN_SUB_HAND && has_melee_weapon(player_ptr, i)) || i == INVEN_BOW) {
2379             continue;
2380         }
2381
2382         /* Fake value does not include unknown objects' value */
2383         if (!o_ptr->is_known() && !is_real_value) {
2384             continue;
2385         }
2386
2387         int bonus_to_h = o_ptr->to_h;
2388
2389         /* When wields only a weapon */
2390         if (pc.equals(PlayerClassType::NINJA)) {
2391             if (o_ptr->to_h > 0) {
2392                 bonus_to_h = (o_ptr->to_h + 1) / 2;
2393             }
2394         }
2395
2396         switch (player_melee_type(player_ptr)) {
2397         case MELEE_TYPE_BAREHAND_TWO: /* fall through */
2398         case MELEE_TYPE_WEAPON_TWOHAND:
2399             if (calc_hand == main_attack_hand(player_ptr)) {
2400                 hit += (int16_t)bonus_to_h;
2401             }
2402             break;
2403
2404         case MELEE_TYPE_BAREHAND_MAIN: /* fall through */
2405         case MELEE_TYPE_WEAPON_MAIN:
2406             if ((calc_hand == PLAYER_HAND_MAIN) && (i != INVEN_SUB_RING)) {
2407                 hit += (int16_t)bonus_to_h;
2408             }
2409             break;
2410
2411         case MELEE_TYPE_BAREHAND_SUB: /* fall through */
2412         case MELEE_TYPE_WEAPON_SUB:
2413             if ((calc_hand == PLAYER_HAND_SUB) && (i != INVEN_MAIN_RING)) {
2414                 hit += (int16_t)bonus_to_h;
2415             }
2416             break;
2417
2418         case MELEE_TYPE_WEAPON_DOUBLE:
2419             if (calc_hand == PLAYER_HAND_MAIN) {
2420                 if (i == INVEN_MAIN_RING) {
2421                     hit += (int16_t)bonus_to_h;
2422                 } else if (i != INVEN_SUB_RING) {
2423                     hit += (bonus_to_h > 0) ? (bonus_to_h + 1) / 2 : bonus_to_h;
2424                 }
2425             }
2426             if (calc_hand == PLAYER_HAND_SUB) {
2427                 if (i == INVEN_SUB_RING) {
2428                     hit += (int16_t)bonus_to_h;
2429                 } else if (i != INVEN_MAIN_RING) {
2430                     hit += (bonus_to_h > 0) ? bonus_to_h / 2 : bonus_to_h;
2431                 }
2432             }
2433             break;
2434
2435         case MELEE_TYPE_SHIELD_DOUBLE:
2436             break;
2437
2438         default:
2439             break;
2440         }
2441     }
2442
2443     /* Martial arts bonus */
2444     if (is_martial_arts_mode(player_ptr) && (!heavy_armor(player_ptr) || !pc.equals(PlayerClassType::BERSERKER))) {
2445         hit += (player_ptr->lev / 3);
2446     }
2447
2448     /* Two handed combat penalty */
2449     hit -= calc_double_weapon_penalty(player_ptr, slot);
2450
2451     // 朱雀の構えをとっているとき、格闘命中に -(レベル)/3 の修正を得る。
2452     if (PlayerClass(player_ptr).monk_stance_is(MonkStanceType::SUZAKU)) {
2453         if (is_martial_arts_mode(player_ptr) && calc_hand == PLAYER_HAND_MAIN) {
2454             hit -= (player_ptr->lev / 3);
2455         }
2456     }
2457
2458     return static_cast<short>(hit);
2459 }
2460
2461 static int16_t calc_to_hit_bow(PlayerType *player_ptr, bool is_real_value)
2462 {
2463     int16_t pow = 0;
2464
2465     pow += ((int)(adj_dex_th[player_ptr->stat_index[A_DEX]]) - 128);
2466     pow += ((int)(adj_str_th[player_ptr->stat_index[A_STR]]) - 128);
2467
2468     {
2469         ObjectType *o_ptr;
2470         o_ptr = &player_ptr->inventory_list[INVEN_BOW];
2471         if (o_ptr->k_idx) {
2472             if (o_ptr->curse_flags.has(CurseTraitType::LOW_MELEE)) {
2473                 if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
2474                     pow -= 15;
2475                 } else {
2476                     pow -= 5;
2477                 }
2478             }
2479         }
2480     }
2481
2482     auto player_stun = player_ptr->effects()->stun();
2483     pow -= player_stun->get_damage_penalty();
2484     if (is_blessed(player_ptr)) {
2485         pow += 10;
2486     }
2487
2488     if (is_hero(player_ptr)) {
2489         pow += 12;
2490     }
2491
2492     if (is_shero(player_ptr)) {
2493         pow -= 12;
2494     }
2495
2496     auto *o_ptr = &player_ptr->inventory_list[INVEN_BOW];
2497
2498     if (is_heavy_shoot(player_ptr, o_ptr)) {
2499         pow += 2 * (calc_bow_weight_limit(player_ptr) - o_ptr->weight / 10);
2500     }
2501
2502     if (o_ptr->k_idx) {
2503         if (o_ptr->k_idx && !is_heavy_shoot(player_ptr, &player_ptr->inventory_list[INVEN_BOW])) {
2504             if (PlayerClass(player_ptr).equals(PlayerClassType::SNIPER) && (player_ptr->tval_ammo == ItemKindType::BOLT)) {
2505                 pow += (10 + (player_ptr->lev / 5));
2506             }
2507         }
2508     }
2509
2510     // 武器以外の装備による修正
2511     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
2512         int bonus_to_h;
2513         o_ptr = &player_ptr->inventory_list[i];
2514         if (!o_ptr->k_idx || o_ptr->tval == ItemKindType::CAPTURE || (i == INVEN_MAIN_HAND && has_melee_weapon(player_ptr, i)) || (i == INVEN_SUB_HAND && has_melee_weapon(player_ptr, i)) || i == INVEN_BOW) {
2515             continue;
2516         }
2517
2518         bonus_to_h = o_ptr->to_h;
2519
2520         if (PlayerClass(player_ptr).equals(PlayerClassType::NINJA)) {
2521             if (o_ptr->to_h > 0) {
2522                 bonus_to_h = (o_ptr->to_h + 1) / 2;
2523             }
2524         }
2525
2526         if (is_real_value || o_ptr->is_known()) {
2527             pow += (int16_t)bonus_to_h;
2528         }
2529     }
2530
2531     pow -= calc_riding_bow_penalty(player_ptr);
2532
2533     return pow;
2534 }
2535
2536 static int16_t calc_to_damage_misc(PlayerType *player_ptr)
2537 {
2538     ObjectType *o_ptr;
2539
2540     int16_t to_dam = 0;
2541
2542     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
2543         o_ptr = &player_ptr->inventory_list[i];
2544         if (!o_ptr->k_idx) {
2545             continue;
2546         }
2547
2548         int bonus_to_d = o_ptr->to_d;
2549         if (PlayerClass(player_ptr).equals(PlayerClassType::NINJA)) {
2550             if (o_ptr->to_d > 0) {
2551                 bonus_to_d = (o_ptr->to_d + 1) / 2;
2552             }
2553         }
2554         to_dam += (int16_t)bonus_to_d;
2555     }
2556
2557     if (is_shero(player_ptr)) {
2558         to_dam += 3 + (player_ptr->lev / 5);
2559     }
2560
2561     auto player_stun = player_ptr->effects()->stun();
2562     to_dam -= player_stun->get_damage_penalty();
2563     to_dam += ((int)(adj_str_td[player_ptr->stat_index[A_STR]]) - 128);
2564     return to_dam;
2565 }
2566
2567 static int16_t calc_to_hit_misc(PlayerType *player_ptr)
2568 {
2569     ObjectType *o_ptr;
2570
2571     int16_t to_hit = 0;
2572
2573     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
2574         o_ptr = &player_ptr->inventory_list[i];
2575         if (!o_ptr->k_idx) {
2576             continue;
2577         }
2578
2579         int bonus_to_h = o_ptr->to_h;
2580         if (PlayerClass(player_ptr).equals(PlayerClassType::NINJA)) {
2581             if (o_ptr->to_h > 0) {
2582                 bonus_to_h = (o_ptr->to_h + 1) / 2;
2583             }
2584         }
2585         to_hit += (int16_t)bonus_to_h;
2586     }
2587
2588     if (is_blessed(player_ptr)) {
2589         to_hit += 10;
2590     }
2591
2592     if (is_hero(player_ptr)) {
2593         to_hit += 12;
2594     }
2595
2596     if (is_shero(player_ptr)) {
2597         to_hit += 12;
2598     }
2599
2600     auto player_stun = player_ptr->effects()->stun();
2601     to_hit -= player_stun->get_damage_penalty();
2602     to_hit += ((int)(adj_dex_th[player_ptr->stat_index[A_DEX]]) - 128);
2603     to_hit += ((int)(adj_str_th[player_ptr->stat_index[A_STR]]) - 128);
2604
2605     return to_hit;
2606 }
2607
2608 static DICE_NUMBER calc_to_weapon_dice_num(PlayerType *player_ptr, INVENTORY_IDX slot)
2609 {
2610     auto *o_ptr = &player_ptr->inventory_list[slot];
2611     return (player_ptr->riding > 0) && o_ptr->is_lance() ? 2 : 0;
2612 }
2613
2614 /*!
2615  * @brief プレイヤーの所持重量制限を計算する /
2616  * Computes current weight limit.
2617  * @return 制限重量(ポンド)
2618  */
2619 WEIGHT calc_weight_limit(PlayerType *player_ptr)
2620 {
2621     WEIGHT i = (WEIGHT)adj_str_wgt[player_ptr->stat_index[A_STR]] * 50;
2622     if (PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER)) {
2623         i = i * 3 / 2;
2624     }
2625     return i;
2626 }
2627
2628 /*!
2629  * @brief update のフラグに応じた更新をまとめて行う / Handle "update"
2630  * @details 更新処理の対象はプレイヤーの能力修正/光源寿命/HP/MP/魔法の学習状態、他多数の外界の状態判定。
2631  */
2632 void update_creature(PlayerType *player_ptr)
2633 {
2634     if (!player_ptr->update) {
2635         return;
2636     }
2637
2638     auto *floor_ptr = player_ptr->current_floor_ptr;
2639     if (any_bits(player_ptr->update, (PU_AUTODESTROY))) {
2640         reset_bits(player_ptr->update, PU_AUTODESTROY);
2641         autopick_delayed_alter(player_ptr);
2642     }
2643
2644     if (any_bits(player_ptr->update, (PU_COMBINE))) {
2645         reset_bits(player_ptr->update, PU_COMBINE);
2646         combine_pack(player_ptr);
2647     }
2648
2649     if (any_bits(player_ptr->update, (PU_REORDER))) {
2650         reset_bits(player_ptr->update, PU_REORDER);
2651         reorder_pack(player_ptr);
2652     }
2653
2654     if (any_bits(player_ptr->update, (PU_BONUS))) {
2655         reset_bits(player_ptr->update, PU_BONUS);
2656         PlayerAlignment(player_ptr).update_alignment();
2657         PlayerSkill ps(player_ptr);
2658         ps.apply_special_weapon_skill_max_values();
2659         ps.limit_weapon_skills_by_max_value();
2660         update_bonuses(player_ptr);
2661     }
2662
2663     if (any_bits(player_ptr->update, (PU_TORCH))) {
2664         reset_bits(player_ptr->update, PU_TORCH);
2665         update_lite_radius(player_ptr);
2666     }
2667
2668     if (any_bits(player_ptr->update, (PU_HP))) {
2669         reset_bits(player_ptr->update, PU_HP);
2670         update_max_hitpoints(player_ptr);
2671     }
2672
2673     if (any_bits(player_ptr->update, (PU_MANA))) {
2674         reset_bits(player_ptr->update, PU_MANA);
2675         update_max_mana(player_ptr);
2676     }
2677
2678     if (any_bits(player_ptr->update, (PU_SPELLS))) {
2679         reset_bits(player_ptr->update, PU_SPELLS);
2680         update_num_of_spells(player_ptr);
2681     }
2682
2683     if (!w_ptr->character_generated) {
2684         return;
2685     }
2686     if (w_ptr->character_icky_depth > 0) {
2687         return;
2688     }
2689     if (any_bits(player_ptr->update, (PU_UN_LITE))) {
2690         reset_bits(player_ptr->update, PU_UN_LITE);
2691         forget_lite(floor_ptr);
2692     }
2693
2694     if (any_bits(player_ptr->update, (PU_UN_VIEW))) {
2695         reset_bits(player_ptr->update, PU_UN_VIEW);
2696         forget_view(floor_ptr);
2697     }
2698
2699     if (any_bits(player_ptr->update, (PU_VIEW))) {
2700         reset_bits(player_ptr->update, PU_VIEW);
2701         update_view(player_ptr);
2702     }
2703
2704     if (any_bits(player_ptr->update, (PU_LITE))) {
2705         reset_bits(player_ptr->update, PU_LITE);
2706         update_lite(player_ptr);
2707     }
2708
2709     if (any_bits(player_ptr->update, (PU_FLOW))) {
2710         reset_bits(player_ptr->update, PU_FLOW);
2711         update_flow(player_ptr);
2712     }
2713
2714     if (any_bits(player_ptr->update, (PU_DISTANCE))) {
2715         reset_bits(player_ptr->update, PU_DISTANCE);
2716
2717         update_monsters(player_ptr, true);
2718     }
2719
2720     if (any_bits(player_ptr->update, (PU_MON_LITE))) {
2721         reset_bits(player_ptr->update, PU_MON_LITE);
2722         update_mon_lite(player_ptr);
2723     }
2724
2725     if (any_bits(player_ptr->update, (PU_DELAY_VIS))) {
2726         reset_bits(player_ptr->update, PU_DELAY_VIS);
2727         delayed_visual_update(player_ptr);
2728     }
2729
2730     if (any_bits(player_ptr->update, (PU_MONSTERS))) {
2731         reset_bits(player_ptr->update, PU_MONSTERS);
2732         update_monsters(player_ptr, false);
2733     }
2734 }
2735
2736 /*!
2737  * @brief プレイヤーが魔道書を一冊も持っていないかを判定する
2738  * @return 魔道書を一冊も持っていないならTRUEを返す
2739  */
2740 bool player_has_no_spellbooks(PlayerType *player_ptr)
2741 {
2742     ObjectType *o_ptr;
2743     for (int i = 0; i < INVEN_PACK; i++) {
2744         o_ptr = &player_ptr->inventory_list[i];
2745         if (o_ptr->k_idx && check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)) {
2746             return false;
2747         }
2748     }
2749
2750     auto *floor_ptr = player_ptr->current_floor_ptr;
2751     for (const auto this_o_idx : floor_ptr->grid_array[player_ptr->y][player_ptr->x].o_idx_list) {
2752         o_ptr = &floor_ptr->o_list[this_o_idx];
2753         if (o_ptr->k_idx && any_bits(o_ptr->marked, OM_FOUND) && check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)) {
2754             return false;
2755         }
2756     }
2757
2758     return true;
2759 }
2760
2761 /*!
2762  * @brief プレイヤーを指定座標に配置する / Place the player in the dungeon XXX XXX
2763  * @param x 配置先X座標
2764  * @param y 配置先Y座標
2765  * @return 配置に成功したらTRUE
2766  */
2767 bool player_place(PlayerType *player_ptr, POSITION y, POSITION x)
2768 {
2769     if (player_ptr->current_floor_ptr->grid_array[y][x].m_idx != 0) {
2770         return false;
2771     }
2772
2773     /* Save player location */
2774     player_ptr->y = y;
2775     player_ptr->x = x;
2776     return true;
2777 }
2778
2779 /*!
2780  * @brief 種族アンバライトが出血時パターンの上に乗った際のペナルティ処理
2781  */
2782 void wreck_the_pattern(PlayerType *player_ptr)
2783 {
2784     auto *floor_ptr = player_ptr->current_floor_ptr;
2785     int pattern_type = terrains_info[floor_ptr->grid_array[player_ptr->y][player_ptr->x].feat].subtype;
2786     if (pattern_type == PATTERN_TILE_WRECKED) {
2787         return;
2788     }
2789
2790     msg_print(_("パターンを血で汚してしまった!", "You bleed on the Pattern!"));
2791     msg_print(_("何か恐ろしい事が起こった!", "Something terrible happens!"));
2792
2793     if (!is_invuln(player_ptr)) {
2794         take_hit(player_ptr, DAMAGE_NOESCAPE, damroll(10, 8), _("パターン損壊", "corrupting the Pattern"));
2795     }
2796
2797     int to_ruin = randint1(45) + 35;
2798     while (to_ruin--) {
2799         POSITION r_y, r_x;
2800         scatter(player_ptr, &r_y, &r_x, player_ptr->y, player_ptr->x, 4, PROJECT_NONE);
2801
2802         if (pattern_tile(floor_ptr, r_y, r_x) && (terrains_info[floor_ptr->grid_array[r_y][r_x].feat].subtype != PATTERN_TILE_WRECKED)) {
2803             cave_set_feat(player_ptr, r_y, r_x, feat_pattern_corrupted);
2804         }
2805     }
2806
2807     cave_set_feat(player_ptr, player_ptr->y, player_ptr->x, feat_pattern_corrupted);
2808 }
2809
2810 /*!
2811  * @brief プレイヤーの経験値について整合性のためのチェックと調整を行う /
2812  * Advance experience levels and print experience
2813  */
2814 void check_experience(PlayerType *player_ptr)
2815 {
2816     if (player_ptr->exp < 0) {
2817         player_ptr->exp = 0;
2818     }
2819     if (player_ptr->max_exp < 0) {
2820         player_ptr->max_exp = 0;
2821     }
2822     if (player_ptr->max_max_exp < 0) {
2823         player_ptr->max_max_exp = 0;
2824     }
2825
2826     if (player_ptr->exp > PY_MAX_EXP) {
2827         player_ptr->exp = PY_MAX_EXP;
2828     }
2829     if (player_ptr->max_exp > PY_MAX_EXP) {
2830         player_ptr->max_exp = PY_MAX_EXP;
2831     }
2832     if (player_ptr->max_max_exp > PY_MAX_EXP) {
2833         player_ptr->max_max_exp = PY_MAX_EXP;
2834     }
2835
2836     if (player_ptr->exp > player_ptr->max_exp) {
2837         player_ptr->max_exp = player_ptr->exp;
2838     }
2839     if (player_ptr->max_exp > player_ptr->max_max_exp) {
2840         player_ptr->max_max_exp = player_ptr->max_exp;
2841     }
2842
2843     set_bits(player_ptr->redraw, PR_EXP);
2844     handle_stuff(player_ptr);
2845
2846     PlayerRace pr(player_ptr);
2847     bool android = pr.equals(PlayerRaceType::ANDROID);
2848     PLAYER_LEVEL old_lev = player_ptr->lev;
2849     while ((player_ptr->lev > 1) && (player_ptr->exp < ((android ? player_exp_a : player_exp)[player_ptr->lev - 2] * player_ptr->expfact / 100L))) {
2850         player_ptr->lev--;
2851         set_bits(player_ptr->update, PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
2852         set_bits(player_ptr->redraw, PR_LEV | PR_TITLE);
2853         set_bits(player_ptr->window_flags, PW_PLAYER);
2854         handle_stuff(player_ptr);
2855     }
2856
2857     bool level_reward = false;
2858     bool level_mutation = false;
2859     bool level_inc_stat = false;
2860     while ((player_ptr->lev < PY_MAX_LEVEL) && (player_ptr->exp >= ((android ? player_exp_a : player_exp)[player_ptr->lev - 1] * player_ptr->expfact / 100L))) {
2861         player_ptr->lev++;
2862         if (player_ptr->lev > player_ptr->max_plv) {
2863             player_ptr->max_plv = player_ptr->lev;
2864
2865             if (PlayerClass(player_ptr).equals(PlayerClassType::CHAOS_WARRIOR) || player_ptr->muta.has(PlayerMutationType::CHAOS_GIFT)) {
2866                 level_reward = true;
2867             }
2868             if (pr.equals(PlayerRaceType::BEASTMAN)) {
2869                 if (one_in_(5)) {
2870                     level_mutation = true;
2871                 }
2872             }
2873             level_inc_stat = true;
2874
2875             exe_write_diary(player_ptr, DIARY_LEVELUP, player_ptr->lev, nullptr);
2876         }
2877
2878         sound(SOUND_LEVEL);
2879         msg_format(_("レベル %d にようこそ。", "Welcome to level %d."), player_ptr->lev);
2880         set_bits(player_ptr->update, (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS));
2881         set_bits(player_ptr->redraw, (PR_LEV | PR_TITLE | PR_EXP));
2882         set_bits(player_ptr->window_flags, (PW_PLAYER | PW_SPELL | PW_INVEN));
2883         player_ptr->level_up_message = true;
2884         handle_stuff(player_ptr);
2885
2886         player_ptr->level_up_message = false;
2887         if (level_inc_stat) {
2888             if (!(player_ptr->max_plv % 10)) {
2889                 int choice;
2890                 screen_save();
2891                 while (true) {
2892                     int n;
2893                     char tmp[32];
2894
2895                     cnv_stat(player_ptr->stat_max[0], tmp);
2896                     prt(format(_("        a) 腕力 (現在値 %s)", "        a) Str (cur %s)"), tmp), 2, 14);
2897                     cnv_stat(player_ptr->stat_max[1], tmp);
2898                     prt(format(_("        b) 知能 (現在値 %s)", "        b) Int (cur %s)"), tmp), 3, 14);
2899                     cnv_stat(player_ptr->stat_max[2], tmp);
2900                     prt(format(_("        c) 賢さ (現在値 %s)", "        c) Wis (cur %s)"), tmp), 4, 14);
2901                     cnv_stat(player_ptr->stat_max[3], tmp);
2902                     prt(format(_("        d) 器用 (現在値 %s)", "        d) Dex (cur %s)"), tmp), 5, 14);
2903                     cnv_stat(player_ptr->stat_max[4], tmp);
2904                     prt(format(_("        e) 耐久 (現在値 %s)", "        e) Con (cur %s)"), tmp), 6, 14);
2905                     cnv_stat(player_ptr->stat_max[5], tmp);
2906                     prt(format(_("        f) 魅力 (現在値 %s)", "        f) Chr (cur %s)"), tmp), 7, 14);
2907
2908                     prt("", 8, 14);
2909                     prt(_("        どの能力値を上げますか?", "        Which stat do you want to raise?"), 1, 14);
2910
2911                     while (true) {
2912                         choice = inkey();
2913                         if ((choice >= 'a') && (choice <= 'f')) {
2914                             break;
2915                         }
2916                     }
2917                     for (n = 0; n < A_MAX; n++) {
2918                         if (n != choice - 'a') {
2919                             prt("", n + 2, 14);
2920                         }
2921                     }
2922                     if (get_check(_("よろしいですか?", "Are you sure? "))) {
2923                         break;
2924                     }
2925                 }
2926                 do_inc_stat(player_ptr, choice - 'a');
2927                 screen_load();
2928             } else if (!(player_ptr->max_plv % 2)) {
2929                 do_inc_stat(player_ptr, randint0(6));
2930             }
2931         }
2932
2933         if (level_mutation) {
2934             msg_print(_("あなたは変わった気がする...", "You feel different..."));
2935             (void)gain_mutation(player_ptr, 0);
2936             level_mutation = false;
2937         }
2938
2939         /*
2940          * 報酬でレベルが上ると再帰的に check_experience(player_ptr) が
2941          * 呼ばれるので順番を最後にする。
2942          */
2943         if (level_reward) {
2944             patron_list[player_ptr->chaos_patron].gain_level_reward(player_ptr, 0);
2945             level_reward = false;
2946         }
2947
2948         set_bits(player_ptr->update, PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
2949         set_bits(player_ptr->redraw, (PR_LEV | PR_TITLE));
2950         set_bits(player_ptr->window_flags, (PW_PLAYER | PW_SPELL));
2951         handle_stuff(player_ptr);
2952     }
2953
2954     if (old_lev != player_ptr->lev) {
2955         autopick_load_pref(player_ptr, false);
2956     }
2957 }
2958
2959 /*!
2960  * @brief 現在の修正後能力値を3~17及び18/xxx形式に変換する / Converts stat num into a six-char (right justified) string
2961  * @param val 能力値
2962  * @param out_val 出力先文字列ポインタ
2963  */
2964 void cnv_stat(int val, char *out_val)
2965 {
2966     if (val <= 18) {
2967         sprintf(out_val, "    %2d", val);
2968         return;
2969     }
2970
2971     int bonus = (val - 18);
2972     if (bonus >= 220) {
2973         sprintf(out_val, "18/%3s", "***");
2974     } else if (bonus >= 100) {
2975         sprintf(out_val, "18/%03d", bonus);
2976     } else {
2977         sprintf(out_val, " 18/%02d", bonus);
2978     }
2979 }
2980
2981 /*!
2982  * @brief 能力値現在値から3~17及び18/xxx様式に基づく加減算を行う。
2983  * Modify a stat value by a "modifier", return new value
2984  * @param value 現在値
2985  * @param amount 加減算値
2986  * @return 加減算後の値
2987  * @details
2988  * <pre>
2989  * Stats go up: 3,4,...,17,18,18/10,18/20,...,18/220
2990  * Or even: 18/13, 18/23, 18/33, ..., 18/220
2991  * Stats go down: 18/220, 18/210,..., 18/10, 18, 17, ..., 3
2992  * Or even: 18/13, 18/03, 18, 17, ..., 3
2993  * </pre>
2994  */
2995 int16_t modify_stat_value(int value, int amount)
2996 {
2997     if (amount > 0) {
2998         for (int i = 0; i < amount; i++) {
2999             if (value < 18) {
3000                 value++;
3001             } else {
3002                 value += 10;
3003             }
3004         }
3005     } else if (amount < 0) {
3006         for (int i = 0; i < (0 - amount); i++) {
3007             if (value >= 18 + 10) {
3008                 value -= 10;
3009             } else if (value > 18) {
3010                 value = 18;
3011             } else if (value > 3) {
3012                 value--;
3013             }
3014         }
3015     }
3016
3017     return (int16_t)value;
3018 }
3019
3020 /*!
3021  * @brief スコアを計算する /
3022  * Hack -- Calculates the total number of points earned         -JWT-
3023  * @details
3024  */
3025 long calc_score(PlayerType *player_ptr)
3026 {
3027     int arena_win = std::min<int>(player_ptr->arena_number, MAX_ARENA_MONS);
3028
3029     int mult = 100;
3030     if (!preserve_mode) {
3031         mult += 10;
3032     }
3033     if (!autoroller) {
3034         mult += 10;
3035     }
3036     if (!smart_learn) {
3037         mult -= 20;
3038     }
3039     if (smart_cheat) {
3040         mult += 30;
3041     }
3042     if (ironman_shops) {
3043         mult += 50;
3044     }
3045     if (ironman_small_levels) {
3046         mult += 10;
3047     }
3048     if (ironman_empty_levels) {
3049         mult += 20;
3050     }
3051     if (!powerup_home) {
3052         mult += 50;
3053     }
3054     if (ironman_rooms) {
3055         mult += 100;
3056     }
3057     if (ironman_nightmare) {
3058         mult += 100;
3059     }
3060
3061     if (mult < 5) {
3062         mult = 5;
3063     }
3064
3065     DEPTH max_dl = 0;
3066     for (const auto &d_ref : dungeons_info) {
3067         if (max_dl < max_dlv[d_ref.idx]) {
3068             max_dl = max_dlv[d_ref.idx];
3069         }
3070     }
3071
3072     uint32_t point_l = (player_ptr->max_max_exp + (100 * max_dl));
3073     uint32_t point_h = point_l / 0x10000L;
3074     point_l = point_l % 0x10000L;
3075     point_h *= mult;
3076     point_l *= mult;
3077     point_h += point_l / 0x10000L;
3078     point_l %= 0x10000L;
3079
3080     point_l += ((point_h % 100) << 16);
3081     point_h /= 100;
3082     point_l /= 100;
3083
3084     uint32_t point = (point_h << 16) + (point_l);
3085     if (player_ptr->arena_number >= 0) {
3086         point += (arena_win * arena_win * (arena_win > 29 ? 1000 : 100));
3087     }
3088
3089     if (ironman_downward) {
3090         point *= 2;
3091     }
3092     if (PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER)) {
3093         if (PlayerRace(player_ptr).equals(PlayerRaceType::SPECTRE)) {
3094             point = point / 5;
3095         }
3096     }
3097
3098     if ((player_ptr->ppersonality == PERSONALITY_MUNCHKIN) && point) {
3099         point = 1;
3100         if (w_ptr->total_winner) {
3101             point = 2;
3102         }
3103     }
3104
3105     return point;
3106 }
3107
3108 /*!
3109  * @param player_ptr プレイヤーへの参照ポインタ
3110  * @return 祝福状態ならばTRUE
3111  */
3112 bool is_blessed(PlayerType *player_ptr)
3113 {
3114     return player_ptr->blessed || music_singing(player_ptr, MUSIC_BLESS) || SpellHex(player_ptr).is_spelling_specific(HEX_BLESS);
3115 }
3116
3117 bool is_tim_esp(PlayerType *player_ptr)
3118 {
3119     auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
3120     auto sniper_concent = sniper_data ? sniper_data->concent : 0;
3121     return player_ptr->tim_esp || music_singing(player_ptr, MUSIC_MIND) || (sniper_concent >= CONCENT_TELE_THRESHOLD);
3122 }
3123
3124 bool is_tim_stealth(PlayerType *player_ptr)
3125 {
3126     return player_ptr->tim_stealth || music_singing(player_ptr, MUSIC_STEALTH);
3127 }
3128
3129 bool is_time_limit_esp(PlayerType *player_ptr)
3130 {
3131     auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
3132     auto sniper_concent = sniper_data ? sniper_data->concent : 0;
3133     return player_ptr->tim_esp || music_singing(player_ptr, MUSIC_MIND) || (sniper_concent >= CONCENT_TELE_THRESHOLD);
3134 }
3135
3136 bool is_time_limit_stealth(PlayerType *player_ptr)
3137 {
3138     return player_ptr->tim_stealth || music_singing(player_ptr, MUSIC_STEALTH);
3139 }
3140
3141 /*!
3142  * @brief 口を使う継続的な処理を中断する
3143  * @param player_ptr プレイヤーへの参照ポインタ
3144  */
3145 void stop_mouth(PlayerType *player_ptr)
3146 {
3147     if (music_singing_any(player_ptr)) {
3148         stop_singing(player_ptr);
3149     }
3150
3151     if (SpellHex(player_ptr).is_spelling_any()) {
3152         (void)SpellHex(player_ptr).stop_all_spells();
3153     }
3154 }
3155
3156 bool is_fast(PlayerType *player_ptr)
3157 {
3158     return player_ptr->effects()->acceleration()->is_fast() || music_singing(player_ptr, MUSIC_SPEED) || music_singing(player_ptr, MUSIC_SHERO);
3159 }
3160
3161 bool is_invuln(PlayerType *player_ptr)
3162 {
3163     return player_ptr->invuln || music_singing(player_ptr, MUSIC_INVULN);
3164 }
3165
3166 bool is_hero(PlayerType *player_ptr)
3167 {
3168     return player_ptr->hero || music_singing(player_ptr, MUSIC_HERO) || music_singing(player_ptr, MUSIC_SHERO);
3169 }
3170
3171 bool is_shero(PlayerType *player_ptr)
3172 {
3173     return player_ptr->shero || PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER);
3174 }
3175
3176 bool is_echizen(PlayerType *player_ptr)
3177 {
3178     return (player_ptr->ppersonality == PERSONALITY_COMBAT) || (player_ptr->inventory_list[INVEN_BOW].fixed_artifact_idx == FixedArtifactId::CRIMSON);
3179 }
3180
3181 bool is_chargeman(PlayerType *player_ptr)
3182 {
3183     return player_ptr->ppersonality == PERSONALITY_CHARGEMAN;
3184 }
3185
3186 WEIGHT calc_weapon_weight_limit(PlayerType *player_ptr)
3187 {
3188     WEIGHT weight = adj_str_hold[player_ptr->stat_index[A_STR]];
3189
3190     if (has_two_handed_weapons(player_ptr)) {
3191         weight *= 2;
3192     }
3193
3194     return weight;
3195 }
3196
3197 WEIGHT calc_bow_weight_limit(PlayerType *player_ptr)
3198 {
3199     WEIGHT weight = adj_str_hold[player_ptr->stat_index[A_STR]];
3200
3201     return weight;
3202 }
3203
3204 static player_hand main_attack_hand(PlayerType *player_ptr)
3205 {
3206     switch (player_melee_type(player_ptr)) {
3207     case MELEE_TYPE_BAREHAND_TWO:
3208         return PLAYER_HAND_MAIN;
3209     case MELEE_TYPE_BAREHAND_MAIN:
3210         return PLAYER_HAND_MAIN;
3211     case MELEE_TYPE_BAREHAND_SUB:
3212         return PLAYER_HAND_SUB;
3213     case MELEE_TYPE_WEAPON_MAIN:
3214         return PLAYER_HAND_MAIN;
3215     case MELEE_TYPE_WEAPON_SUB:
3216         return PLAYER_HAND_SUB;
3217     case MELEE_TYPE_WEAPON_TWOHAND:
3218         return has_melee_weapon(player_ptr, INVEN_MAIN_HAND) ? PLAYER_HAND_MAIN : PLAYER_HAND_SUB;
3219     case MELEE_TYPE_WEAPON_DOUBLE:
3220         return PLAYER_HAND_MAIN;
3221     case MELEE_TYPE_SHIELD_DOUBLE:
3222         return PLAYER_HAND_MAIN;
3223     }
3224     return PLAYER_HAND_MAIN;
3225 }
3226
3227 bool set_quick_and_tiny(PlayerType *player_ptr)
3228 {
3229     auto is_quickly_tiny = player_ptr->inventory_list[INVEN_MAIN_HAND].fixed_artifact_idx == FixedArtifactId::QUICKTHORN;
3230     is_quickly_tiny &= player_ptr->inventory_list[INVEN_SUB_HAND].fixed_artifact_idx == FixedArtifactId::TINYTHORN;
3231     return is_quickly_tiny;
3232 }
3233
3234 bool set_musasi(PlayerType *player_ptr)
3235 {
3236     auto is_musasi = player_ptr->inventory_list[INVEN_MAIN_HAND].fixed_artifact_idx == FixedArtifactId::MUSASI_KATANA;
3237     is_musasi &= player_ptr->inventory_list[INVEN_SUB_HAND].fixed_artifact_idx == FixedArtifactId::MUSASI_WAKIZASI;
3238     return is_musasi;
3239 }
3240
3241 bool set_icing_and_twinkle(PlayerType *player_ptr)
3242 {
3243     auto can_call_ice_wind_saga = player_ptr->inventory_list[INVEN_MAIN_HAND].fixed_artifact_idx == FixedArtifactId::ICINGDEATH;
3244     can_call_ice_wind_saga &= player_ptr->inventory_list[INVEN_SUB_HAND].fixed_artifact_idx == FixedArtifactId::TWINKLE;
3245     return can_call_ice_wind_saga;
3246 }
3247
3248 bool set_anubis_and_chariot(PlayerType *player_ptr)
3249 {
3250     auto is_anubis_chariot = player_ptr->inventory_list[INVEN_MAIN_HAND].fixed_artifact_idx == FixedArtifactId::ANUBIS;
3251     is_anubis_chariot &= player_ptr->inventory_list[INVEN_SUB_HAND].fixed_artifact_idx == FixedArtifactId::SILVER_CHARIOT;
3252     return is_anubis_chariot;
3253 }