OSDN Git Service

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