OSDN Git Service

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