OSDN Git Service

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