OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / specific-object / torch.c
1 #include "specific-object/torch.h"
2 #include "core/player-update-types.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "floor/cave.h"
6 #include "inventory/inventory-slot-types.h"
7 #include "mind/mind-ninja.h"
8 #include "object-enchant/object-ego.h"
9 #include "object-enchant/tr-types.h"
10 #include "object/object-flags.h"
11 #include "player/special-defense-types.h"
12 #include "system/floor-type-definition.h"
13 #include "sv-definition/sv-lite-types.h"
14 #include "util/bit-flags-calculator.h"
15
16 /*!
17  * @brief 投擲時たいまつに投げやすい/焼棄/アンデッドスレイの特別効果を返す。
18  * Torches have special abilities when they are flaming.
19  * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
20  * @param flgs 特別に追加するフラグを返す参照ポインタ
21  * @return なし
22  */
23 void torch_flags(object_type *o_ptr, BIT_FLAGS *flgs)
24 {
25     if ((o_ptr->tval != TV_LITE) || (o_ptr->sval != SV_LITE_TORCH) || (o_ptr->xtra4 <= 0))
26         return;
27
28     add_flag(flgs, TR_BRAND_FIRE);
29     add_flag(flgs, TR_KILL_UNDEAD);
30     add_flag(flgs, TR_THROW);
31 }
32
33 /*!
34  * @brief 投擲時たいまつにダイスを与える。
35  * Torches have special abilities when they are flaming.
36  * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
37  * @param dd 特別なダイス数を返す参照ポインタ
38  * @param ds 特別なダイス面数を返す参照ポインタ
39  * @return なし
40  */
41 void torch_dice(object_type *o_ptr, DICE_NUMBER *dd, DICE_SID *ds)
42 {
43     if ((o_ptr->tval != TV_LITE) || (o_ptr->sval != SV_LITE_TORCH) || (o_ptr->xtra4 <= 0))
44         return;
45
46     *dd = 1;
47     *ds = 6;
48 }
49
50 /*!
51  * @brief 投擲時命中したたいまつの寿命を縮める。
52  * Torches have special abilities when they are flaming.
53  * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
54  * @return なし
55  */
56 void torch_lost_fuel(object_type *o_ptr)
57 {
58     if ((o_ptr->tval != TV_LITE) || (o_ptr->sval != SV_LITE_TORCH))
59         return;
60
61     o_ptr->xtra4 -= (FUEL_TORCH / 25);
62     if (o_ptr->xtra4 < 0)
63         o_ptr->xtra4 = 0;
64 }
65
66 /*!
67  * @brief プレイヤーの光源半径を計算する / Extract and set the current "lite radius"
68  * @return なし
69  * @details
70  * SWD: Experimental modification: multiple light sources have additive effect.
71  */
72 void calc_lite_radius(player_type *creature_ptr)
73 {
74     creature_ptr->cur_lite = 0;
75     for (inventory_slot_type i = INVEN_RARM; i < INVEN_TOTAL; i++) {
76         object_type *o_ptr;
77         o_ptr = &creature_ptr->inventory_list[i];
78         if (!o_ptr->k_idx)
79             continue;
80
81         if (o_ptr->name2 == EGO_LITE_SHINE)
82             creature_ptr->cur_lite++;
83
84         if (o_ptr->name2 != EGO_LITE_DARKNESS) {
85             if (o_ptr->tval == TV_LITE) {
86                 if ((o_ptr->sval == SV_LITE_TORCH) && !(o_ptr->xtra4 > 0))
87                     continue;
88
89                 if ((o_ptr->sval == SV_LITE_LANTERN) && !(o_ptr->xtra4 > 0))
90                     continue;
91             }
92         }
93
94         BIT_FLAGS flgs[TR_FLAG_SIZE];
95         object_flags(creature_ptr, o_ptr, flgs);
96
97         POSITION rad = 0;
98         if (have_flag(flgs, TR_LITE_1) && o_ptr->name2 != EGO_LITE_DARKNESS)
99             rad += 1;
100
101         if (have_flag(flgs, TR_LITE_2) && o_ptr->name2 != EGO_LITE_DARKNESS)
102             rad += 2;
103
104         if (have_flag(flgs, TR_LITE_3) && o_ptr->name2 != EGO_LITE_DARKNESS)
105             rad += 3;
106
107         if (have_flag(flgs, TR_LITE_M1))
108             rad -= 1;
109
110         if (have_flag(flgs, TR_LITE_M2))
111             rad -= 2;
112
113         if (have_flag(flgs, TR_LITE_M3))
114             rad -= 3;
115
116         creature_ptr->cur_lite += rad;
117     }
118
119     if (d_info[creature_ptr->dungeon_idx].flags1 & DF1_DARKNESS && creature_ptr->cur_lite > 1)
120         creature_ptr->cur_lite = 1;
121
122     if (creature_ptr->cur_lite <= 0 && creature_ptr->lite)
123         creature_ptr->cur_lite++;
124
125     if (creature_ptr->cur_lite > 14)
126         creature_ptr->cur_lite = 14;
127
128     if (creature_ptr->cur_lite < 0)
129         creature_ptr->cur_lite = 0;
130
131     if (creature_ptr->old_lite == creature_ptr->cur_lite)
132         return;
133
134     creature_ptr->update |= PU_LITE | PU_MON_LITE | PU_MONSTERS;
135     creature_ptr->old_lite = creature_ptr->cur_lite;
136
137     if ((creature_ptr->cur_lite > 0) && (creature_ptr->special_defense & NINJA_S_STEALTH))
138         set_superstealth(creature_ptr, FALSE);
139 }
140
141 /*
142  * Update the set of grids "illuminated" by the player's lite.
143  *
144  * This routine needs to use the results of "update_view()"
145  *
146  * Note that "blindness" does NOT affect "torch lite".  Be careful!
147  *
148  * We optimize most lites (all non-artifact lites) by using "obvious"
149  * facts about the results of "small" lite radius, and we attempt to
150  * list the "nearby" grids before the more "distant" ones in the
151  * array of torch-lit grids.
152  *
153  * We assume that "radius zero" lite is in fact no lite at all.
154  *
155  *     Torch     Lantern     Artifacts
156  *     (etc)
157  *                              ***
158  *                 ***         *****
159  *      ***       *****       *******
160  *      *@*       **@**       ***@***
161  *      ***       *****       *******
162  *                 ***         *****
163  *                              ***
164  */
165 void update_lite(player_type *subject_ptr)
166 {
167     POSITION p = subject_ptr->cur_lite;
168     grid_type *g_ptr;
169     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
170     for (int i = 0; i < floor_ptr->lite_n; i++) {
171         POSITION y = floor_ptr->lite_y[i];
172         POSITION x = floor_ptr->lite_x[i];
173         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
174         floor_ptr->grid_array[y][x].info |= CAVE_TEMP;
175         tmp_pos.y[tmp_pos.n] = y;
176         tmp_pos.x[tmp_pos.n] = x;
177         tmp_pos.n++;
178     }
179
180     floor_ptr->lite_n = 0;
181     if (p >= 1) {
182         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x);
183         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x);
184         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x);
185         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 1);
186         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 1);
187         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1);
188         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1);
189         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1);
190         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1);
191     }
192
193     if (p >= 2) {
194         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x)) {
195             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x);
196             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 1);
197             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 1);
198         }
199
200         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x)) {
201             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x);
202             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 1);
203             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 1);
204         }
205
206         if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1)) {
207             cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 2);
208             cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 2);
209             cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 2);
210         }
211
212         if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1)) {
213             cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 2);
214             cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 2);
215             cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 2);
216         }
217     }
218
219     if (p >= 3) {
220         int d;
221         if (p > 14)
222             p = 14;
223
224         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
225             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
226
227         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
228             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
229
230         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
231             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
232
233         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
234             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
235
236         POSITION min_y = subject_ptr->y - p;
237         if (min_y < 0)
238             min_y = 0;
239
240         POSITION max_y = subject_ptr->y + p;
241         if (max_y > floor_ptr->height - 1)
242             max_y = floor_ptr->height - 1;
243
244         POSITION min_x = subject_ptr->x - p;
245         if (min_x < 0)
246             min_x = 0;
247
248         POSITION max_x = subject_ptr->x + p;
249         if (max_x > floor_ptr->width - 1)
250             max_x = floor_ptr->width - 1;
251
252         for (POSITION y = min_y; y <= max_y; y++) {
253             for (POSITION x = min_x; x <= max_x; x++) {
254                 int dy = (subject_ptr->y > y) ? (subject_ptr->y - y) : (y - subject_ptr->y);
255                 int dx = (subject_ptr->x > x) ? (subject_ptr->x - x) : (x - subject_ptr->x);
256                 if ((dy <= 2) && (dx <= 2))
257                     continue;
258
259                 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
260                 if (d > p)
261                     continue;
262
263                 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
264                     cave_lite_hack(floor_ptr, y, x);
265             }
266         }
267     }
268
269     for (int i = 0; i < floor_ptr->lite_n; i++) {
270         POSITION y = floor_ptr->lite_y[i];
271         POSITION x = floor_ptr->lite_x[i];
272         g_ptr = &floor_ptr->grid_array[y][x];
273         if (g_ptr->info & CAVE_TEMP)
274             continue;
275
276         cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
277     }
278
279     for (int i = 0; i < tmp_pos.n; i++) {
280         POSITION y = tmp_pos.y[i];
281         POSITION x = tmp_pos.x[i];
282         g_ptr = &floor_ptr->grid_array[y][x];
283         g_ptr->info &= ~(CAVE_TEMP);
284         if (g_ptr->info & CAVE_LITE)
285             continue;
286
287         cave_redraw_later(floor_ptr, g_ptr, y, x);
288     }
289
290     tmp_pos.n = 0;
291     subject_ptr->update |= PU_DELAY_VIS;
292 }