OSDN Git Service

[Refactor] #2807 Renamed monster-race-definition.h to monster-race-info.h
[hengbandforosx/hengbandosx.git] / src / dungeon / dungeon-processor.cpp
1 #include "dungeon/dungeon-processor.h"
2 #include "cmd-building/cmd-building.h"
3 #include "cmd-io/cmd-dump.h"
4 #include "core/disturbance.h"
5 #include "core/object-compressor.h"
6 #include "core/player-processor.h"
7 #include "core/player-redraw-types.h"
8 #include "core/player-update-types.h"
9 #include "core/stuff-handler.h"
10 #include "core/turn-compensator.h"
11 #include "core/window-redrawer.h"
12 #include "dungeon/quest.h"
13 #include "floor/floor-leaver.h"
14 #include "floor/floor-save-util.h"
15 #include "floor/floor-save.h"
16 #include "game-option/cheat-options.h"
17 #include "game-option/map-screen-options.h"
18 #include "game-option/play-record-options.h"
19 #include "hpmp/hp-mp-regenerator.h"
20 #include "io/cursor.h"
21 #include "io/input-key-requester.h"
22 #include "io/write-diary.h"
23 #include "market/arena.h"
24 #include "mind/mind-ninja.h"
25 #include "monster-race/monster-race.h"
26 #include "monster-race/race-flags1.h"
27 #include "monster/monster-compaction.h"
28 #include "monster/monster-processor.h"
29 #include "monster/monster-status.h"
30 #include "monster/monster-util.h"
31 #include "pet/pet-util.h"
32 #include "player-base/player-class.h"
33 #include "player/special-defense-types.h"
34 #include "realm/realm-song-numbers.h"
35 #include "realm/realm-song.h"
36 #include "spell-realm/spells-song.h"
37 #include "system/dungeon-info.h"
38 #include "system/floor-type-definition.h"
39 #include "system/monster-race-info.h"
40 #include "system/player-type-definition.h"
41 #include "target/target-checker.h"
42 #include "util/bit-flags-calculator.h"
43 #include "view/display-messages.h"
44 #include "world/world-turn-processor.h"
45 #include "world/world.h"
46
47 /*!
48  * process_player()、process_world() をcore.c から移設するのが先.
49  * process_upkeep_with_speed() はこの関数と同じところでOK
50  * @brief 現在プレイヤーがいるダンジョンの全体処理 / Interact with the current dungeon level.
51  * @details
52  * <p>
53  * この関数から現在の階層を出る、プレイヤーがキャラが死ぬ、
54  * ゲームを終了するかのいずれかまでループする。
55  * </p>
56  * <p>
57  * This function will not exit until the level is completed,\n
58  * the user dies, or the game is terminated.\n
59  * </p>
60  */
61 void process_dungeon(PlayerType *player_ptr, bool load_game)
62 {
63     auto *floor_ptr = player_ptr->current_floor_ptr;
64     floor_ptr->base_level = floor_ptr->dun_level;
65     w_ptr->is_loading_now = false;
66     player_ptr->leaving = false;
67
68     command_cmd = 0;
69     command_rep = 0;
70     command_arg = 0;
71     command_dir = 0;
72
73     target_who = 0;
74     player_ptr->pet_t_m_idx = 0;
75     player_ptr->riding_t_m_idx = 0;
76     player_ptr->ambush_flag = false;
77     health_track(player_ptr, 0);
78
79     disturb(player_ptr, true, true);
80     auto quest_num = quest_number(player_ptr, floor_ptr->dun_level);
81     const auto &quest_list = QuestList::get_instance();
82     auto *questor_ptr = &monraces_info[quest_list[quest_num].r_idx];
83     if (inside_quest(quest_num)) {
84         set_bits(questor_ptr->flags1, RF1_QUESTOR);
85     }
86
87     if (player_ptr->max_plv < player_ptr->lev) {
88         player_ptr->max_plv = player_ptr->lev;
89     }
90
91     if ((max_dlv[player_ptr->dungeon_idx] < floor_ptr->dun_level) && !inside_quest(floor_ptr->quest_number)) {
92         max_dlv[player_ptr->dungeon_idx] = floor_ptr->dun_level;
93         if (record_maxdepth) {
94             exe_write_diary(player_ptr, DIARY_MAXDEAPTH, floor_ptr->dun_level, nullptr);
95         }
96     }
97
98     (void)calculate_upkeep(player_ptr);
99     panel_bounds_center();
100     verify_panel(player_ptr);
101     msg_erase();
102
103     w_ptr->character_xtra = true;
104     set_bits(player_ptr->window_flags, PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER | PW_MONSTER | PW_OVERHEAD | PW_DUNGEON);
105     set_bits(player_ptr->redraw, PR_WIPE | PR_BASIC | PR_EXTRA | PR_EQUIPPY | PR_MAP);
106     set_bits(player_ptr->update, PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_VIEW | PU_LITE | PU_MON_LITE | PU_TORCH | PU_MONSTERS | PU_DISTANCE | PU_FLOW);
107     handle_stuff(player_ptr);
108
109     w_ptr->character_xtra = false;
110     set_bits(player_ptr->update, PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_COMBINE | PU_REORDER);
111     handle_stuff(player_ptr);
112     term_fresh();
113
114     auto no_feeling_quest = (quest_num == QuestId::OBERON);
115     no_feeling_quest |= (quest_num == QuestId::SERPENT);
116     no_feeling_quest |= none_bits(quest_list[quest_num].flags, QUEST_FLAG_PRESET);
117     if (inside_quest(quest_num) && quest_type::is_fixed(quest_num) && !no_feeling_quest) {
118         do_cmd_feeling(player_ptr);
119     }
120
121     if (player_ptr->phase_out) {
122         if (load_game) {
123             player_ptr->energy_need = 0;
124             update_gambling_monsters(player_ptr);
125         } else {
126             msg_print(_("試合開始!", "Ready..Fight!"));
127             msg_print(nullptr);
128         }
129     }
130
131     if (PlayerClass(player_ptr).equals(PlayerClassType::BARD) && (get_singing_song_effect(player_ptr) > MUSIC_DETECT)) {
132         set_singing_song_effect(player_ptr, MUSIC_DETECT);
133     }
134
135     if (!player_ptr->playing || player_ptr->is_dead) {
136         return;
137     }
138
139     if (!inside_quest(floor_ptr->quest_number) && (player_ptr->dungeon_idx == DUNGEON_ANGBAND)) {
140         quest_discovery(random_quest_number(player_ptr, floor_ptr->dun_level));
141         floor_ptr->quest_number = random_quest_number(player_ptr, floor_ptr->dun_level);
142     }
143
144     const auto &dungeon = dungeons_info[player_ptr->dungeon_idx];
145     const auto guardian = dungeon.final_guardian;
146     if ((floor_ptr->dun_level == dungeon.maxdepth) && MonsterRace(guardian).is_valid()) {
147         const auto &guardian_ref = monraces_info[guardian];
148         if (guardian_ref.max_num) {
149 #ifdef JP
150             msg_format("この階には%sの主である%sが棲んでいる。", dungeon.name.data(), guardian_ref.name.data());
151 #else
152             msg_format("%^s lives in this level as the keeper of %s.", guardian_ref.name.data(), dungeon.name.data());
153 #endif
154         }
155     }
156
157     if (!load_game) {
158         set_superstealth(player_ptr, false);
159     }
160
161     floor_ptr->monster_level = floor_ptr->base_level;
162     floor_ptr->object_level = floor_ptr->base_level;
163     w_ptr->is_loading_now = true;
164     if (player_ptr->energy_need > 0 && !player_ptr->phase_out && (floor_ptr->dun_level || player_ptr->leaving_dungeon || floor_ptr->inside_arena)) {
165         player_ptr->energy_need = 0;
166     }
167
168     player_ptr->leaving_dungeon = false;
169     mproc_init(floor_ptr);
170
171     while (true) {
172         if ((floor_ptr->m_cnt + 32 > w_ptr->max_m_idx) && !player_ptr->phase_out) {
173             compact_monsters(player_ptr, 64);
174         }
175
176         if ((floor_ptr->m_cnt + 32 < floor_ptr->m_max) && !player_ptr->phase_out) {
177             compact_monsters(player_ptr, 0);
178         }
179
180         if (floor_ptr->o_cnt + 32 > w_ptr->max_o_idx) {
181             compact_objects(player_ptr, 64);
182         }
183
184         if (floor_ptr->o_cnt + 32 < floor_ptr->o_max) {
185             compact_objects(player_ptr, 0);
186         }
187
188         process_player(player_ptr);
189         process_upkeep_with_speed(player_ptr);
190         handle_stuff(player_ptr);
191
192         move_cursor_relative(player_ptr->y, player_ptr->x);
193         if (fresh_after) {
194             term_fresh_force();
195         }
196
197         if (!player_ptr->playing || player_ptr->is_dead) {
198             break;
199         }
200
201         process_monsters(player_ptr);
202         handle_stuff(player_ptr);
203
204         move_cursor_relative(player_ptr->y, player_ptr->x);
205         if (fresh_after) {
206             term_fresh_force();
207         }
208
209         if (!player_ptr->playing || player_ptr->is_dead) {
210             break;
211         }
212
213         WorldTurnProcessor(player_ptr).process_world();
214         handle_stuff(player_ptr);
215
216         move_cursor_relative(player_ptr->y, player_ptr->x);
217         if (fresh_after) {
218             term_fresh_force();
219         }
220
221         if (!player_ptr->playing || player_ptr->is_dead) {
222             break;
223         }
224
225         w_ptr->game_turn++;
226         if (w_ptr->dungeon_turn < w_ptr->dungeon_turn_limit) {
227             if (!player_ptr->wild_mode || wild_regen) {
228                 w_ptr->dungeon_turn++;
229             } else if (player_ptr->wild_mode && !(w_ptr->game_turn % ((MAX_HGT + MAX_WID) / 2))) {
230                 w_ptr->dungeon_turn++;
231             }
232         }
233
234         prevent_turn_overflow(player_ptr);
235
236         if (player_ptr->leaving) {
237             break;
238         }
239
240         if (wild_regen) {
241             wild_regen--;
242         }
243     }
244
245     if ((inside_quest(quest_num)) && questor_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
246         reset_bits(questor_ptr->flags1, RF1_QUESTOR);
247     }
248
249     if (player_ptr->playing && !player_ptr->is_dead) {
250         /*
251          * Maintain Unique monsters and artifact, save current
252          * floor, then prepare next floor
253          */
254         leave_floor(player_ptr);
255         reinit_wilderness = false;
256     }
257
258     write_level = true;
259 }