OSDN Git Service

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