OSDN Git Service

[Refactor] #38993 o_cnt, o_max を floor_type 構造体に取り込み.
[hengband/hengband.git] / src / spells-floor.c
1 #include "angband.h"
2 #include "util.h"
3
4 #include "dungeon.h"
5 #include "floor.h"
6 #include "spells-floor.h"
7 #include "grid.h"
8 #include "quest.h"
9 #include "cmd-basic.h"
10 #include "floor-save.h"
11 #include "player-effects.h"
12 #include "feature.h"
13
14 /*
15  * Light up the dungeon using "clairvoyance"
16  *
17  * This function "illuminates" every grid in the dungeon, memorizes all
18  * "objects", memorizes all grids as with magic mapping, and, under the
19  * standard option settings (view_perma_grids but not view_torch_grids)
20  * memorizes all floor grids too.
21  *
22  * Note that if "view_perma_grids" is not set, we do not memorize floor
23  * grids, since this would defeat the purpose of "view_perma_grids", not
24  * that anyone seems to play without this option.
25  *
26  * Note that if "view_torch_grids" is set, we do not memorize floor grids,
27  * since this would prevent the use of "view_torch_grids" as a method to
28  * keep track of what grids have been observed directly.
29  */
30 void wiz_lite(bool ninja)
31 {
32         OBJECT_IDX i;
33         POSITION y, x;
34         FEAT_IDX feat;
35         feature_type *f_ptr;
36
37         /* Memorize objects */
38         for (i = 1; i < current_floor_ptr->o_max; i++)
39         {
40                 object_type *o_ptr = &current_floor_ptr->o_list[i];
41
42                 /* Skip dead objects */
43                 if (!o_ptr->k_idx) continue;
44
45                 /* Skip held objects */
46                 if (o_ptr->held_m_idx) continue;
47
48                 /* Memorize */
49                 o_ptr->marked |= OM_FOUND;
50         }
51
52         /* Scan all normal grids */
53         for (y = 1; y < current_floor_ptr->height - 1; y++)
54         {
55                 /* Scan all normal grids */
56                 for (x = 1; x < current_floor_ptr->width - 1; x++)
57                 {
58                         grid_type *g_ptr = &current_floor_ptr->grid_array[y][x];
59
60                         /* Memorize terrain of the grid */
61                         g_ptr->info |= (CAVE_KNOWN);
62
63                         /* Feature code (applying "mimic" field) */
64                         feat = get_feat_mimic(g_ptr);
65                         f_ptr = &f_info[feat];
66
67                         /* Process all non-walls */
68                         if (!have_flag(f_ptr->flags, FF_WALL))
69                         {
70                                 /* Scan all neighbors */
71                                 for (i = 0; i < 9; i++)
72                                 {
73                                         POSITION yy = y + ddy_ddd[i];
74                                         POSITION xx = x + ddx_ddd[i];
75                                         g_ptr = &current_floor_ptr->grid_array[yy][xx];
76
77                                         /* Feature code (applying "mimic" field) */
78                                         f_ptr = &f_info[get_feat_mimic(g_ptr)];
79
80                                         /* Perma-lite the grid */
81                                         if (!(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !ninja)
82                                         {
83                                                 g_ptr->info |= (CAVE_GLOW);
84                                         }
85
86                                         /* Memorize normal features */
87                                         if (have_flag(f_ptr->flags, FF_REMEMBER))
88                                         {
89                                                 /* Memorize the grid */
90                                                 g_ptr->info |= (CAVE_MARK);
91                                         }
92
93                                         /* Perma-lit grids (newly and previously) */
94                                         else if (g_ptr->info & CAVE_GLOW)
95                                         {
96                                                 /* Normally, memorize floors (see above) */
97                                                 if (view_perma_grids && !view_torch_grids)
98                                                 {
99                                                         /* Memorize the grid */
100                                                         g_ptr->info |= (CAVE_MARK);
101                                                 }
102                                         }
103                                 }
104                         }
105                 }
106         }
107
108         p_ptr->update |= (PU_MONSTERS);
109         p_ptr->redraw |= (PR_MAP);
110         p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
111
112         if (p_ptr->special_defense & NINJA_S_STEALTH)
113         {
114                 if (current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(FALSE);
115         }
116 }
117
118
119 /*
120  * Forget the dungeon map (ala "Thinking of Maud...").
121  */
122 void wiz_dark(void)
123 {
124         OBJECT_IDX i;
125         POSITION y, x;
126
127         /* Forget every grid */
128         for (y = 1; y < current_floor_ptr->height - 1; y++)
129         {
130                 for (x = 1; x < current_floor_ptr->width - 1; x++)
131                 {
132                         grid_type *g_ptr = &current_floor_ptr->grid_array[y][x];
133
134                         /* Process the grid */
135                         g_ptr->info &= ~(CAVE_MARK | CAVE_IN_DETECT | CAVE_KNOWN);
136                         g_ptr->info |= (CAVE_UNSAFE);
137                 }
138         }
139
140         /* Forget every grid on horizontal edge */
141         for (x = 0; x < current_floor_ptr->width; x++)
142         {
143                 current_floor_ptr->grid_array[0][x].info &= ~(CAVE_MARK);
144                 current_floor_ptr->grid_array[current_floor_ptr->height - 1][x].info &= ~(CAVE_MARK);
145         }
146
147         /* Forget every grid on vertical edge */
148         for (y = 1; y < (current_floor_ptr->height - 1); y++)
149         {
150                 current_floor_ptr->grid_array[y][0].info &= ~(CAVE_MARK);
151                 current_floor_ptr->grid_array[y][current_floor_ptr->width - 1].info &= ~(CAVE_MARK);
152         }
153
154         /* Forget all objects */
155         for (i = 1; i < current_floor_ptr->o_max; i++)
156         {
157                 object_type *o_ptr = &current_floor_ptr->o_list[i];
158
159                 /* Skip dead objects */
160                 if (!o_ptr->k_idx) continue;
161
162                 /* Skip held objects */
163                 if (o_ptr->held_m_idx) continue;
164
165                 /* Forget the object */
166                 o_ptr->marked &= OM_TOUCHED;
167         }
168
169         /* Forget travel route when we have forgotten map */
170         forget_travel_flow();
171
172         p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
173         p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
174         p_ptr->update |= (PU_MONSTERS);
175         p_ptr->redraw |= (PR_MAP);
176         p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
177 }
178
179 /*!
180  * @brief 守りのルーン設置処理 /
181  * Leave a "glyph of warding" which prevents monster movement
182  * @return 実際に設置が行われた場合TRUEを返す
183  */
184 bool warding_glyph(void)
185 {
186         if (!cave_clean_bold(p_ptr->y, p_ptr->x))
187         {
188                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
189                 return FALSE;
190         }
191
192         /* Create a glyph */
193         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info |= CAVE_OBJECT;
194         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].mimic = feat_glyph;
195
196         note_spot(p_ptr->y, p_ptr->x);
197         lite_spot(p_ptr->y, p_ptr->x);
198
199         return TRUE;
200 }
201
202
203 /*!
204  * @brief 爆発のルーン設置処理 /
205  * Leave an "explosive rune" which prevents monster movement
206  * @return 実際に設置が行われた場合TRUEを返す
207  */
208 bool explosive_rune(void)
209 {
210         if (!cave_clean_bold(p_ptr->y, p_ptr->x))
211         {
212                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
213                 return FALSE;
214         }
215
216         /* Create a glyph */
217         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info |= CAVE_OBJECT;
218         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].mimic = feat_explosive_rune;
219
220         note_spot(p_ptr->y, p_ptr->x);
221         lite_spot(p_ptr->y, p_ptr->x);
222
223         return TRUE;
224 }
225
226
227 /*!
228  * @brief 鏡設置処理
229  * @return 実際に設置が行われた場合TRUEを返す
230  */
231 bool place_mirror(void)
232 {
233         if (!cave_clean_bold(p_ptr->y, p_ptr->x))
234         {
235                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
236                 return FALSE;
237         }
238
239         /* Create a mirror */
240         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info |= CAVE_OBJECT;
241         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].mimic = feat_mirror;
242
243         /* Turn on the light */
244         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info |= CAVE_GLOW;
245
246         note_spot(p_ptr->y, p_ptr->x);
247         lite_spot(p_ptr->y, p_ptr->x);
248         update_local_illumination(p_ptr->y, p_ptr->x);
249
250         return TRUE;
251 }
252
253 /*!
254  * @brief プレイヤーの手による能動的な階段生成処理 /
255  * Create stairs at or move previously created stairs into the player location.
256  * @return なし
257  */
258 void stair_creation(void)
259 {
260         saved_floor_type *sf_ptr;
261         saved_floor_type *dest_sf_ptr;
262
263         bool up = TRUE;
264         bool down = TRUE;
265         FLOOR_IDX dest_floor_id = 0;
266
267
268         /* Forbid up staircases on Ironman mode */
269         if (ironman_downward) up = FALSE;
270
271         /* Forbid down staircases on quest level */
272         if (quest_number(current_floor_ptr->dun_level) || (current_floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth)) down = FALSE;
273
274         /* No effect out of standard dungeon floor */
275         if (!current_floor_ptr->dun_level || (!up && !down) ||
276                 (p_ptr->inside_quest && is_fixed_quest_idx(p_ptr->inside_quest)) ||
277                 p_ptr->inside_arena || p_ptr->inside_battle)
278         {
279                 /* arena or quest */
280                 msg_print(_("効果がありません!", "There is no effect!"));
281                 return;
282         }
283
284         /* Artifacts resists */
285         if (!cave_valid_bold(p_ptr->y, p_ptr->x))
286         {
287                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
288                 return;
289         }
290
291         /* Destroy all objects in the grid */
292         delete_object(p_ptr->y, p_ptr->x);
293
294         /* Extract current floor data */
295         sf_ptr = get_sf_ptr(p_ptr->floor_id);
296         if (!sf_ptr)
297         {
298                 /* No floor id? -- Create now! */
299                 p_ptr->floor_id = get_new_floor_id();
300                 sf_ptr = get_sf_ptr(p_ptr->floor_id);
301         }
302
303         /* Choose randomly */
304         if (up && down)
305         {
306                 if (randint0(100) < 50) up = FALSE;
307                 else down = FALSE;
308         }
309
310         /* Destination is already fixed */
311         if (up)
312         {
313                 if (sf_ptr->upper_floor_id) dest_floor_id = sf_ptr->upper_floor_id;
314         }
315         else
316         {
317                 if (sf_ptr->lower_floor_id) dest_floor_id = sf_ptr->lower_floor_id;
318         }
319
320
321         /* Search old stairs leading to the destination */
322         if (dest_floor_id)
323         {
324                 POSITION x, y;
325
326                 for (y = 0; y < current_floor_ptr->height; y++)
327                 {
328                         for (x = 0; x < current_floor_ptr->width; x++)
329                         {
330                                 grid_type *g_ptr = &current_floor_ptr->grid_array[y][x];
331
332                                 if (!g_ptr->special) continue;
333                                 if (feat_uses_special(g_ptr->feat)) continue;
334                                 if (g_ptr->special != dest_floor_id) continue;
335
336                                 /* Remove old stairs */
337                                 g_ptr->special = 0;
338                                 cave_set_feat(y, x, feat_ground_type[randint0(100)]);
339                         }
340                 }
341         }
342
343         /* No old destination -- Get new one now */
344         else
345         {
346                 dest_floor_id = get_new_floor_id();
347
348                 /* Fix it */
349                 if (up)
350                         sf_ptr->upper_floor_id = dest_floor_id;
351                 else
352                         sf_ptr->lower_floor_id = dest_floor_id;
353         }
354
355         /* Extract destination floor data */
356         dest_sf_ptr = get_sf_ptr(dest_floor_id);
357
358
359         /* Create a staircase */
360         if (up)
361         {
362                 cave_set_feat(p_ptr->y, p_ptr->x,
363                         (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level <= current_floor_ptr->dun_level - 2)) ?
364                         feat_state(feat_up_stair, FF_SHAFT) : feat_up_stair);
365         }
366         else
367         {
368                 cave_set_feat(p_ptr->y, p_ptr->x,
369                         (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level >= current_floor_ptr->dun_level + 2)) ?
370                         feat_state(feat_down_stair, FF_SHAFT) : feat_down_stair);
371         }
372
373
374         /* Connect this stairs to the destination */
375         current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].special = dest_floor_id;
376 }
377
378 /*
379  * Hack -- map the current panel (plus some) ala "magic mapping"
380  */
381 void map_area(POSITION range)
382 {
383         int i;
384         POSITION x, y;
385         grid_type *g_ptr;
386         FEAT_IDX feat;
387         feature_type *f_ptr;
388
389         if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
390
391         /* Scan that area */
392         for (y = 1; y < current_floor_ptr->height - 1; y++)
393         {
394                 for (x = 1; x < current_floor_ptr->width - 1; x++)
395                 {
396                         if (distance(p_ptr->y, p_ptr->x, y, x) > range) continue;
397
398                         g_ptr = &current_floor_ptr->grid_array[y][x];
399
400                         /* Memorize terrain of the grid */
401                         g_ptr->info |= (CAVE_KNOWN);
402
403                         /* Feature code (applying "mimic" field) */
404                         feat = get_feat_mimic(g_ptr);
405                         f_ptr = &f_info[feat];
406
407                         /* All non-walls are "checked" */
408                         if (!have_flag(f_ptr->flags, FF_WALL))
409                         {
410                                 /* Memorize normal features */
411                                 if (have_flag(f_ptr->flags, FF_REMEMBER))
412                                 {
413                                         /* Memorize the object */
414                                         g_ptr->info |= (CAVE_MARK);
415                                 }
416
417                                 /* Memorize known walls */
418                                 for (i = 0; i < 8; i++)
419                                 {
420                                         g_ptr = &current_floor_ptr->grid_array[y + ddy_ddd[i]][x + ddx_ddd[i]];
421
422                                         /* Feature code (applying "mimic" field) */
423                                         feat = get_feat_mimic(g_ptr);
424                                         f_ptr = &f_info[feat];
425
426                                         /* Memorize walls (etc) */
427                                         if (have_flag(f_ptr->flags, FF_REMEMBER))
428                                         {
429                                                 /* Memorize the walls */
430                                                 g_ptr->info |= (CAVE_MARK);
431                                         }
432                                 }
433                         }
434                 }
435         }
436
437         p_ptr->redraw |= (PR_MAP);
438         p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
439 }