OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / world / world-movement-processor.cpp
1 #include "world/world-movement-processor.h"
2 #include "cmd-io/cmd-save.h"
3 #include "core/disturbance.h"
4 #include "dungeon/quest.h"
5 #include "floor/floor-mode-changer.h"
6 #include "game-option/birth-options.h"
7 #include "game-option/play-record-options.h"
8 #include "game-option/special-options.h"
9 #include "io/write-diary.h"
10 #include "main/sound-definitions-table.h"
11 #include "main/sound-of-music.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags1.h"
14 #include "system/dungeon-info.h"
15 #include "system/floor-type-definition.h"
16 #include "system/monster-race-info.h"
17 #include "system/player-type-definition.h"
18 #include "system/redrawing-flags-updater.h"
19 #include "util/enum-range.h"
20 #include "view/display-messages.h"
21 #include "world/world.h"
22
23 /*!
24  * @brief プレイヤーの現在ダンジョンIDと階層に応じて、ダンジョン内ランクエの自動放棄を行う
25  * @param player_ptr プレイヤーへの参照ポインタ
26  */
27 void check_random_quest_auto_failure(PlayerType *player_ptr)
28 {
29     auto &quest_list = QuestList::get_instance();
30     const auto &floor = *player_ptr->current_floor_ptr;
31     if (floor.dungeon_idx != DUNGEON_ANGBAND) {
32         return;
33     }
34     for (auto q_idx : EnumRange(QuestId::RANDOM_QUEST1, QuestId::RANDOM_QUEST10)) {
35         auto &quest = quest_list[q_idx];
36         auto is_taken_quest = (quest.type == QuestKindType::RANDOM);
37         is_taken_quest &= (quest.status == QuestStatusType::TAKEN);
38         is_taken_quest &= (quest.level < floor.dun_level);
39         if (!is_taken_quest) {
40             continue;
41         }
42
43         quest.status = QuestStatusType::FAILED;
44         quest.complev = (byte)player_ptr->lev;
45         update_playtime();
46         quest.comptime = w_ptr->play_time;
47         monraces_info[quest.r_idx].flags1 &= ~(RF1_QUESTOR);
48     }
49 }
50
51 /*!
52  * @brief 10ゲームターンが進行するごとに帰還の残り時間カウントダウンと発動を処理する。
53  * / Handle involuntary movement once every 10 game turns
54  * @param player_ptr プレイヤーへの参照ポインタ
55  * @details
56  * Autosave BEFORE resetting the recall counter (rr9)
57  * The player is yanked up/down as soon as he loads the autosaved game.
58  */
59 void execute_recall(PlayerType *player_ptr)
60 {
61     if (player_ptr->word_recall == 0) {
62         return;
63     }
64
65     if (autosave_l && (player_ptr->word_recall == 1) && !player_ptr->phase_out) {
66         do_cmd_save_game(player_ptr, true);
67     }
68
69     player_ptr->word_recall--;
70     RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
71     if (player_ptr->word_recall != 0) {
72         return;
73     }
74
75     disturb(player_ptr, false, true);
76     auto *floor_ptr = player_ptr->current_floor_ptr;
77     if (floor_ptr->dun_level || inside_quest(floor_ptr->quest_number) || player_ptr->enter_dungeon) {
78         msg_print(_("上に引っ張りあげられる感じがする!", "You feel yourself yanked upwards!"));
79         if (floor_ptr->dungeon_idx) {
80             player_ptr->recall_dungeon = floor_ptr->dungeon_idx;
81         }
82         if (record_stair) {
83             exe_write_diary(player_ptr, DiaryKind::RECALL, floor_ptr->dun_level);
84         }
85
86         floor_ptr->dun_level = 0;
87         floor_ptr->reset_dungeon_index();
88         leave_quest_check(player_ptr);
89         leave_tower_check(player_ptr);
90         floor_ptr->quest_number = QuestId::NONE;
91         player_ptr->leaving = true;
92         sound(SOUND_TPLEVEL);
93         return;
94     }
95
96     msg_print(_("下に引きずり降ろされる感じがする!", "You feel yourself yanked downwards!"));
97     floor_ptr->set_dungeon_index(player_ptr->recall_dungeon);
98     if (record_stair) {
99         exe_write_diary(player_ptr, DiaryKind::RECALL, floor_ptr->dun_level);
100     }
101
102     floor_ptr->dun_level = max_dlv[floor_ptr->dungeon_idx];
103     if (floor_ptr->dun_level < 1) {
104         floor_ptr->dun_level = 1;
105     }
106     if (ironman_nightmare && !randint0(666) && (floor_ptr->dungeon_idx == DUNGEON_ANGBAND)) {
107         if (floor_ptr->dun_level < 50) {
108             floor_ptr->dun_level *= 2;
109         } else if (floor_ptr->dun_level < 99) {
110             floor_ptr->dun_level = (floor_ptr->dun_level + 99) / 2;
111         } else if (floor_ptr->dun_level > 100) {
112             floor_ptr->dun_level = floor_ptr->get_dungeon_definition().maxdepth - 1;
113         }
114     }
115
116     if (player_ptr->wild_mode) {
117         player_ptr->wilderness_y = player_ptr->y;
118         player_ptr->wilderness_x = player_ptr->x;
119     } else {
120         player_ptr->oldpx = player_ptr->x;
121         player_ptr->oldpy = player_ptr->y;
122     }
123
124     player_ptr->wild_mode = false;
125
126     /*
127      * Clear all saved floors
128      * and create a first saved floor
129      */
130     prepare_change_floor_mode(player_ptr, CFM_FIRST_FLOOR);
131     player_ptr->leaving = true;
132
133     check_random_quest_auto_failure(player_ptr);
134     sound(SOUND_TPLEVEL);
135 }
136
137 /*!
138  * @brief 10ゲームターンが進行するごとにフロア・リセット/現実変容の残り時間カウントダウンと発動を処理する。
139  * / Handle involuntary movement once every 10 game turns
140  * @param player_ptr プレイヤーへの参照ポインタ
141  */
142 void execute_floor_reset(PlayerType *player_ptr)
143 {
144     const auto &floor = *player_ptr->current_floor_ptr;
145     if (player_ptr->alter_reality == 0) {
146         return;
147     }
148
149     if (autosave_l && (player_ptr->alter_reality == 1) && !player_ptr->phase_out) {
150         do_cmd_save_game(player_ptr, true);
151     }
152
153     player_ptr->alter_reality--;
154     RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
155     if (player_ptr->alter_reality != 0) {
156         return;
157     }
158
159     disturb(player_ptr, false, true);
160     if (!inside_quest(quest_number(floor, floor.dun_level)) && floor.dun_level) {
161         msg_print(_("世界が変わった!", "The world changes!"));
162
163         /*
164          * Clear all saved floors
165          * and create a first saved floor
166          */
167         prepare_change_floor_mode(player_ptr, CFM_FIRST_FLOOR);
168         player_ptr->leaving = true;
169     } else {
170         msg_print(_("世界が少しの間変化したようだ。", "The world seems to change for a moment!"));
171     }
172
173     sound(SOUND_TPLEVEL);
174 }