OSDN Git Service

[feature] ソースファイルをC++に対応
[hengbandforosx/hengbandosx.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 update_lite_radius(player_type *creature_ptr)
73 {
74     creature_ptr->cur_lite = 0;
75     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
76         object_type *o_ptr;
77         o_ptr = &creature_ptr->inventory_list[i];
78         BIT_FLAGS flgs[TR_FLAG_SIZE];
79         object_flags(creature_ptr, o_ptr, flgs);
80
81         if (!o_ptr->k_idx)
82             continue;
83
84         if (o_ptr->name2 == EGO_LITE_SHINE)
85             creature_ptr->cur_lite++;
86
87         if (!has_flag(flgs, TR_DARK_SOURCE)) {
88             if (o_ptr->tval == TV_LITE) {
89                 if ((o_ptr->sval == SV_LITE_TORCH) && !(o_ptr->xtra4 > 0))
90                     continue;
91
92                 if ((o_ptr->sval == SV_LITE_LANTERN) && !(o_ptr->xtra4 > 0))
93                     continue;
94             }
95         }
96
97
98         POSITION rad = 0;
99         if (has_flag(flgs, TR_LITE_1) && !has_flag(flgs, TR_DARK_SOURCE))
100             rad += 1;
101
102         if (has_flag(flgs, TR_LITE_2) && !has_flag(flgs, TR_DARK_SOURCE))
103             rad += 2;
104
105         if (has_flag(flgs, TR_LITE_3) && !has_flag(flgs, TR_DARK_SOURCE))
106             rad += 3;
107
108         if (has_flag(flgs, TR_LITE_M1))
109             rad -= 1;
110
111         if (has_flag(flgs, TR_LITE_M2))
112             rad -= 2;
113
114         if (has_flag(flgs, TR_LITE_M3))
115             rad -= 3;
116
117         creature_ptr->cur_lite += rad;
118     }
119
120     if (d_info[creature_ptr->dungeon_idx].flags1 & DF1_DARKNESS && creature_ptr->cur_lite > 1)
121         creature_ptr->cur_lite = 1;
122
123     if (creature_ptr->cur_lite <= 0 && creature_ptr->lite)
124         creature_ptr->cur_lite++;
125
126     if (creature_ptr->cur_lite > 14)
127         creature_ptr->cur_lite = 14;
128
129     if (creature_ptr->cur_lite < 0)
130         creature_ptr->cur_lite = 0;
131
132     if (creature_ptr->old_lite == creature_ptr->cur_lite)
133         return;
134
135     creature_ptr->update |= PU_LITE | PU_MON_LITE | PU_MONSTERS;
136     creature_ptr->old_lite = creature_ptr->cur_lite;
137
138     if ((creature_ptr->cur_lite > 0) && (creature_ptr->special_defense & NINJA_S_STEALTH))
139         set_superstealth(creature_ptr, FALSE);
140 }
141
142 /*
143  * Update the set of grids "illuminated" by the player's lite.
144  *
145  * This routine needs to use the results of "update_view()"
146  *
147  * Note that "blindness" does NOT affect "torch lite".  Be careful!
148  *
149  * We optimize most lites (all non-artifact lites) by using "obvious"
150  * facts about the results of "small" lite radius, and we attempt to
151  * list the "nearby" grids before the more "distant" ones in the
152  * array of torch-lit grids.
153  *
154  * We assume that "radius zero" lite is in fact no lite at all.
155  *
156  *     Torch     Lantern     Artifacts
157  *     (etc)
158  *                              ***
159  *                 ***         *****
160  *      ***       *****       *******
161  *      *@*       **@**       ***@***
162  *      ***       *****       *******
163  *                 ***         *****
164  *                              ***
165  */
166 void update_lite(player_type *subject_ptr)
167 {
168     POSITION p = subject_ptr->cur_lite;
169     grid_type *g_ptr;
170     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
171     for (int i = 0; i < floor_ptr->lite_n; i++) {
172         POSITION y = floor_ptr->lite_y[i];
173         POSITION x = floor_ptr->lite_x[i];
174         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
175         floor_ptr->grid_array[y][x].info |= CAVE_TEMP;
176         tmp_pos.y[tmp_pos.n] = y;
177         tmp_pos.x[tmp_pos.n] = x;
178         tmp_pos.n++;
179     }
180
181     floor_ptr->lite_n = 0;
182     if (p >= 1) {
183         cave_lite_hack(floor_ptr, subject_ptr->y, 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 - 1, subject_ptr->x);
186         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 1);
187         cave_lite_hack(floor_ptr, subject_ptr->y, 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         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1);
192     }
193
194     if (p >= 2) {
195         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x)) {
196             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x);
197             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 1);
198             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 1);
199         }
200
201         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x)) {
202             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x);
203             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 1);
204             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 1);
205         }
206
207         if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1)) {
208             cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 2);
209             cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 2);
210             cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 2);
211         }
212
213         if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1)) {
214             cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 2);
215             cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 2);
216             cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 2);
217         }
218     }
219
220     if (p >= 3) {
221         int d;
222         if (p > 14)
223             p = 14;
224
225         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
226             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
227
228         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
229             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
230
231         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
232             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
233
234         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
235             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
236
237         POSITION min_y = subject_ptr->y - p;
238         if (min_y < 0)
239             min_y = 0;
240
241         POSITION max_y = subject_ptr->y + p;
242         if (max_y > floor_ptr->height - 1)
243             max_y = floor_ptr->height - 1;
244
245         POSITION min_x = subject_ptr->x - p;
246         if (min_x < 0)
247             min_x = 0;
248
249         POSITION max_x = subject_ptr->x + p;
250         if (max_x > floor_ptr->width - 1)
251             max_x = floor_ptr->width - 1;
252
253         for (POSITION y = min_y; y <= max_y; y++) {
254             for (POSITION x = min_x; x <= max_x; x++) {
255                 int dy = (subject_ptr->y > y) ? (subject_ptr->y - y) : (y - subject_ptr->y);
256                 int dx = (subject_ptr->x > x) ? (subject_ptr->x - x) : (x - subject_ptr->x);
257                 if ((dy <= 2) && (dx <= 2))
258                     continue;
259
260                 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
261                 if (d > p)
262                     continue;
263
264                 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
265                     cave_lite_hack(floor_ptr, y, x);
266             }
267         }
268     }
269
270     for (int i = 0; i < floor_ptr->lite_n; i++) {
271         POSITION y = floor_ptr->lite_y[i];
272         POSITION x = floor_ptr->lite_x[i];
273         g_ptr = &floor_ptr->grid_array[y][x];
274         if (g_ptr->info & CAVE_TEMP)
275             continue;
276
277         cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
278     }
279
280     for (int i = 0; i < tmp_pos.n; i++) {
281         POSITION y = tmp_pos.y[i];
282         POSITION x = tmp_pos.x[i];
283         g_ptr = &floor_ptr->grid_array[y][x];
284         g_ptr->info &= ~(CAVE_TEMP);
285         if (g_ptr->info & CAVE_LITE)
286             continue;
287
288         cave_redraw_later(floor_ptr, g_ptr, y, x);
289     }
290
291     tmp_pos.n = 0;
292     subject_ptr->update |= PU_DELAY_VIS;
293 }