OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[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/stuff-handler.h"
8 #include "core/turn-compensator.h"
9 #include "core/window-redrawer.h"
10 #include "dungeon/quest.h"
11 #include "floor/floor-leaver.h"
12 #include "floor/floor-save-util.h"
13 #include "floor/floor-save.h"
14 #include "game-option/cheat-options.h"
15 #include "game-option/map-screen-options.h"
16 #include "game-option/play-record-options.h"
17 #include "hpmp/hp-mp-regenerator.h"
18 #include "io/cursor.h"
19 #include "io/input-key-requester.h"
20 #include "io/write-diary.h"
21 #include "market/arena.h"
22 #include "mind/mind-ninja.h"
23 #include "monster-race/monster-race.h"
24 #include "monster-race/race-flags1.h"
25 #include "monster/monster-compaction.h"
26 #include "monster/monster-processor.h"
27 #include "monster/monster-status.h"
28 #include "monster/monster-util.h"
29 #include "pet/pet-util.h"
30 #include "player-base/player-class.h"
31 #include "player/special-defense-types.h"
32 #include "realm/realm-song-numbers.h"
33 #include "realm/realm-song.h"
34 #include "spell-realm/spells-song.h"
35 #include "system/angband-system.h"
36 #include "system/dungeon-info.h"
37 #include "system/floor-type-definition.h"
38 #include "system/monster-race-info.h"
39 #include "system/player-type-definition.h"
40 #include "system/redrawing-flags-updater.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 static void redraw_character_xtra(PlayerType *player_ptr)
48 {
49     w_ptr->character_xtra = true;
50     auto &rfu = RedrawingFlagsUpdater::get_instance();
51     static constexpr auto flags_swrf = {
52         SubWindowRedrawingFlag::INVENTORY,
53         SubWindowRedrawingFlag::EQUIPMENT,
54         SubWindowRedrawingFlag::SPELL,
55         SubWindowRedrawingFlag::PLAYER,
56         SubWindowRedrawingFlag::MONSTER_LORE,
57         SubWindowRedrawingFlag::OVERHEAD,
58         SubWindowRedrawingFlag::DUNGEON,
59     };
60     rfu.set_flags(flags_swrf);
61     static constexpr auto flags_mwrf = {
62         MainWindowRedrawingFlag::WIPE,
63         MainWindowRedrawingFlag::BASIC,
64         MainWindowRedrawingFlag::EXTRA,
65         MainWindowRedrawingFlag::EQUIPPY,
66         MainWindowRedrawingFlag::MAP,
67     };
68     rfu.set_flags(flags_mwrf);
69     auto flags_srf = {
70         StatusRecalculatingFlag::BONUS,
71         StatusRecalculatingFlag::HP,
72         StatusRecalculatingFlag::MP,
73         StatusRecalculatingFlag::SPELLS,
74         StatusRecalculatingFlag::VIEW,
75         StatusRecalculatingFlag::LITE,
76         StatusRecalculatingFlag::MONSTER_LITE,
77         StatusRecalculatingFlag::TORCH,
78         StatusRecalculatingFlag::MONSTER_STATUSES,
79         StatusRecalculatingFlag::DISTANCE,
80         StatusRecalculatingFlag::FLOW,
81     };
82     rfu.set_flags(flags_srf);
83     handle_stuff(player_ptr);
84     w_ptr->character_xtra = false;
85 }
86
87 /*!
88  * process_player()、process_world() をcore.c から移設するのが先.
89  * process_upkeep_with_speed() はこの関数と同じところでOK
90  * @brief 現在プレイヤーがいるダンジョンの全体処理 / Interact with the current dungeon level.
91  * @details
92  * <p>
93  * この関数から現在の階層を出る、プレイヤーがキャラが死ぬ、
94  * ゲームを終了するかのいずれかまでループする。
95  * </p>
96  * <p>
97  * This function will not exit until the level is completed,\n
98  * the user dies, or the game is terminated.\n
99  * </p>
100  */
101 void process_dungeon(PlayerType *player_ptr, bool load_game)
102 {
103     auto &floor = *player_ptr->current_floor_ptr;
104     floor.base_level = floor.dun_level;
105     w_ptr->is_loading_now = false;
106     player_ptr->leaving = false;
107
108     command_cmd = 0;
109     command_rep = 0;
110     command_arg = 0;
111     command_dir = 0;
112
113     target_who = 0;
114     player_ptr->pet_t_m_idx = 0;
115     player_ptr->riding_t_m_idx = 0;
116     player_ptr->ambush_flag = false;
117     health_track(player_ptr, 0);
118
119     disturb(player_ptr, true, true);
120     auto quest_num = floor.get_quest_id();
121     const auto &quest_list = QuestList::get_instance();
122     auto *questor_ptr = &monraces_info[quest_list[quest_num].r_idx];
123     if (inside_quest(quest_num)) {
124         questor_ptr->misc_flags.set(MonsterMiscType::QUESTOR);
125     }
126
127     if (player_ptr->max_plv < player_ptr->lev) {
128         player_ptr->max_plv = player_ptr->lev;
129     }
130
131     if ((max_dlv[floor.dungeon_idx] < floor.dun_level) && !floor.is_in_quest()) {
132         max_dlv[floor.dungeon_idx] = floor.dun_level;
133         if (record_maxdepth) {
134             exe_write_diary(player_ptr, DiaryKind::MAXDEAPTH, floor.dun_level);
135         }
136     }
137
138     (void)calculate_upkeep(player_ptr);
139     panel_bounds_center();
140     verify_panel(player_ptr);
141     msg_erase();
142
143     redraw_character_xtra(player_ptr);
144     auto flags_srf = {
145         StatusRecalculatingFlag::BONUS,
146         StatusRecalculatingFlag::HP,
147         StatusRecalculatingFlag::MP,
148         StatusRecalculatingFlag::SPELLS,
149         StatusRecalculatingFlag::COMBINATION,
150         StatusRecalculatingFlag::REORDER,
151     };
152     RedrawingFlagsUpdater::get_instance().set_flags(flags_srf);
153     handle_stuff(player_ptr);
154     term_fresh();
155
156     auto no_feeling_quest = (quest_num == QuestId::OBERON);
157     no_feeling_quest |= (quest_num == QuestId::SERPENT);
158     no_feeling_quest |= none_bits(quest_list[quest_num].flags, QUEST_FLAG_PRESET);
159     if (inside_quest(quest_num) && QuestType::is_fixed(quest_num) && !no_feeling_quest) {
160         do_cmd_feeling(player_ptr);
161     }
162
163     const auto is_watching = AngbandSystem::get_instance().is_phase_out();
164     if (is_watching) {
165         if (load_game) {
166             player_ptr->energy_need = 0;
167             update_gambling_monsters(player_ptr);
168         } else {
169             msg_print(_("試合開始!", "Ready..Fight!"));
170             msg_print(nullptr);
171         }
172     }
173
174     if (PlayerClass(player_ptr).equals(PlayerClassType::BARD) && (get_singing_song_effect(player_ptr) > MUSIC_DETECT)) {
175         set_singing_song_effect(player_ptr, MUSIC_DETECT);
176     }
177
178     if (!player_ptr->playing || player_ptr->is_dead) {
179         return;
180     }
181
182     if (!floor.is_in_quest() && (floor.dungeon_idx == DUNGEON_ANGBAND)) {
183         const auto random_quest_id = floor.get_random_quest_id();
184         quest_discovery(random_quest_id);
185         floor.quest_number = random_quest_id;
186     }
187
188     const auto &dungeon = floor.get_dungeon_definition();
189     const auto guardian = dungeon.final_guardian;
190     if ((floor.dun_level == dungeon.maxdepth) && MonsterRace(guardian).is_valid()) {
191         const auto &guardian_ref = monraces_info[guardian];
192         if (guardian_ref.max_num) {
193 #ifdef JP
194             msg_format("この階には%sの主である%sが棲んでいる。", dungeon.name.data(), guardian_ref.name.data());
195 #else
196             msg_format("%s^ lives in this level as the keeper of %s.", guardian_ref.name.data(), dungeon.name.data());
197 #endif
198         }
199     }
200
201     if (!load_game) {
202         set_superstealth(player_ptr, false);
203     }
204
205     floor.monster_level = floor.base_level;
206     floor.object_level = floor.base_level;
207     w_ptr->is_loading_now = true;
208     if (player_ptr->energy_need > 0 && !is_watching && (floor.dun_level || player_ptr->leaving_dungeon || floor.inside_arena)) {
209         player_ptr->energy_need = 0;
210     }
211
212     player_ptr->leaving_dungeon = false;
213     mproc_init(&floor);
214
215     while (true) {
216         if ((floor.m_cnt + 32 > w_ptr->max_m_idx) && !is_watching) {
217             compact_monsters(player_ptr, 64);
218         }
219
220         if ((floor.m_cnt + 32 < floor.m_max) && !is_watching) {
221             compact_monsters(player_ptr, 0);
222         }
223
224         if (floor.o_cnt + 32 > w_ptr->max_o_idx) {
225             compact_objects(player_ptr, 64);
226         }
227
228         if (floor.o_cnt + 32 < floor.o_max) {
229             compact_objects(player_ptr, 0);
230         }
231
232         process_player(player_ptr);
233         process_upkeep_with_speed(player_ptr);
234         handle_stuff(player_ptr);
235
236         move_cursor_relative(player_ptr->y, player_ptr->x);
237         if (fresh_after) {
238             term_fresh_force();
239         }
240
241         if (!player_ptr->playing || player_ptr->is_dead) {
242             break;
243         }
244
245         process_monsters(player_ptr);
246         handle_stuff(player_ptr);
247
248         move_cursor_relative(player_ptr->y, player_ptr->x);
249         if (fresh_after) {
250             term_fresh_force();
251         }
252
253         if (!player_ptr->playing || player_ptr->is_dead) {
254             break;
255         }
256
257         WorldTurnProcessor(player_ptr).process_world();
258         handle_stuff(player_ptr);
259
260         move_cursor_relative(player_ptr->y, player_ptr->x);
261         if (fresh_after) {
262             term_fresh_force();
263         }
264
265         if (!player_ptr->playing || player_ptr->is_dead) {
266             break;
267         }
268
269         w_ptr->game_turn++;
270         if (w_ptr->dungeon_turn < w_ptr->dungeon_turn_limit) {
271             if (!player_ptr->wild_mode || wild_regen) {
272                 w_ptr->dungeon_turn++;
273             } else if (player_ptr->wild_mode && !(w_ptr->game_turn % ((MAX_HGT + MAX_WID) / 2))) {
274                 w_ptr->dungeon_turn++;
275             }
276         }
277
278         prevent_turn_overflow(player_ptr);
279
280         if (player_ptr->leaving) {
281             break;
282         }
283
284         if (wild_regen) {
285             wild_regen--;
286         }
287     }
288
289     if ((inside_quest(quest_num)) && questor_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
290         questor_ptr->misc_flags.reset(MonsterMiscType::QUESTOR);
291     }
292
293     if (player_ptr->playing && !player_ptr->is_dead) {
294         /*
295          * Maintain Unique monsters and artifact, save current
296          * floor, then prepare next floor
297          */
298         leave_floor(player_ptr);
299         reinit_wilderness = false;
300     }
301
302     write_level = true;
303 }