OSDN Git Service

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