OSDN Git Service

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