OSDN Git Service

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