OSDN Git Service

b40d53e12ba4524ffa360a041615d136a50775c8
[hengband/hengband.git] / src / spell / spells-floor.c
1 #include "system/angband.h"
2 #include "util.h"
3
4 #include "dungeon/dungeon.h"
5 #include "floor/floor.h"
6 #include "grid.h"
7 #include "quest.h"
8 #include "artifact.h"
9 #include "object/object-kind.h"
10 #include "object/object-flavor.h"
11 #include "object/object-hook.h"
12
13 #include "io/write-diary.h"
14 #include "cmd/cmd-basic.h"
15 #include "cmd/cmd-dump.h"
16
17 #include "floor/floor-events.h"
18 #include "floor/floor-save.h"
19 #include "player/player-damage.h"
20 #include "player/player-effects.h"
21 #include "player/player-move.h"
22 #include "feature.h"
23 #include "view/display-main-window.h"
24
25 #include "monster/monster-status.h"
26
27 #include "spell/spells3.h"
28 #include "spell/spells-floor.h"
29
30 /*
31  * Light up the dungeon using "clairvoyance"
32  *
33  * This function "illuminates" every grid in the dungeon, memorizes all
34  * "objects", memorizes all grids as with magic mapping, and, under the
35  * standard option settings (view_perma_grids but not view_torch_grids)
36  * memorizes all floor grids too.
37  *
38  * Note that if "view_perma_grids" is not set, we do not memorize floor
39  * grids, since this would defeat the purpose of "view_perma_grids", not
40  * that anyone seems to play without this option.
41  *
42  * Note that if "view_torch_grids" is set, we do not memorize floor grids,
43  * since this would prevent the use of "view_torch_grids" as a method to
44  * keep track of what grids have been observed directly.
45  */
46 void wiz_lite(player_type *caster_ptr, bool ninja)
47 {
48         /* Memorize objects */
49         for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++)
50         {
51                 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
52                 if (!OBJECT_IS_VALID(o_ptr)) continue;
53                 if (OBJECT_IS_HELD_MONSTER(o_ptr)) continue;
54                 o_ptr->marked |= OM_FOUND;
55         }
56
57         /* Scan all normal grids */
58         for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++)
59         {
60                 /* Scan all normal grids */
61                 for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++)
62                 {
63                         grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
64
65                         /* Memorize terrain of the grid */
66                         g_ptr->info |= (CAVE_KNOWN);
67
68                         /* Feature code (applying "mimic" field) */
69                         FEAT_IDX feat = get_feat_mimic(g_ptr);
70                         feature_type *f_ptr;
71                         f_ptr = &f_info[feat];
72
73                         /* Process all non-walls */
74                         if (have_flag(f_ptr->flags, FF_WALL)) continue;
75
76                         /* Scan all neighbors */
77                         for (OBJECT_IDX i = 0; i < 9; i++)
78                         {
79                                 POSITION yy = y + ddy_ddd[i];
80                                 POSITION xx = x + ddx_ddd[i];
81                                 g_ptr = &caster_ptr->current_floor_ptr->grid_array[yy][xx];
82
83                                 /* Feature code (applying "mimic" field) */
84                                 f_ptr = &f_info[get_feat_mimic(g_ptr)];
85
86                                 /* Perma-lite the grid */
87                                 if (!(d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !ninja)
88                                 {
89                                         g_ptr->info |= (CAVE_GLOW);
90                                 }
91
92                                 /* Memorize normal features */
93                                 if (have_flag(f_ptr->flags, FF_REMEMBER))
94                                 {
95                                         /* Memorize the grid */
96                                         g_ptr->info |= (CAVE_MARK);
97                                 }
98
99                                 /* Perma-lit grids (newly and previously) */
100                                 else if (g_ptr->info & CAVE_GLOW)
101                                 {
102                                         /* Normally, memorize floors (see above) */
103                                         if (view_perma_grids && !view_torch_grids)
104                                         {
105                                                 /* Memorize the grid */
106                                                 g_ptr->info |= (CAVE_MARK);
107                                         }
108                                 }
109                         }
110                 }
111         }
112
113         caster_ptr->update |= (PU_MONSTERS);
114         caster_ptr->redraw |= (PR_MAP);
115         caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
116
117         if (caster_ptr->special_defense & NINJA_S_STEALTH)
118         {
119                 if (caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW) set_superstealth(caster_ptr, FALSE);
120         }
121 }
122
123
124 /*
125  * Forget the dungeon map (ala "Thinking of Maud...").
126  */
127 void wiz_dark(player_type *caster_ptr)
128 {
129         /* Forget every grid */
130         for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++)
131         {
132                 for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++)
133                 {
134                         grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
135
136                         /* Process the grid */
137                         g_ptr->info &= ~(CAVE_MARK | CAVE_IN_DETECT | CAVE_KNOWN);
138                         g_ptr->info |= (CAVE_UNSAFE);
139                 }
140         }
141
142         /* Forget every grid on horizontal edge */
143         for (POSITION x = 0; x < caster_ptr->current_floor_ptr->width; x++)
144         {
145                 caster_ptr->current_floor_ptr->grid_array[0][x].info &= ~(CAVE_MARK);
146                 caster_ptr->current_floor_ptr->grid_array[caster_ptr->current_floor_ptr->height - 1][x].info &= ~(CAVE_MARK);
147         }
148
149         /* Forget every grid on vertical edge */
150         for (POSITION y = 1; y < (caster_ptr->current_floor_ptr->height - 1); y++)
151         {
152                 caster_ptr->current_floor_ptr->grid_array[y][0].info &= ~(CAVE_MARK);
153                 caster_ptr->current_floor_ptr->grid_array[y][caster_ptr->current_floor_ptr->width - 1].info &= ~(CAVE_MARK);
154         }
155
156         /* Forget all objects */
157         for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++)
158         {
159                 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
160
161                 if (!OBJECT_IS_VALID(o_ptr)) continue;
162                 if (OBJECT_IS_HELD_MONSTER(o_ptr)) 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(caster_ptr->current_floor_ptr);
170
171         caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
172         caster_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
173         caster_ptr->update |= (PU_MONSTERS);
174         caster_ptr->redraw |= (PR_MAP);
175         caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
176 }
177
178
179 /*!
180  * @brief 守りのルーン設置処理 /
181  * Leave a "glyph of warding" which prevents monster movement
182  * @return 実際に設置が行われた場合TRUEを返す
183  */
184 bool warding_glyph(player_type *caster_ptr)
185 {
186         if (!cave_clean_bold(caster_ptr->current_floor_ptr, caster_ptr->y, caster_ptr->x))
187         {
188                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
189                 return FALSE;
190         }
191
192         /* Create a glyph */
193         caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info |= CAVE_OBJECT;
194         caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].mimic = feat_glyph;
195
196         note_spot(caster_ptr, caster_ptr->y, caster_ptr->x);
197         lite_spot(caster_ptr, caster_ptr->y, caster_ptr->x);
198
199         return TRUE;
200 }
201
202
203 /*!
204  * @brief 爆発のルーン設置処理 /
205  * Leave an "explosive rune" which prevents monster movement
206  * @param caster_ptr プレーヤーへの参照ポインタ
207  * @param y 設置場所
208  * @param x 設置場所
209  * @return 実際に設置が行われた場合TRUEを返す
210  */
211 bool explosive_rune(player_type *caster_ptr, POSITION y, POSITION x)
212 {
213         floor_type *floor_ptr = caster_ptr->current_floor_ptr;
214         if (!cave_clean_bold(floor_ptr, y, x))
215         {
216                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
217                 return FALSE;
218         }
219
220         /* Create a glyph */
221         floor_ptr->grid_array[y][x].info |= CAVE_OBJECT;
222         floor_ptr->grid_array[y][x].mimic = feat_explosive_rune;
223
224         note_spot(caster_ptr, y, x);
225         lite_spot(caster_ptr, y, x);
226
227         return TRUE;
228 }
229
230
231 /*!
232  * @brief 鏡設置処理
233  * @return 実際に設置が行われた場合TRUEを返す
234  */
235 bool place_mirror(player_type *caster_ptr)
236 {
237         if (!cave_clean_bold(caster_ptr->current_floor_ptr, caster_ptr->y, caster_ptr->x))
238         {
239                 msg_print(_("床上のアイテムが呪文を跳ね返した。", "The object resists the spell."));
240                 return FALSE;
241         }
242
243         /* Create a mirror */
244         caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info |= CAVE_OBJECT;
245         caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].mimic = feat_mirror;
246
247         /* Turn on the light */
248         caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info |= CAVE_GLOW;
249
250         note_spot(caster_ptr, caster_ptr->y, caster_ptr->x);
251         lite_spot(caster_ptr, caster_ptr->y, caster_ptr->x);
252         update_local_illumination(caster_ptr, caster_ptr->y, caster_ptr->x);
253
254         return TRUE;
255 }
256
257
258 /*!
259  * @brief プレイヤーの手による能動的な階段生成処理 /
260  * Create stairs at or move previously created stairs into the player location.
261  * @return なし
262  */
263 void stair_creation(player_type *caster_ptr)
264 {
265         /* Forbid up staircases on Ironman mode */
266         bool up = TRUE;
267         if (ironman_downward) up = FALSE;
268
269         /* Forbid down staircases on quest level */
270         bool down = TRUE;
271         floor_type *floor_ptr = caster_ptr->current_floor_ptr;
272         if (quest_number(caster_ptr, floor_ptr->dun_level) || (floor_ptr->dun_level >= d_info[caster_ptr->dungeon_idx].maxdepth)) down = FALSE;
273
274         /* No effect out of standard dungeon floor */
275         if (!floor_ptr->dun_level || (!up && !down) ||
276                 (floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest)) ||
277                 floor_ptr->inside_arena || caster_ptr->phase_out)
278         {
279                 /* arena or quest */
280                 msg_print(_("効果がありません!", "There is no effect!"));
281                 return;
282         }
283
284         /* Artifacts resists */
285         if (!cave_valid_bold(floor_ptr, caster_ptr->y, caster_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(caster_ptr, caster_ptr->y, caster_ptr->x);
293
294         /* Extract current floor data */
295         saved_floor_type *sf_ptr;
296         sf_ptr = get_sf_ptr(caster_ptr->floor_id);
297         if (!sf_ptr)
298         {
299                 /* No floor id? -- Create now! */
300                 caster_ptr->floor_id = get_new_floor_id(caster_ptr);
301                 sf_ptr = get_sf_ptr(caster_ptr->floor_id);
302         }
303
304         /* Choose randomly */
305         if (up && down)
306         {
307                 if (randint0(100) < 50) up = FALSE;
308                 else down = FALSE;
309         }
310
311         /* Destination is already fixed */
312         FLOOR_IDX dest_floor_id = 0;
313         if (up)
314         {
315                 if (sf_ptr->upper_floor_id) dest_floor_id = sf_ptr->upper_floor_id;
316         }
317         else
318         {
319                 if (sf_ptr->lower_floor_id) dest_floor_id = sf_ptr->lower_floor_id;
320         }
321         
322         /* Search old stairs leading to the destination */
323         if (dest_floor_id)
324         {
325                 POSITION x, y;
326
327                 for (y = 0; y < floor_ptr->height; y++)
328                 {
329                         for (x = 0; x < floor_ptr->width; x++)
330                         {
331                                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
332
333                                 if (!g_ptr->special) continue;
334                                 if (feat_uses_special(g_ptr->feat)) continue;
335                                 if (g_ptr->special != dest_floor_id) continue;
336
337                                 /* Remove old stairs */
338                                 g_ptr->special = 0;
339                                 cave_set_feat(caster_ptr, y, x, feat_ground_type[randint0(100)]);
340                         }
341                 }
342         }
343
344         /* No old destination -- Get new one now */
345         else
346         {
347                 dest_floor_id = get_new_floor_id(caster_ptr);
348
349                 /* Fix it */
350                 if (up)
351                         sf_ptr->upper_floor_id = dest_floor_id;
352                 else
353                         sf_ptr->lower_floor_id = dest_floor_id;
354         }
355
356         /* Extract destination floor data */
357         saved_floor_type *dest_sf_ptr;
358         dest_sf_ptr = get_sf_ptr(dest_floor_id);
359         
360         /* Create a staircase */
361         if (up)
362         {
363                 cave_set_feat(caster_ptr, caster_ptr->y, caster_ptr->x,
364                         (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level <= floor_ptr->dun_level - 2)) ?
365                         feat_state(caster_ptr, feat_up_stair, FF_SHAFT) : feat_up_stair);
366         }
367         else
368         {
369                 cave_set_feat(caster_ptr, caster_ptr->y, caster_ptr->x,
370                         (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level >= floor_ptr->dun_level + 2)) ?
371                         feat_state(caster_ptr, feat_down_stair, FF_SHAFT) : feat_down_stair);
372         }
373
374         /* Connect this stairs to the destination */
375         floor_ptr->grid_array[caster_ptr->y][caster_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(player_type *caster_ptr, POSITION range)
382 {
383         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
384
385         /* Scan that area */
386         for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++)
387         {
388                 for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++)
389                 {
390                         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
391
392                         grid_type *g_ptr;
393                         g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
394
395                         /* Memorize terrain of the grid */
396                         g_ptr->info |= (CAVE_KNOWN);
397
398                         /* Feature code (applying "mimic" field) */
399                         FEAT_IDX feat = get_feat_mimic(g_ptr);
400                         feature_type *f_ptr;
401                         f_ptr = &f_info[feat];
402
403                         /* All non-walls are "checked" */
404                         if (have_flag(f_ptr->flags, FF_WALL)) continue;
405
406                         /* Memorize normal features */
407                         if (have_flag(f_ptr->flags, FF_REMEMBER))
408                         {
409                                 /* Memorize the object */
410                                 g_ptr->info |= (CAVE_MARK);
411                         }
412
413                         /* Memorize known walls */
414                         for (int i = 0; i < 8; i++)
415                         {
416                                 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y + ddy_ddd[i]][x + ddx_ddd[i]];
417
418                                 /* Feature code (applying "mimic" field) */
419                                 feat = get_feat_mimic(g_ptr);
420                                 f_ptr = &f_info[feat];
421
422                                 /* Memorize walls (etc) */
423                                 if (have_flag(f_ptr->flags, FF_REMEMBER))
424                                 {
425                                         /* Memorize the walls */
426                                         g_ptr->info |= (CAVE_MARK);
427                                 }
428                         }
429                 }
430         }
431
432         caster_ptr->redraw |= (PR_MAP);
433         caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
434 }
435
436
437
438 /*!
439  * @brief *破壊*処理を行う / The spell of destruction
440  * @param y1 破壊の中心Y座標
441  * @param x1 破壊の中心X座標
442  * @param r 破壊の半径
443  * @param in_generate ダンジョンフロア生成中の処理ならばTRUE
444  * @return 効力があった場合TRUEを返す
445  * @details
446  * <pre>
447  * This spell "deletes" monsters (instead of "killing" them).
448  *
449  * Later we may use one function for both "destruction" and
450  * "earthquake" by using the "full" to select "destruction".
451  * </pre>
452  */
453 bool destroy_area(player_type *caster_ptr, POSITION y1, POSITION x1, POSITION r, bool in_generate)
454 {
455         /* Prevent destruction of quest levels and town */
456         floor_type *floor_ptr = caster_ptr->current_floor_ptr;
457         if ((floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest)) || !floor_ptr->dun_level)
458         {
459                 return FALSE;
460         }
461
462         /* Lose monster light */
463         if (!in_generate) clear_mon_lite(floor_ptr);
464
465         /* Big area of affect */
466         bool flag = FALSE;
467         for (POSITION y = (y1 - r); y <= (y1 + r); y++)
468         {
469                 for (POSITION x = (x1 - r); x <= (x1 + r); x++)
470                 {
471                         if (!in_bounds(floor_ptr, y, x)) continue;
472
473                         /* Extract the distance */
474                         int k = distance(y1, x1, y, x);
475
476                         /* Stay in the circle of death */
477                         if (k > r) continue;
478                         grid_type *g_ptr;
479                         g_ptr = &floor_ptr->grid_array[y][x];
480
481                         /* Lose room and vault */
482                         g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
483
484                         /* Lose light and knowledge */
485                         g_ptr->info &= ~(CAVE_MARK | CAVE_GLOW | CAVE_KNOWN);
486
487                         if (!in_generate) /* Normal */
488                         {
489                                 /* Lose unsafety */
490                                 g_ptr->info &= ~(CAVE_UNSAFE);
491
492                                 /* Hack -- Notice player affect */
493                                 if (player_bold(caster_ptr, y, x))
494                                 {
495                                         /* Hurt the player later */
496                                         flag = TRUE;
497
498                                         /* Do not hurt this grid */
499                                         continue;
500                                 }
501                         }
502
503                         /* Hack -- Skip the epicenter */
504                         if ((y == y1) && (x == x1)) continue;
505
506                         if (g_ptr->m_idx)
507                         {
508                                 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
509                                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
510
511                                 if (in_generate) /* In generation */
512                                 {
513                                         /* Delete the monster (if any) */
514                                         delete_monster(caster_ptr, y, x);
515                                 }
516                                 else if (r_ptr->flags1 & RF1_QUESTOR)
517                                 {
518                                         /* Heal the monster */
519                                         m_ptr->hp = m_ptr->maxhp;
520
521                                         /* Try to teleport away quest monsters */
522                                         if (!teleport_away(caster_ptr, g_ptr->m_idx, (r * 2) + 1, TELEPORT_DEC_VALOUR)) continue;
523                                 }
524                                 else
525                                 {
526                                         if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
527                                         {
528                                                 GAME_TEXT m_name[MAX_NLEN];
529
530                                                 monster_desc(caster_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
531                                                 exe_write_diary(caster_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_DESTROY, m_name);
532                                         }
533
534                                         /* Delete the monster (if any) */
535                                         delete_monster(caster_ptr, y, x);
536                                 }
537                         }
538
539                         /* During generation, destroyed artifacts are "preserved" */
540                         if (preserve_mode || in_generate)
541                         {
542                                 OBJECT_IDX this_o_idx, next_o_idx = 0;
543
544                                 /* Scan all objects in the grid */
545                                 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
546                                 {
547                                         object_type *o_ptr;
548                                         o_ptr = &floor_ptr->o_list[this_o_idx];
549                                         next_o_idx = o_ptr->next_o_idx;
550
551                                         /* Hack -- Preserve unknown artifacts */
552                                         if (object_is_fixed_artifact(o_ptr) && (!object_is_known(o_ptr) || in_generate))
553                                         {
554                                                 /* Mega-Hack -- Preserve the artifact */
555                                                 a_info[o_ptr->name1].cur_num = 0;
556
557                                                 if (in_generate && cheat_peek)
558                                                 {
559                                                         GAME_TEXT o_name[MAX_NLEN];
560                                                         object_desc(caster_ptr, o_name, o_ptr, (OD_NAME_ONLY | OD_STORE));
561                                                         msg_format(_("伝説のアイテム (%s) は生成中に*破壊*された。", "Artifact (%s) was *destroyed* during generation."), o_name);
562                                                 }
563                                         }
564                                         else if (in_generate && cheat_peek && o_ptr->art_name)
565                                         {
566                                                 msg_print(_("ランダム・アーティファクトの1つは生成中に*破壊*された。",
567                                                         "One of the random artifacts was *destroyed* during generation."));
568                                         }
569                                 }
570                         }
571
572                         delete_object(caster_ptr, y, x);
573
574                         /* Destroy "non-permanent" grids */
575                         if (cave_perma_grid(g_ptr)) continue;
576
577                         /* Wall (or floor) type */
578                         int t = randint0(200);
579
580                         if (!in_generate) /* Normal */
581                         {
582                                 if (t < 20)
583                                 {
584                                         /* Create granite wall */
585                                         cave_set_feat(caster_ptr, y, x, feat_granite);
586                                 }
587                                 else if (t < 70)
588                                 {
589                                         /* Create quartz vein */
590                                         cave_set_feat(caster_ptr, y, x, feat_quartz_vein);
591                                 }
592                                 else if (t < 100)
593                                 {
594                                         /* Create magma vein */
595                                         cave_set_feat(caster_ptr, y, x, feat_magma_vein);
596                                 }
597                                 else
598                                 {
599                                         /* Create floor */
600                                         cave_set_feat(caster_ptr, y, x, feat_ground_type[randint0(100)]);
601                                 }
602
603                                 continue;
604                         }
605                         
606                         if (t < 20)
607                         {
608                                 /* Create granite wall */
609                                 place_grid(caster_ptr, g_ptr, GB_EXTRA);
610                         }
611                         else if (t < 70)
612                         {
613                                 /* Create quartz vein */
614                                 g_ptr->feat = feat_quartz_vein;
615                         }
616                         else if (t < 100)
617                         {
618                                 /* Create magma vein */
619                                 g_ptr->feat = feat_magma_vein;
620                         }
621                         else
622                         {
623                                 /* Create floor */
624                                 place_grid(caster_ptr, g_ptr, GB_FLOOR);
625                         }
626
627                         /* Clear garbage of hidden trap or door */
628                         g_ptr->mimic = 0;
629                 }
630         }
631
632         if (in_generate) return TRUE;
633
634         /* Process "re-glowing" */
635         for (POSITION y = (y1 - r); y <= (y1 + r); y++)
636         {
637                 for (POSITION x = (x1 - r); x <= (x1 + r); x++)
638                 {
639                         if (!in_bounds(floor_ptr, y, x)) continue;
640
641                         /* Extract the distance */
642                         int k = distance(y1, x1, y, x);
643
644                         /* Stay in the circle of death */
645                         if (k > r) continue;
646                         grid_type *g_ptr;
647                         g_ptr = &floor_ptr->grid_array[y][x];
648
649                         if (is_mirror_grid(g_ptr))
650                         {
651                                 g_ptr->info |= CAVE_GLOW;
652                                 continue;
653                         }
654                         
655                         if ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) continue;
656
657                         DIRECTION i;
658                         POSITION yy, xx;
659                         grid_type *cc_ptr;
660
661                         for (i = 0; i < 9; i++)
662                         {
663                                 yy = y + ddy_ddd[i];
664                                 xx = x + ddx_ddd[i];
665                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
666                                 cc_ptr = &floor_ptr->grid_array[yy][xx];
667                                 if (have_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW))
668                                 {
669                                         g_ptr->info |= CAVE_GLOW;
670                                         break;
671                                 }
672                         }
673                 }
674         }
675
676         /* Hack -- Affect player */
677         if (flag)
678         {
679                 msg_print(_("燃えるような閃光が発生した!", "There is a searing blast of light!"));
680
681                 /* Blind the player */
682                 if (!caster_ptr->resist_blind && !caster_ptr->resist_lite)
683                 {
684                         /* Become blind */
685                         (void)set_blind(caster_ptr, caster_ptr->blind + 10 + randint1(10));
686                 }
687         }
688
689         forget_flow(floor_ptr);
690
691         /* Mega-Hack -- Forget the view and lite */
692         caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
693         caster_ptr->redraw |= (PR_MAP);
694         caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
695
696         if (caster_ptr->special_defense & NINJA_S_STEALTH)
697         {
698                 if (floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW) set_superstealth(caster_ptr, FALSE);
699         }
700
701         return TRUE;
702 }
703
704
705 /*!
706  * @brief 地震処理(サブルーチン) /
707  * Induce an "earthquake" of the given radius at the given location.
708  * @param caster_ptrプレーヤーへの参照ポインタ
709  * @param cy 中心Y座標
710  * @param cx 中心X座標
711  * @param r 効果半径
712  * @param m_idx 地震を起こしたモンスターID(0ならばプレイヤー)
713  * @return 効力があった場合TRUEを返す
714  * @details
715  * <pre>
716  *
717  * This will turn some walls into floors and some floors into walls.
718  *
719  * The player will take damage and "jump" into a safe grid if possible,
720  * otherwise, he will "tunnel" through the rubble instantaneously.
721  *
722  * Monsters will take damage, and "jump" into a safe grid if possible,
723  * otherwise they will be "buried" in the rubble, disappearing from
724  * the level in the same way that they do when genocided.
725  *
726  * Note that thus the player and monsters (except eaters of walls and
727  * passers through walls) will never occupy the same grid as a wall.
728  * Note that as of now (2.7.8) no monster may occupy a "wall" grid, even
729  * for a single turn, unless that monster can pass_walls or kill_walls.
730  * This has allowed massive simplification of the "monster" code.
731  * </pre>
732  */
733 bool earthquake(player_type *caster_ptr, POSITION cy, POSITION cx, POSITION r, MONSTER_IDX m_idx)
734 {
735         /* Prevent destruction of quest levels and town */
736         floor_type *floor_ptr = caster_ptr->current_floor_ptr;
737         if ((floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest)) || !floor_ptr->dun_level)
738         {
739                 return FALSE;
740         }
741
742         /* Paranoia -- Enforce maximum range */
743         if (r > 12) r = 12;
744
745         /* Clear the "maximal blast" area */
746         POSITION y, x;
747         bool map[32][32];
748         for (y = 0; y < 32; y++)
749         {
750                 for (x = 0; x < 32; x++)
751                 {
752                         map[y][x] = FALSE;
753                 }
754         }
755
756         /* Check around the epicenter */
757         POSITION yy, xx, dy, dx;
758         int damage = 0;
759         bool hurt = FALSE;
760         for (dy = -r; dy <= r; dy++)
761         {
762                 for (dx = -r; dx <= r; dx++)
763                 {
764                         yy = cy + dy;
765                         xx = cx + dx;
766
767                         if (!in_bounds(floor_ptr, yy, xx)) continue;
768
769                         /* Skip distant grids */
770                         if (distance(cy, cx, yy, xx) > r) continue;
771                         grid_type *g_ptr;
772                         g_ptr = &floor_ptr->grid_array[yy][xx];
773
774                         /* Lose room and vault / Lose light and knowledge */
775                         g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_UNSAFE);
776                         g_ptr->info &= ~(CAVE_GLOW | CAVE_MARK | CAVE_KNOWN);
777
778                         /* Skip the epicenter */
779                         if (!dx && !dy) continue;
780
781                         /* Skip most grids */
782                         if (randint0(100) < 85) continue;
783
784                         /* Damage this grid */
785                         map[16 + yy - cy][16 + xx - cx] = TRUE;
786
787                         /* Hack -- Take note of player damage */
788                         if (player_bold(caster_ptr, yy, xx)) hurt = TRUE;
789                 }
790         }
791
792         /* First, affect the player (if necessary) */
793         int sn = 0;
794         POSITION sy = 0, sx = 0;
795         if (hurt && !caster_ptr->pass_wall && !caster_ptr->kill_wall)
796         {
797                 /* Check around the player */
798                 for (DIRECTION i = 0; i < 8; i++)
799                 {
800                         y = caster_ptr->y + ddy_ddd[i];
801                         x = caster_ptr->x + ddx_ddd[i];
802
803                         /* Skip non-empty grids */
804                         if (!is_cave_empty_bold(caster_ptr, y, x)) continue;
805
806                         /* Important -- Skip "quake" grids */
807                         if (map[16 + y - cy][16 + x - cx]) continue;
808
809                         if (floor_ptr->grid_array[y][x].m_idx) continue;
810
811                         /* Count "safe" grids */
812                         sn++;
813
814                         /* Randomize choice */
815                         if (randint0(sn) > 0) continue;
816
817                         /* Save the safe location */
818                         sy = y; sx = x;
819                 }
820
821                 /* Random message */
822                 switch (randint1(3))
823                 {
824                 case 1:
825                 {
826                         msg_print(_("ダンジョンの壁が崩れた!", "The dungeon's ceiling collapses!"));
827                         break;
828                 }
829                 case 2:
830                 {
831                         msg_print(_("ダンジョンの床が不自然にねじ曲がった!", "The dungeon's floor twists in an unnatural way!"));
832                         break;
833                 }
834                 default:
835                 {
836                         msg_print(_("ダンジョンが揺れた!崩れた岩が頭に降ってきた!", "The dungeon quakes!  You are pummeled with debris!"));
837                         break;
838                 }
839                 }
840
841                 /* Hurt the player a lot */
842                 if (!sn)
843                 {
844                         /* Message and damage */
845                         msg_print(_("あなたはひどい怪我を負った!", "You are severely crushed!"));
846                         damage = 200;
847                 }
848
849                 /* Destroy the grid, and push the player to safety */
850                 else
851                 {
852                         /* Calculate results */
853                         switch (randint1(3))
854                         {
855                         case 1:
856                         {
857                                 msg_print(_("降り注ぐ岩をうまく避けた!", "You nimbly dodge the blast!"));
858                                 damage = 0;
859                                 break;
860                         }
861                         case 2:
862                         {
863                                 msg_print(_("岩石があなたに直撃した!", "You are bashed by rubble!"));
864                                 damage = damroll(10, 4);
865                                 (void)set_stun(caster_ptr, caster_ptr->stun + randint1(50));
866                                 break;
867                         }
868                         case 3:
869                         {
870                                 msg_print(_("あなたは床と壁との間に挟まれてしまった!", "You are crushed between the floor and ceiling!"));
871                                 damage = damroll(10, 4);
872                                 (void)set_stun(caster_ptr, caster_ptr->stun + randint1(50));
873                                 break;
874                         }
875                         }
876
877                         /* Move the player to the safe location */
878                         (void)move_player_effect(caster_ptr, sy, sx, MPE_DONT_PICKUP);
879                 }
880
881                 /* Important -- no wall on player */
882                 map[16 + caster_ptr->y - cy][16 + caster_ptr->x - cx] = FALSE;
883
884                 if (damage)
885                 {
886                         concptr killer;
887
888                         if (m_idx)
889                         {
890                                 GAME_TEXT m_name[MAX_NLEN];
891                                 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
892                                 monster_desc(caster_ptr, m_name, m_ptr, MD_WRONGDOER_NAME);
893                                 killer = format(_("%sの起こした地震", "an earthquake caused by %s"), m_name);
894                         }
895                         else
896                         {
897                                 killer = _("地震", "an earthquake");
898                         }
899
900                         take_hit(caster_ptr, DAMAGE_ATTACK, damage, killer, -1);
901                 }
902         }
903
904         /* Examine the quaked region */
905         for (dy = -r; dy <= r; dy++)
906         {
907                 for (dx = -r; dx <= r; dx++)
908                 {
909                         yy = cy + dy;
910                         xx = cx + dx;
911
912                         /* Skip unaffected grids */
913                         if (!map[16 + yy - cy][16 + xx - cx]) continue;
914
915                         grid_type *g_ptr;
916                         g_ptr = &floor_ptr->grid_array[yy][xx];
917
918                         if (g_ptr->m_idx == caster_ptr->riding) continue;
919
920                         /* Process monsters */
921                         if (!g_ptr->m_idx) continue;
922
923                         monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
924                         monster_race *r_ptr = &r_info[m_ptr->r_idx];
925
926                         /* Quest monsters */
927                         if (r_ptr->flags1 & RF1_QUESTOR)
928                         {
929                                 /* No wall on quest monsters */
930                                 map[16 + yy - cy][16 + xx - cx] = FALSE;
931
932                                 continue;
933                         }
934
935                         /* Most monsters cannot co-exist with rock */
936                         if ((r_ptr->flags2 & RF2_KILL_WALL) || (r_ptr->flags2 & RF2_PASS_WALL)) continue;
937
938                         GAME_TEXT m_name[MAX_NLEN];
939
940                         /* Assume not safe */
941                         sn = 0;
942
943                         /* Monster can move to escape the wall */
944                         if (!(r_ptr->flags1 & RF1_NEVER_MOVE))
945                         {
946                                 /* Look for safety */
947                                 for (DIRECTION i = 0; i < 8; i++)
948                                 {
949                                         y = yy + ddy_ddd[i];
950                                         x = xx + ddx_ddd[i];
951
952                                         /* Skip non-empty grids */
953                                         if (!is_cave_empty_bold(caster_ptr, y, x)) continue;
954
955                                         /* Hack -- no safety on glyph of warding */
956                                         if (is_glyph_grid(&floor_ptr->grid_array[y][x])) continue;
957                                         if (is_explosive_rune_grid(&floor_ptr->grid_array[y][x])) continue;
958
959                                         /* ... nor on the Pattern */
960                                         if (pattern_tile(floor_ptr, y, x)) continue;
961
962                                         /* Important -- Skip "quake" grids */
963                                         if (map[16 + y - cy][16 + x - cx]) continue;
964
965                                         if (floor_ptr->grid_array[y][x].m_idx) continue;
966                                         if (player_bold(caster_ptr, y, x)) continue;
967
968                                         /* Count "safe" grids */
969                                         sn++;
970
971                                         /* Randomize choice */
972                                         if (randint0(sn) > 0) continue;
973
974                                         /* Save the safe grid */
975                                         sy = y; sx = x;
976                                 }
977                         }
978
979                         monster_desc(caster_ptr, m_name, m_ptr, 0);
980
981                         /* Scream in pain */
982                         if (!ignore_unview || is_seen(m_ptr)) msg_format(_("%^sは苦痛で泣きわめいた!", "%^s wails out in pain!"), m_name);
983
984                         /* Take damage from the quake */
985                         damage = (sn ? damroll(4, 8) : (m_ptr->hp + 1));
986
987                         /* Monster is certainly awake */
988                         (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
989
990                         /* Apply damage directly */
991                         m_ptr->hp -= damage;
992
993                         /* Delete (not kill) "dead" monsters */
994                         if (m_ptr->hp < 0)
995                         {
996                                 if (!ignore_unview || is_seen(m_ptr))
997                                         msg_format(_("%^sは岩石に埋もれてしまった!", "%^s is embedded in the rock!"), m_name);
998
999                                 if (g_ptr->m_idx)
1000                                 {
1001                                         if (record_named_pet && is_pet(&floor_ptr->m_list[g_ptr->m_idx]) && floor_ptr->m_list[g_ptr->m_idx].nickname)
1002                                         {
1003                                                 char m2_name[MAX_NLEN];
1004
1005                                                 monster_desc(caster_ptr, m2_name, m_ptr, MD_INDEF_VISIBLE);
1006                                                 exe_write_diary(caster_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_EARTHQUAKE, m2_name);
1007                                         }
1008                                 }
1009
1010                                 delete_monster(caster_ptr, yy, xx);
1011
1012                                 sn = 0;
1013                         }
1014
1015                         /* Hack -- Escape from the rock */
1016                         if (sn == 0) continue;
1017
1018                         IDX m_idx_aux = floor_ptr->grid_array[yy][xx].m_idx;
1019
1020                         /* Update the old location */
1021                         floor_ptr->grid_array[yy][xx].m_idx = 0;
1022
1023                         /* Update the new location */
1024                         floor_ptr->grid_array[sy][sx].m_idx = m_idx_aux;
1025
1026                         /* Move the monster */
1027                         m_ptr->fy = sy;
1028                         m_ptr->fx = sx;
1029
1030                         update_monster(caster_ptr, m_idx, TRUE);
1031                         lite_spot(caster_ptr, yy, xx);
1032                         lite_spot(caster_ptr, sy, sx);
1033                 }
1034         }
1035
1036         /* Lose monster light */
1037         clear_mon_lite(floor_ptr);
1038
1039         /* Examine the quaked region */
1040         for (dy = -r; dy <= r; dy++)
1041         {
1042                 for (dx = -r; dx <= r; dx++)
1043                 {
1044                         yy = cy + dy;
1045                         xx = cx + dx;
1046
1047                         /* Skip unaffected grids */
1048                         if (!map[16 + yy - cy][16 + xx - cx]) continue;
1049
1050                         /* Destroy location (if valid) */
1051                         if (!cave_valid_bold(floor_ptr, yy, xx)) continue;
1052
1053                         delete_object(caster_ptr, yy, xx);
1054
1055                         /* Wall (or floor) type */
1056                         int t = cave_have_flag_bold(floor_ptr, yy, xx, FF_PROJECT) ? randint0(100) : 200;
1057
1058                         /* Create granite wall */
1059                         if (t < 20)
1060                         {
1061                                 cave_set_feat(caster_ptr, yy, xx, feat_granite);
1062                                 continue;
1063                         }
1064
1065                         /* Create quartz vein */
1066                         if (t < 70)
1067                         {
1068                                 cave_set_feat(caster_ptr, yy, xx, feat_quartz_vein);
1069                                 continue;
1070                         }
1071
1072                         /* Create magma vein */
1073                         if (t < 100)
1074                         {
1075                                 cave_set_feat(caster_ptr, yy, xx, feat_magma_vein);
1076                                 continue;
1077                         }
1078
1079                         /* Create floor */
1080                         cave_set_feat(caster_ptr, yy, xx, feat_ground_type[randint0(100)]);
1081                 }
1082         }
1083
1084         /* Process "re-glowing" */
1085         for (dy = -r; dy <= r; dy++)
1086         {
1087                 for (dx = -r; dx <= r; dx++)
1088                 {
1089                         yy = cy + dy;
1090                         xx = cx + dx;
1091
1092                         if (!in_bounds(floor_ptr, yy, xx)) continue;
1093
1094                         /* Skip distant grids */
1095                         if (distance(cy, cx, yy, xx) > r) continue;
1096                         grid_type *g_ptr;
1097                         g_ptr = &floor_ptr->grid_array[yy][xx];
1098
1099                         if (is_mirror_grid(g_ptr))
1100                         {
1101                                 g_ptr->info |= CAVE_GLOW;
1102                                 continue;
1103                         }
1104                         
1105                         if ((d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) continue;
1106                         
1107                         DIRECTION ii;
1108                         POSITION yyy, xxx;
1109                         grid_type *cc_ptr;
1110
1111                         for (ii = 0; ii < 9; ii++)
1112                         {
1113                                 yyy = yy + ddy_ddd[ii];
1114                                 xxx = xx + ddx_ddd[ii];
1115                                 if (!in_bounds2(floor_ptr, yyy, xxx)) continue;
1116                                 cc_ptr = &floor_ptr->grid_array[yyy][xxx];
1117                                 if (have_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW))
1118                                 {
1119                                         g_ptr->info |= CAVE_GLOW;
1120                                         break;
1121                                 }
1122                         }
1123                 }
1124         }
1125
1126         /* Mega-Hack -- Forget the view and lite */
1127         caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
1128         caster_ptr->redraw |= (PR_HEALTH | PR_UHEALTH | PR_MAP);
1129         caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1130
1131         if (caster_ptr->special_defense & NINJA_S_STEALTH)
1132         {
1133                 if (floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW) set_superstealth(caster_ptr, FALSE);
1134         }
1135
1136         /* Success */
1137         return TRUE;
1138 }