OSDN Git Service

Merge pull request #3532 from sikabane-works/release/3.0.0.87-alpha
[hengbandforosx/hengbandosx.git] / src / spell-kind / spells-grid.cpp
1 #include "spell-kind/spells-grid.h"
2 #include "dungeon/quest.h"
3 #include "floor/cave.h"
4 #include "floor/floor-object.h"
5 #include "floor/floor-save-util.h"
6 #include "floor/floor-save.h"
7 #include "game-option/birth-options.h"
8 #include "grid/feature.h"
9 #include "grid/grid.h"
10 #include "grid/stair.h"
11 #include "system/dungeon-info.h"
12 #include "system/floor-type-definition.h"
13 #include "system/grid-type-definition.h"
14 #include "system/player-type-definition.h"
15 #include "system/terrain-type-definition.h"
16 #include "util/bit-flags-calculator.h"
17 #include "view/display-messages.h"
18
19 /*!
20  * @brief 守りのルーン設置処理 /
21  * Leave a "rune of protection" which prevents monster movement
22  * @return 実際に設置が行われた場合TRUEを返す
23  */
24 bool create_rune_protection_one(PlayerType *player_ptr)
25 {
26     if (!cave_clean_bold(player_ptr->current_floor_ptr, player_ptr->y, player_ptr->x)) {
27         msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
28         return false;
29     }
30
31     player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].info |= CAVE_OBJECT;
32     player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].mimic = feat_rune_protection;
33     note_spot(player_ptr, player_ptr->y, player_ptr->x);
34     lite_spot(player_ptr, player_ptr->y, player_ptr->x);
35     return true;
36 }
37
38 /*!
39  * @brief 爆発のルーン設置処理 /
40  * Leave an "explosive rune" which prevents monster movement
41  * @param player_ptr プレイヤーへの参照ポインタ
42  * @param y 設置場所
43  * @param x 設置場所
44  * @return 実際に設置が行われた場合TRUEを返す
45  */
46 bool create_rune_explosion(PlayerType *player_ptr, POSITION y, POSITION x)
47 {
48     auto *floor_ptr = player_ptr->current_floor_ptr;
49     if (!cave_clean_bold(floor_ptr, y, x)) {
50         msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
51         return false;
52     }
53
54     floor_ptr->grid_array[y][x].info |= CAVE_OBJECT;
55     floor_ptr->grid_array[y][x].mimic = feat_rune_explosion;
56     note_spot(player_ptr, y, x);
57     lite_spot(player_ptr, y, x);
58     return true;
59 }
60
61 /*!
62  * @brief プレイヤーの手による能動的な階段生成処理 /
63  * Create stairs at or move previously created stairs into the player location.
64  */
65 void stair_creation(PlayerType *player_ptr)
66 {
67     bool up = true;
68     if (ironman_downward) {
69         up = false;
70     }
71
72     bool down = true;
73     auto &floor = *player_ptr->current_floor_ptr;
74     if (inside_quest(quest_number(floor, floor.dun_level)) || (floor.dun_level >= floor.get_dungeon_definition().maxdepth)) {
75         down = false;
76     }
77
78     if (!floor.dun_level || (!up && !down) || (inside_quest(floor.quest_number) && QuestType::is_fixed(floor.quest_number)) || floor.inside_arena || player_ptr->phase_out) {
79         msg_print(_("効果がありません!", "There is no effect!"));
80         return;
81     }
82
83     if (!cave_valid_bold(&floor, player_ptr->y, player_ptr->x)) {
84         msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
85         return;
86     }
87
88     delete_all_items_from_floor(player_ptr, player_ptr->y, player_ptr->x);
89     saved_floor_type *sf_ptr;
90     sf_ptr = get_sf_ptr(player_ptr->floor_id);
91     if (!sf_ptr) {
92         player_ptr->floor_id = get_new_floor_id(player_ptr);
93         sf_ptr = get_sf_ptr(player_ptr->floor_id);
94     }
95
96     if (up && down) {
97         if (randint0(100) < 50) {
98             up = false;
99         } else {
100             down = false;
101         }
102     }
103
104     FLOOR_IDX dest_floor_id = 0;
105     if (up) {
106         if (sf_ptr->upper_floor_id) {
107             dest_floor_id = sf_ptr->upper_floor_id;
108         }
109     } else {
110         if (sf_ptr->lower_floor_id) {
111             dest_floor_id = sf_ptr->lower_floor_id;
112         }
113     }
114
115     if (dest_floor_id) {
116         for (POSITION y = 0; y < floor.height; y++) {
117             for (POSITION x = 0; x < floor.width; x++) {
118                 auto *g_ptr = &floor.grid_array[y][x];
119                 if (!g_ptr->special) {
120                     continue;
121                 }
122                 if (feat_uses_special(g_ptr->feat)) {
123                     continue;
124                 }
125                 if (g_ptr->special != dest_floor_id) {
126                     continue;
127                 }
128
129                 /* Remove old stairs */
130                 g_ptr->special = 0;
131                 cave_set_feat(player_ptr, y, x, rand_choice(feat_ground_type));
132             }
133         }
134     } else {
135         dest_floor_id = get_new_floor_id(player_ptr);
136         if (up) {
137             sf_ptr->upper_floor_id = dest_floor_id;
138         } else {
139             sf_ptr->lower_floor_id = dest_floor_id;
140         }
141     }
142
143     saved_floor_type *dest_sf_ptr;
144     dest_sf_ptr = get_sf_ptr(dest_floor_id);
145     if (up) {
146         cave_set_feat(player_ptr, player_ptr->y, player_ptr->x,
147             (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level <= floor.dun_level - 2)) ? feat_state(&floor, feat_up_stair, TerrainCharacteristics::SHAFT)
148                                                                                          : feat_up_stair);
149     } else {
150         cave_set_feat(player_ptr, player_ptr->y, player_ptr->x,
151             (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level >= floor.dun_level + 2)) ? feat_state(&floor, feat_down_stair, TerrainCharacteristics::SHAFT)
152                                                                                          : feat_down_stair);
153     }
154
155     floor.grid_array[player_ptr->y][player_ptr->x].special = dest_floor_id;
156 }