OSDN Git Service

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