OSDN Git Service

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