OSDN Git Service

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