OSDN Git Service

[Refactor] #38997 confuse_monsters()、charm_monsters()、charm_animals()、stun_monsters...
[hengband/hengband.git] / src / spells2.c
1 /*!
2  * @file spells2.c
3  * @brief 魔法効果の実装/ Spell code (part 2)
4  * @date 2014/07/15
5  * @author
6  * <pre>
7  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8  * This software may be copied and distributed for educational, research,
9  * and not for profit purposes provided that this copyright and statement
10  * are included in all such copies.  Other copyrights may also apply.
11  * </pre>
12  */
13
14 #include "angband.h"
15 #include "core.h"
16 #include "util.h"
17
18 #include "creature.h"
19
20 #include "artifact.h"
21 #include "cmd-pet.h"
22 #include "cmd-dump.h"
23 #include "floor.h"
24 #include "grid.h"
25 #include "trap.h"
26 #include "monsterrace-hook.h"
27 #include "melee.h"
28 #include "world.h"
29 #include "spells.h"
30 #include "spells-summon.h"
31 #include "mutation.h"
32 #include "quest.h"
33 #include "avatar.h"
34
35 #include "spells-status.h"
36 #include "spells-floor.h"
37 #include "spells-diceroll.h"
38 #include "realm-hex.h"
39 #include "autopick.h"
40 #include "object-flavor.h"
41 #include "object-hook.h"
42 #include "monster-status.h"
43 #include "player-move.h"
44 #include "player-status.h"
45 #include "player-effects.h"
46 #include "player-skill.h"
47 #include "player-class.h"
48 #include "player-damage.h"
49 #include "player-inventory.h"
50
51 #include "dungeon.h"
52 #include "floor-events.h"
53 #include "feature.h"
54 #include "view-mainwindow.h"
55 #include "objectkind.h"
56 #include "monsterrace.h"
57 #include "targeting.h"
58 #include "realm-song.h"
59 #include "english.h"
60
61 /*!
62  * @brief プレイヤー周辺の地形を感知する
63  * @param caster_ptr プレーヤーへの参照ポインタ
64  * @param range 効果範囲
65  * @param flag 特定地形ID
66  * @param known 地形から危険フラグを外すならTRUE
67  * @return 効力があった場合TRUEを返す
68  */
69 static bool detect_feat_flag(player_type *caster_ptr, POSITION range, int flag, bool known)
70 {
71         POSITION x, y;
72         bool detect = FALSE;
73         grid_type *g_ptr;
74
75         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
76
77         /* Scan the current panel */
78         for (y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++)
79         {
80                 for (x = 1; x <= caster_ptr->current_floor_ptr->width - 1; x++)
81                 {
82                         int dist = distance(caster_ptr->y, caster_ptr->x, y, x);
83                         if (dist > range) continue;
84                         g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
85
86                         /* Hack -- Safe */
87                         if (flag == FF_TRAP)
88                         {
89                                 /* Mark as detected */
90                                 if (dist <= range && known)
91                                 {
92                                         if (dist <= range - 1) g_ptr->info |= (CAVE_IN_DETECT);
93
94                                         g_ptr->info &= ~(CAVE_UNSAFE);
95
96                                         lite_spot(y, x);
97                                 }
98                         }
99
100                         if (cave_have_flag_grid(g_ptr, flag))
101                         {
102                                 disclose_grid(caster_ptr->current_floor_ptr, y, x);
103                                 g_ptr->info |= (CAVE_MARK);
104                                 lite_spot(y, x);
105                                 detect = TRUE;
106                         }
107                 }
108         }
109
110         return detect;
111 }
112
113
114 /*!
115  * @brief プレイヤー周辺のトラップを感知する / Detect all traps on current panel
116  * @param caster_ptr プレーヤーへの参照ポインタ
117  * @param range 効果範囲
118  * @param known 感知外範囲を超える警告フラグを立てる場合TRUEを返す
119  * @return 効力があった場合TRUEを返す
120  */
121 bool detect_traps(player_type *caster_ptr, POSITION range, bool known)
122 {
123         bool detect = detect_feat_flag(caster_ptr, range, FF_TRAP, known);
124
125         if (known) caster_ptr->dtrap = TRUE;
126
127         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 0) detect = FALSE;
128         if (detect)
129         {
130                 msg_print(_("トラップの存在を感じとった!", "You sense the presence of traps!"));
131         }
132
133         return detect;
134 }
135
136
137 /*!
138  * @brief プレイヤー周辺のドアを感知する / Detect all doors on current panel
139  * @param caster_ptr プレーヤーへの参照ポインタ
140  * @param range 効果範囲
141  * @return 効力があった場合TRUEを返す
142  */
143 bool detect_doors(player_type *caster_ptr, POSITION range)
144 {
145         bool detect = detect_feat_flag(caster_ptr, range, FF_DOOR, TRUE);
146
147         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 0) detect = FALSE;
148         if (detect)
149         {
150                 msg_print(_("ドアの存在を感じとった!", "You sense the presence of doors!"));
151         }
152
153         return detect;
154 }
155
156
157 /*!
158  * @brief プレイヤー周辺の階段を感知する / Detect all stairs on current panel
159  * @param caster_ptr プレーヤーへの参照ポインタ
160  * @param range 効果範囲
161  * @return 効力があった場合TRUEを返す
162  */
163 bool detect_stairs(player_type *caster_ptr, POSITION range)
164 {
165         bool detect = detect_feat_flag(caster_ptr, range, FF_STAIRS, TRUE);
166
167         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 0) detect = FALSE;
168         if (detect)
169         {
170                 msg_print(_("階段の存在を感じとった!", "You sense the presence of stairs!"));
171         }
172
173         return detect;
174 }
175
176
177 /*!
178  * @brief プレイヤー周辺の地形財宝を感知する / Detect any treasure on the current panel
179  * @param caster_ptr プレーヤーへの参照ポインタ
180  * @param range 効果範囲
181  * @return 効力があった場合TRUEを返す
182  */
183 bool detect_treasure(player_type *caster_ptr, POSITION range)
184 {
185         bool detect = detect_feat_flag(caster_ptr, range, FF_HAS_GOLD, TRUE);
186
187         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 6) detect = FALSE;
188         if (detect)
189         {
190                 msg_print(_("埋蔵された財宝の存在を感じとった!", "You sense the presence of buried treasure!"));
191         }
192
193         return detect;
194 }
195
196
197 /*!
198  * @brief プレイヤー周辺のアイテム財宝を感知する / Detect all "gold" objects on the current panel
199  * @param caster_ptr プレーヤーへの参照ポインタ
200  * @param range 効果範囲
201  * @return 効力があった場合TRUEを返す
202  */
203 bool detect_objects_gold(player_type *caster_ptr, POSITION range)
204 {
205         OBJECT_IDX i;
206         POSITION y, x;
207         POSITION range2 = range;
208
209         bool detect = FALSE;
210
211         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range2 /= 3;
212
213         /* Scan objects */
214         for (i = 1; i < caster_ptr->current_floor_ptr->o_max; i++)
215         {
216                 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
217
218                 if (!OBJECT_IS_VALID(o_ptr)) continue;
219                 if (OBJECT_IS_HELD_MONSTER(o_ptr)) continue;
220
221                 y = o_ptr->iy;
222                 x = o_ptr->ix;
223
224                 /* Only detect nearby objects */
225                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range2) continue;
226
227                 /* Detect "gold" objects */
228                 if (o_ptr->tval == TV_GOLD)
229                 {
230                         o_ptr->marked |= OM_FOUND;
231                         lite_spot(y, x);
232                         detect = TRUE;
233                 }
234         }
235
236         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 6) detect = FALSE;
237         if (detect)
238         {
239                 msg_print(_("財宝の存在を感じとった!", "You sense the presence of treasure!"));
240         }
241
242         if (detect_monsters_string(caster_ptr, range, "$"))
243         {
244                 detect = TRUE;
245         }
246
247         return (detect);
248 }
249
250
251 /*!
252  * @brief 通常のアイテムオブジェクトを感知する / Detect all "normal" objects on the current panel
253  * @param caster_ptr プレーヤーへの参照ポインタ
254  * @param range 効果範囲
255  * @return 効力があった場合TRUEを返す
256  */
257 bool detect_objects_normal(player_type *caster_ptr, POSITION range)
258 {
259         OBJECT_IDX i;
260         POSITION y, x;
261         POSITION range2 = range;
262
263         bool detect = FALSE;
264
265         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range2 /= 3;
266
267         /* Scan objects */
268         for (i = 1; i < caster_ptr->current_floor_ptr->o_max; i++)
269         {
270                 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
271
272                 if (!OBJECT_IS_VALID(o_ptr)) continue;
273                 if (OBJECT_IS_HELD_MONSTER(o_ptr)) continue;
274
275                 y = o_ptr->iy;
276                 x = o_ptr->ix;
277
278                 /* Only detect nearby objects */
279                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range2) continue;
280
281                 /* Detect "real" objects */
282                 if (o_ptr->tval != TV_GOLD)
283                 {
284                         o_ptr->marked |= OM_FOUND;
285                         lite_spot(y, x);
286                         detect = TRUE;
287                 }
288         }
289
290         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 6) detect = FALSE;
291         if (detect)
292         {
293                 msg_print(_("アイテムの存在を感じとった!", "You sense the presence of objects!"));
294         }
295
296         if (detect_monsters_string(caster_ptr, range, "!=?|/`"))
297         {
298                 detect = TRUE;
299         }
300
301         return (detect);
302 }
303
304
305 /*!
306  * @brief 魔法効果のあるのアイテムオブジェクトを感知する / Detect all "magic" objects on the current panel.
307  * @param caster_ptr プレーヤーへの参照ポインタ
308  * @param range 効果範囲
309  * @return 効力があった場合TRUEを返す
310  * @details
311  * <pre>
312  * This will light up all spaces with "magic" items, including artifacts,
313  * ego-items, potions, scrolls, books, rods, wands, staves, amulets, rings,
314  * and "enchanted" items of the "good" variety.
315  *
316  * It can probably be argued that this function is now too powerful.
317  * </pre>
318  */
319 bool detect_objects_magic(player_type *caster_ptr, POSITION range)
320 {
321         OBJECT_TYPE_VALUE tv;
322         OBJECT_IDX i;
323         POSITION y, x;
324
325         bool detect = FALSE;
326
327         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
328
329         /* Scan all objects */
330         for (i = 1; i < caster_ptr->current_floor_ptr->o_max; i++)
331         {
332                 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
333
334                 if (!OBJECT_IS_VALID(o_ptr)) continue;
335                 if (OBJECT_IS_HELD_MONSTER(o_ptr)) continue;
336
337                 y = o_ptr->iy;
338                 x = o_ptr->ix;
339
340                 /* Only detect nearby objects */
341                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
342
343                 /* Examine the tval */
344                 tv = o_ptr->tval;
345
346                 /* Artifacts, misc magic items, or enchanted wearables */
347                 if (object_is_artifact(o_ptr) ||
348                         object_is_ego(o_ptr) ||
349                     (tv == TV_WHISTLE) ||
350                     (tv == TV_AMULET) ||
351                         (tv == TV_RING) ||
352                     (tv == TV_STAFF) ||
353                         (tv == TV_WAND) ||
354                         (tv == TV_ROD) ||
355                     (tv == TV_SCROLL) ||
356                         (tv == TV_POTION) ||
357                     (tv == TV_LIFE_BOOK) ||
358                         (tv == TV_SORCERY_BOOK) ||
359                     (tv == TV_NATURE_BOOK) ||
360                         (tv == TV_CHAOS_BOOK) ||
361                     (tv == TV_DEATH_BOOK) ||
362                     (tv == TV_TRUMP_BOOK) ||
363                         (tv == TV_ARCANE_BOOK) ||
364                         (tv == TV_CRAFT_BOOK) ||
365                         (tv == TV_DAEMON_BOOK) ||
366                         (tv == TV_CRUSADE_BOOK) ||
367                         (tv == TV_MUSIC_BOOK) ||
368                         (tv == TV_HISSATSU_BOOK) ||
369                         (tv == TV_HEX_BOOK) ||
370                     ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0)))
371                 {
372                         /* Memorize the item */
373                         o_ptr->marked |= OM_FOUND;
374                         lite_spot(y, x);
375                         detect = TRUE;
376                 }
377         }
378
379         if (detect)
380         {
381                 msg_print(_("魔法のアイテムの存在を感じとった!", "You sense the presence of magic objects!"));
382         }
383
384         return (detect);
385 }
386
387
388 /*!
389  * @brief 一般のモンスターを感知する / Detect all "normal" monsters on the current panel
390  * @param caster_ptr プレーヤーへの参照ポインタ
391  * @param range 効果範囲
392  * @return 効力があった場合TRUEを返す
393  */
394 bool detect_monsters_normal(player_type *caster_ptr, POSITION range)
395 {
396         MONSTER_IDX i;
397         POSITION y, x;
398         bool flag = FALSE;
399
400         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
401
402         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
403         {
404                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
405                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
406                 if (!monster_is_valid(m_ptr)) continue;
407
408                 y = m_ptr->fy;
409                 x = m_ptr->fx;
410
411                 /* Only detect nearby monsters */
412                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
413
414                 /* Detect all non-invisible monsters */
415                 if (!(r_ptr->flags2 & RF2_INVISIBLE) || caster_ptr->see_inv)
416                 {
417                         /* Repair visibility later */
418                         repair_monsters = TRUE;
419
420                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
421                         update_monster(caster_ptr, i, FALSE);
422                         flag = TRUE;
423                 }
424         }
425
426         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 3) flag = FALSE;
427         if (flag)
428         {
429                 msg_print(_("モンスターの存在を感じとった!", "You sense the presence of monsters!"));
430         }
431
432         return (flag);
433 }
434
435
436 /*!
437  * @brief 不可視のモンスターを感知する / Detect all "invisible" monsters around the player
438  * @param caster_ptr プレーヤーへの参照ポインタ
439  * @param range 効果範囲
440  * @return 効力があった場合TRUEを返す
441  */
442 bool detect_monsters_invis(player_type *caster_ptr, POSITION range)
443 {
444         MONSTER_IDX i;
445         POSITION y, x;
446         bool flag = FALSE;
447
448         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
449
450         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
451         {
452                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
453                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
454
455                 if (!monster_is_valid(m_ptr)) continue;
456
457                 y = m_ptr->fy;
458                 x = m_ptr->fx;
459
460                 /* Only detect nearby monsters */
461                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
462
463                 /* Detect invisible monsters */
464                 if (r_ptr->flags2 & RF2_INVISIBLE)
465                 {
466                         /* Update monster recall window */
467                         if (caster_ptr->monster_race_idx == m_ptr->r_idx)
468                         {
469                                 caster_ptr->window |= (PW_MONSTER);
470                         }
471
472                         /* Repair visibility later */
473                         repair_monsters = TRUE;
474
475                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
476                         update_monster(caster_ptr, i, FALSE);
477                         flag = TRUE;
478                 }
479         }
480
481         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 3) flag = FALSE;
482         if (flag)
483         {
484                 msg_print(_("透明な生物の存在を感じとった!", "You sense the presence of invisible creatures!"));
485         }
486
487         return (flag);
488 }
489
490 /*!
491  * @brief 邪悪なモンスターを感知する / Detect all "evil" monsters on current panel
492  * @param caster_ptr プレーヤーへの参照ポインタ
493  * @param range 効果範囲
494  * @return 効力があった場合TRUEを返す
495  */
496 bool detect_monsters_evil(player_type *caster_ptr, POSITION range)
497 {
498         MONSTER_IDX i;
499         POSITION y, x;
500         bool flag = FALSE;
501
502         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
503
504         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
505         {
506                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
507                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
508                 if (!monster_is_valid(m_ptr)) continue;
509
510                 y = m_ptr->fy;
511                 x = m_ptr->fx;
512
513                 /* Only detect nearby monsters */
514                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
515
516                 /* Detect evil monsters */
517                 if (r_ptr->flags3 & RF3_EVIL)
518                 {
519                         if (is_original_ap(m_ptr))
520                         {
521                                 /* Take note that they are evil */
522                                 r_ptr->r_flags3 |= (RF3_EVIL);
523
524                                 /* Update monster recall window */
525                                 if (caster_ptr->monster_race_idx == m_ptr->r_idx)
526                                 {
527                                         caster_ptr->window |= (PW_MONSTER);
528                                 }
529                         }
530
531                         /* Repair visibility later */
532                         repair_monsters = TRUE;
533
534                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
535                         update_monster(caster_ptr, i, FALSE);
536                         flag = TRUE;
537                 }
538         }
539
540         if (flag)
541         {
542                 msg_print(_("邪悪なる生物の存在を感じとった!", "You sense the presence of evil creatures!"));
543         }
544
545         return (flag);
546 }
547
548 /*!
549  * @brief 無生命のモンスターを感知する(アンデッド、悪魔系を含む) / Detect all "nonliving", "undead" or "demonic" monsters on current panel
550  * @param caster_ptr プレーヤーへの参照ポインタ
551  * @param range 効果範囲
552  * @return 効力があった場合TRUEを返す
553  */
554 bool detect_monsters_nonliving(player_type *caster_ptr, POSITION range)
555 {
556         MONSTER_IDX i;
557         POSITION y, x;
558         bool flag = FALSE;
559
560         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
561
562         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
563         {
564                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
565                 if (!monster_is_valid(m_ptr)) continue;
566
567                 y = m_ptr->fy;
568                 x = m_ptr->fx;
569
570                 /* Only detect nearby monsters */
571                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
572
573                 /* Detect non-living monsters */
574                 if (!monster_living(m_ptr->r_idx))
575                 {
576                         /* Update monster recall window */
577                         if (caster_ptr->monster_race_idx == m_ptr->r_idx)
578                         {
579                                 caster_ptr->window |= (PW_MONSTER);
580                         }
581
582                         /* Repair visibility later */
583                         repair_monsters = TRUE;
584
585                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
586                         update_monster(caster_ptr, i, FALSE);
587                         flag = TRUE;
588                 }
589         }
590
591         if (flag)
592         {
593                 msg_print(_("自然でないモンスターの存在を感じた!", "You sense the presence of unnatural beings!"));
594         }
595
596         return (flag);
597 }
598
599 /*!
600  * @brief 精神のあるモンスターを感知する / Detect all monsters it has mind on current panel
601  * @param caster_ptr プレーヤーへの参照ポインタ
602  * @param range 効果範囲
603  * @return 効力があった場合TRUEを返す
604  */
605 bool detect_monsters_mind(player_type *caster_ptr, POSITION range)
606 {
607         MONSTER_IDX i;
608         POSITION y, x;
609         bool flag = FALSE;
610
611         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
612
613         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
614         {
615                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
616                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
617                 if (!monster_is_valid(m_ptr)) continue;
618
619                 y = m_ptr->fy;
620                 x = m_ptr->fx;
621
622                 /* Only detect nearby monsters */
623                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
624
625                 /* Detect non-living monsters */
626                 if (!(r_ptr->flags2 & RF2_EMPTY_MIND))
627                 {
628                         /* Update monster recall window */
629                         if (caster_ptr->monster_race_idx == m_ptr->r_idx)
630                         {
631                                 caster_ptr->window |= (PW_MONSTER);
632                         }
633
634                         /* Repair visibility later */
635                         repair_monsters = TRUE;
636
637                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
638                         update_monster(caster_ptr, i, FALSE);
639                         flag = TRUE;
640                 }
641         }
642
643         if (flag)
644         {
645                 msg_print(_("殺気を感じとった!", "You sense the presence of someone's mind!"));
646         }
647
648         return (flag);
649 }
650
651
652 /*!
653  * @brief 該当シンボルのモンスターを感知する / Detect all (string) monsters on current panel
654  * @param caster_ptr プレーヤーへの参照ポインタ
655  * @param range 効果範囲
656  * @param Match 対応シンボルの混じったモンスター文字列(複数指定化)
657  * @return 効力があった場合TRUEを返す
658  */
659 bool detect_monsters_string(player_type *caster_ptr, POSITION range, concptr Match)
660 {
661         MONSTER_IDX i;
662         POSITION y, x;
663         bool flag = FALSE;
664
665         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
666
667         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
668         {
669                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
670                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
671                 if (!monster_is_valid(m_ptr)) continue;
672
673                 y = m_ptr->fy;
674                 x = m_ptr->fx;
675
676                 /* Only detect nearby monsters */
677                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
678
679                 /* Detect monsters with the same symbol */
680                 if (my_strchr(Match, r_ptr->d_char))
681                 {
682                         /* Update monster recall window */
683                         if (caster_ptr->monster_race_idx == m_ptr->r_idx)
684                         {
685                                 caster_ptr->window |= (PW_MONSTER);
686                         }
687
688                         /* Repair visibility later */
689                         repair_monsters = TRUE;
690
691                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
692                         update_monster(caster_ptr, i, FALSE);
693                         flag = TRUE;
694                 }
695         }
696
697         if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 3) flag = FALSE;
698         if (flag)
699         {
700                 msg_print(_("モンスターの存在を感じとった!", "You sense the presence of monsters!"));
701         }
702
703         return (flag);
704 }
705
706 /*!
707  * @brief flags3に対応するモンスターを感知する / A "generic" detect monsters routine, tagged to flags3
708  * @param caster_ptr プレーヤーへの参照ポインタ
709  * @param range 効果範囲
710  * @param match_flag 感知フラグ
711  * @return 効力があった場合TRUEを返す
712  */
713 bool detect_monsters_xxx(player_type *caster_ptr, POSITION range, u32b match_flag)
714 {
715         MONSTER_IDX i;
716         POSITION y, x;
717         bool flag = FALSE;
718         concptr desc_monsters = _("変なモンスター", "weird monsters");
719
720         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
721
722         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
723         {
724                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
725                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
726                 if (!monster_is_valid(m_ptr)) continue;
727
728                 y = m_ptr->fy;
729                 x = m_ptr->fx;
730
731                 /* Only detect nearby monsters */
732                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range) continue;
733
734                 /* Detect evil monsters */
735                 if (r_ptr->flags3 & (match_flag))
736                 {
737                         if (is_original_ap(m_ptr))
738                         {
739                                 /* Take note that they are something */
740                                 r_ptr->r_flags3 |= (match_flag);
741
742                                 /* Update monster recall window */
743                                 if (caster_ptr->monster_race_idx == m_ptr->r_idx)
744                                 {
745                                         caster_ptr->window |= (PW_MONSTER);
746                                 }
747                         }
748
749                         /* Repair visibility later */
750                         repair_monsters = TRUE;
751
752                         m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
753                         update_monster(caster_ptr, i, FALSE);
754                         flag = TRUE;
755                 }
756         }
757
758         if (flag)
759         {
760                 switch (match_flag)
761                 {
762                         case RF3_DEMON:
763                         desc_monsters = _("デーモン", "demons");
764                                 break;
765                         case RF3_UNDEAD:
766                         desc_monsters = _("アンデッド", "the undead");
767                                 break;
768                 }
769
770                 msg_format(_("%sの存在を感じとった!", "You sense the presence of %s!"), desc_monsters);
771                 msg_print(NULL);
772         }
773
774         return (flag);
775 }
776
777
778 /*!
779  * @brief 全感知処理 / Detect everything
780  * @param caster_ptr プレーヤーへの参照ポインタ
781  * @param range 効果範囲
782  * @return 効力があった場合TRUEを返す
783  */
784 bool detect_all(player_type *caster_ptr, POSITION range)
785 {
786         bool detect = FALSE;
787
788         /* Detect everything */
789         if (detect_traps(caster_ptr, range, TRUE)) detect = TRUE;
790         if (detect_doors(caster_ptr, range)) detect = TRUE;
791         if (detect_stairs(caster_ptr, range)) detect = TRUE;
792
793         /* There are too many hidden treasure.  So... */
794         /* if (detect_treasure(range)) detect = TRUE; */
795
796         if (detect_objects_gold(caster_ptr, range)) detect = TRUE;
797         if (detect_objects_normal(caster_ptr, range)) detect = TRUE;
798         if (detect_monsters_invis(caster_ptr, range)) detect = TRUE;
799         if (detect_monsters_normal(caster_ptr, range)) detect = TRUE;
800         return (detect);
801 }
802
803
804 /*!
805  * @brief 視界内モンスターに魔法効果を与える / Apply a "project()" directly to all viewable monsters
806  * @param typ 属性効果
807  * @param dam 効果量
808  * @return 効力があった場合TRUEを返す
809  * @details
810  * <pre>
811  * Note that affected monsters are NOT auto-tracked by this usage.
812  *
813  * To avoid misbehavior when monster deaths have side-effects,
814  * this is done in two passes. -- JDL
815  * </pre>
816  */
817 bool project_all_los(player_type *caster_ptr, EFFECT_ID typ, HIT_POINT dam)
818 {
819         MONSTER_IDX i;
820         POSITION x, y;
821         BIT_FLAGS flg = PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE;
822         bool obvious = FALSE;
823
824         /* Mark all (nearby) monsters */
825         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
826         {
827                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
828                 if (!monster_is_valid(m_ptr)) continue;
829
830                 y = m_ptr->fy;
831                 x = m_ptr->fx;
832
833                 /* Require line of sight */
834                 if (!player_has_los_bold(caster_ptr, y, x) || !projectable(caster_ptr->current_floor_ptr, caster_ptr->y, caster_ptr->x, y, x)) continue;
835
836                 /* Mark the monster */
837                 m_ptr->mflag |= (MFLAG_LOS);
838         }
839
840         /* Affect all marked monsters */
841         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
842         {
843                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
844
845                 /* Skip unmarked monsters */
846                 if (!(m_ptr->mflag & (MFLAG_LOS))) continue;
847
848                 /* Remove mark */
849                 m_ptr->mflag &= ~(MFLAG_LOS);
850
851                 y = m_ptr->fy;
852                 x = m_ptr->fx;
853
854                 /* Jump directly to the target monster */
855                 if (project(caster_ptr, 0, 0, y, x, dam, typ, flg, -1)) obvious = TRUE;
856         }
857
858         return (obvious);
859 }
860
861
862 /*!
863  * @brief 視界内モンスターを加速する処理 / Speed monsters
864  * @param caster_ptr プレーヤーへの参照ポインタ
865  * @return 効力があった場合TRUEを返す
866  */
867 bool speed_monsters(player_type *caster_ptr)
868 {
869         return (project_all_los(caster_ptr, GF_OLD_SPEED, caster_ptr->lev));
870 }
871
872
873 /*!
874  * @brief 視界内モンスターを加速する処理 / Slow monsters
875  * @param caster_ptr プレーヤーへの参照ポインタ
876  * @return 効力があった場合TRUEを返す
877  */
878 bool slow_monsters(player_type *caster_ptr, int power)
879 {
880         return (project_all_los(caster_ptr, GF_OLD_SLOW, power));
881 }
882
883
884 /*!
885  * @brief 視界内モンスターを眠らせる処理 / Sleep monsters
886  * @param caster_ptr プレーヤーへの参照ポインタ
887  * @return 効力があった場合TRUEを返す
888  */
889 bool sleep_monsters(player_type *caster_ptr, int power)
890 {
891         return (project_all_los(caster_ptr, GF_OLD_SLEEP, power));
892 }
893
894
895 /*!
896  * @brief 視界内の邪悪なモンスターをテレポート・アウェイさせる処理 / Banish evil monsters
897  * @param caster_ptr プレーヤーへの参照ポインタ
898  * @return 効力があった場合TRUEを返す
899  */
900 bool banish_evil(player_type *caster_ptr, int dist)
901 {
902         return (project_all_los(caster_ptr, GF_AWAY_EVIL, dist));
903 }
904
905
906 /*!
907  * @brief 視界内のアンデッド・モンスターを恐怖させる処理 / Turn undead
908  * @return 効力があった場合TRUEを返す
909  */
910 bool turn_undead(player_type *caster_ptr)
911 {
912         bool tester = (project_all_los(caster_ptr, GF_TURN_UNDEAD, caster_ptr->lev));
913         if (tester)
914                 chg_virtue(caster_ptr, V_UNLIFE, -1);
915         return tester;
916 }
917
918
919 /*!
920  * @brief 視界内のアンデッド・モンスターにダメージを与える処理 / Dispel undead monsters
921  * @param caster_ptr プレーヤーへの参照ポインタ
922  * @return 効力があった場合TRUEを返す
923  */
924 bool dispel_undead(player_type *caster_ptr, HIT_POINT dam)
925 {
926         bool tester = (project_all_los(caster_ptr, GF_DISP_UNDEAD, dam));
927         if (tester)
928                 chg_virtue(caster_ptr, V_UNLIFE, -2);
929         return tester;
930 }
931
932
933 /*!
934  * @brief 視界内の邪悪なモンスターにダメージを与える処理 / Dispel evil monsters
935  * @param caster_ptr プレーヤーへの参照ポインタ
936  * @return 効力があった場合TRUEを返す
937  */
938 bool dispel_evil(player_type *caster_ptr, HIT_POINT dam)
939 {
940         return (project_all_los(caster_ptr, GF_DISP_EVIL, dam));
941 }
942
943
944 /*!
945  * @brief 視界内の善良なモンスターにダメージを与える処理 / Dispel good monsters
946  * @param caster_ptr プレーヤーへの参照ポインタ
947  * @return 効力があった場合TRUEを返す
948  */
949 bool dispel_good(player_type *caster_ptr, HIT_POINT dam)
950 {
951         return (project_all_los(caster_ptr, GF_DISP_GOOD, dam));
952 }
953
954
955 /*!
956  * @brief 視界内のあらゆるモンスターにダメージを与える処理 / Dispel all monsters
957  * @param caster_ptr プレーヤーへの参照ポインタ
958  * @return 効力があった場合TRUEを返す
959  */
960 bool dispel_monsters(player_type *caster_ptr, HIT_POINT dam)
961 {
962         return (project_all_los(caster_ptr, GF_DISP_ALL, dam));
963 }
964
965
966 bool cleansing_nova(player_type *creature_ptr, bool magic, bool powerful)
967 {
968         bool ident = FALSE;
969         if (dispel_evil(creature_ptr, powerful ? 225 : 150)) ident = TRUE;
970         int k = 3 * creature_ptr->lev;
971         if (set_protevil(creature_ptr, (magic ? 0 : creature_ptr->protevil) + randint1(25) + k, FALSE)) ident = TRUE;
972         if (set_poisoned(creature_ptr, 0)) ident = TRUE;
973         if (set_afraid(creature_ptr, 0)) ident = TRUE;
974         if (hp_player(creature_ptr, 50)) ident = TRUE;
975         if (set_stun(creature_ptr, 0)) ident = TRUE;
976         if (set_cut(creature_ptr,0)) ident = TRUE;
977         return ident;
978 }
979
980
981 bool unleash_mana_storm(player_type *creature_ptr, bool powerful)
982 {
983         msg_print(_("強力な魔力が敵を引き裂いた!", "Mighty magics rend your enemies!"));
984         project(creature_ptr, 0, (powerful ? 7 : 5), creature_ptr->y, creature_ptr->x,
985         (randint1(200) + (powerful ? 500 : 300)) * 2, GF_MANA, PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID, -1);
986         if ((creature_ptr->pclass != CLASS_MAGE) && (creature_ptr->pclass != CLASS_HIGH_MAGE) && (creature_ptr->pclass != CLASS_SORCERER) && (creature_ptr->pclass != CLASS_MAGIC_EATER) && (creature_ptr->pclass != CLASS_BLUE_MAGE))
987         {
988                 (void)take_hit(creature_ptr, DAMAGE_NOESCAPE, 50, _("コントロールし難い強力な魔力の解放", "unleashing magics too mighty to control"), -1);
989         }
990
991         return TRUE;
992 }
993
994
995 /*!
996  * @brief 視界内の生命のあるモンスターにダメージを与える処理 / Dispel 'living' monsters
997  * @param caster_ptr プレーヤーへの参照ポインタ
998  * @return 効力があった場合TRUEを返す
999  */
1000 bool dispel_living(player_type *caster_ptr, HIT_POINT dam)
1001 {
1002         return (project_all_los(caster_ptr, GF_DISP_LIVING, dam));
1003 }
1004
1005
1006 /*!
1007  * @brief 視界内の悪魔系モンスターにダメージを与える処理 / Dispel 'living' monsters
1008  * @param caster_ptr プレーヤーへの参照ポインタ
1009  * @return 効力があった場合TRUEを返す
1010  */
1011 bool dispel_demons(player_type *caster_ptr, HIT_POINT dam)
1012 {
1013         return (project_all_los(caster_ptr, GF_DISP_DEMON, dam));
1014 }
1015
1016
1017 /*!
1018  * @brief 視界内のモンスターに「聖戦」効果を与える処理
1019  * @param caster_ptr プレーヤーへの参照ポインタ
1020  * @return 効力があった場合TRUEを返す
1021  */
1022 bool crusade(player_type *caster_ptr)
1023 {
1024         return (project_all_los(caster_ptr, GF_CRUSADE, caster_ptr->lev*4));
1025 }
1026
1027
1028 /*!
1029  * @brief 視界内モンスターを怒らせる処理 / Wake up all monsters, and speed up "los" monsters.
1030  * @param caster_ptr プレーヤーへの参照ポインタ
1031  * @param who 怒らせる原因を起こしたモンスター(0ならばプレイヤー)
1032  * @return なし
1033  */
1034 void aggravate_monsters(player_type *caster_ptr, MONSTER_IDX who)
1035 {
1036         MONSTER_IDX i;
1037         bool sleep = FALSE;
1038         bool speed = FALSE;
1039
1040         /* Aggravate everyone nearby */
1041         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1042         {
1043                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1044                 if (!monster_is_valid(m_ptr)) continue;
1045
1046                 /* Skip aggravating monster (or player) */
1047                 if (i == who) continue;
1048
1049                 /* Wake up nearby sleeping monsters */
1050                 if (m_ptr->cdis < MAX_SIGHT * 2)
1051                 {
1052                         /* Wake up */
1053                         if (MON_CSLEEP(m_ptr))
1054                         {
1055                                 (void)set_monster_csleep(i, 0);
1056                                 sleep = TRUE;
1057                         }
1058                         if (!is_pet(m_ptr)) m_ptr->mflag2 |= MFLAG2_NOPET;
1059                 }
1060
1061                 /* Speed up monsters in line of sight */
1062                 if (player_has_los_bold(caster_ptr, m_ptr->fy, m_ptr->fx))
1063                 {
1064                         if (!is_pet(m_ptr))
1065                         {
1066                                 (void)set_monster_fast(i, MON_FAST(m_ptr) + 100);
1067                                 speed = TRUE;
1068                         }
1069                 }
1070         }
1071
1072         if (speed) msg_print(_("付近で何かが突如興奮したような感じを受けた!", "You feel a sudden stirring nearby!"));
1073         else if (sleep) msg_print(_("何かが突如興奮したような騒々しい音が遠くに聞こえた!", "You hear a sudden stirring in the distance!"));
1074         if (caster_ptr->riding) caster_ptr->update |= PU_BONUS;
1075 }
1076
1077
1078 /*!
1079  * @brief モンスターへの単体抹殺処理サブルーチン / Delete a non-unique/non-quest monster
1080  * @param m_idx 抹殺するモンスターID
1081  * @param power 抹殺の威力
1082  * @param player_cast プレイヤーの魔法によるものならば TRUE
1083  * @param dam_side プレイヤーへの負担ダメージ量(1d(dam_side))
1084  * @param spell_name 抹殺効果を起こした魔法の名前
1085  * @return 効力があった場合TRUEを返す
1086  */
1087 bool genocide_aux(player_type *caster_ptr, MONSTER_IDX m_idx, int power, bool player_cast, int dam_side, concptr spell_name)
1088 {
1089         int          msec = delay_factor * delay_factor * delay_factor;
1090         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
1091         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1092         bool         resist = FALSE;
1093
1094         if (is_pet(m_ptr) && !player_cast) return FALSE;
1095
1096         /* Hack -- Skip Unique Monsters or Quest Monsters */
1097         if (r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) resist = TRUE;
1098         else if (r_ptr->flags7 & RF7_UNIQUE2) resist = TRUE;
1099         else if (m_idx == caster_ptr->riding) resist = TRUE;
1100         else if ((caster_ptr->current_floor_ptr->inside_quest && !random_quest_number(caster_ptr->current_floor_ptr->dun_level)) || caster_ptr->current_floor_ptr->inside_arena || caster_ptr->phase_out) resist = TRUE;
1101         else if (player_cast && (r_ptr->level > randint0(power))) resist = TRUE;
1102         else if (player_cast && (m_ptr->mflag2 & MFLAG2_NOGENO)) resist = TRUE;
1103
1104         else
1105         {
1106                 if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
1107                 {
1108                         GAME_TEXT m_name[MAX_NLEN];
1109
1110                         monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE);
1111                         exe_write_diary(caster_ptr, NIKKI_NAMED_PET, RECORD_NAMED_PET_GENOCIDE, m_name);
1112                 }
1113
1114                 delete_monster_idx(m_idx);
1115         }
1116
1117         if (resist && player_cast)
1118         {
1119                 bool see_m = is_seen(m_ptr);
1120                 GAME_TEXT m_name[MAX_NLEN];
1121
1122                 monster_desc(m_name, m_ptr, 0);
1123                 if (see_m)
1124                 {
1125                         msg_format(_("%^sには効果がなかった。", "%^s is unaffected."), m_name);
1126                 }
1127
1128                 if (MON_CSLEEP(m_ptr))
1129                 {
1130                         (void)set_monster_csleep(m_idx, 0);
1131                         if (m_ptr->ml)
1132                         {
1133                                 msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
1134                         }
1135                 }
1136
1137                 if (is_friendly(m_ptr) && !is_pet(m_ptr))
1138                 {
1139                         if (see_m)
1140                         {
1141                                 msg_format(_("%sは怒った!", "%^s gets angry!"), m_name);
1142                         }
1143                         set_hostile(m_ptr);
1144                 }
1145
1146                 if (one_in_(13)) m_ptr->mflag2 |= MFLAG2_NOGENO;
1147         }
1148
1149         if (player_cast)
1150         {
1151                 take_hit(caster_ptr, DAMAGE_GENO, randint1(dam_side), format(_("%^sの呪文を唱えた疲労", "the strain of casting %^s"), spell_name), -1);
1152         }
1153
1154         /* Visual feedback */
1155         move_cursor_relative(caster_ptr->y, caster_ptr->x);
1156
1157         caster_ptr->redraw |= (PR_HP);
1158         caster_ptr->window |= (PW_PLAYER);
1159
1160         handle_stuff();
1161         Term_fresh();
1162
1163         Term_xtra(TERM_XTRA_DELAY, msec);
1164
1165         return !resist;
1166 }
1167
1168
1169 /*!
1170  * @brief モンスターへのシンボル抹殺処理ルーチン / Delete all non-unique/non-quest monsters of a given "type" from the level
1171  * @param power 抹殺の威力
1172  * @param player_cast プレイヤーの魔法によるものならば TRUE
1173  * @return 効力があった場合TRUEを返す
1174  */
1175 bool symbol_genocide(player_type *caster_ptr, int power, bool player_cast)
1176 {
1177         MONSTER_IDX i;
1178         char typ;
1179         bool result = FALSE;
1180
1181         /* Prevent genocide in quest levels */
1182         if ((caster_ptr->current_floor_ptr->inside_quest && !random_quest_number(caster_ptr->current_floor_ptr->dun_level)) || caster_ptr->current_floor_ptr->inside_arena || caster_ptr->phase_out)
1183         {
1184                 msg_print(_("何も起きないようだ……", "It seems nothing happen here..."));
1185                 return (FALSE);
1186         }
1187
1188         /* Mega-Hack -- Get a monster symbol */
1189         while (!get_com(_("どの種類(文字)のモンスターを抹殺しますか: ", "Choose a monster race (by symbol) to genocide: "), &typ, FALSE)) ;
1190
1191         /* Delete the monsters of that "type" */
1192         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1193         {
1194                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1195                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
1196                 if (!monster_is_valid(m_ptr)) continue;
1197
1198                 /* Skip "wrong" monsters */
1199                 if (r_ptr->d_char != typ) continue;
1200
1201                 result |= genocide_aux(caster_ptr, i, power, player_cast, 4, _("抹殺", "Genocide"));
1202         }
1203
1204         if (result)
1205         {
1206                 chg_virtue(caster_ptr, V_VITALITY, -2);
1207                 chg_virtue(caster_ptr, V_CHANCE, -1);
1208         }
1209
1210         return result;
1211 }
1212
1213
1214 /*!
1215  * @brief モンスターへの周辺抹殺処理ルーチン / Delete all nearby (non-unique) monsters
1216  * @param power 抹殺の威力
1217  * @param player_cast プレイヤーの魔法によるものならば TRUE
1218  * @return 効力があった場合TRUEを返す
1219  */
1220 bool mass_genocide(player_type *caster_ptr, int power, bool player_cast)
1221 {
1222         MONSTER_IDX i;
1223         bool result = FALSE;
1224
1225         /* Prevent mass genocide in quest levels */
1226         if ((caster_ptr->current_floor_ptr->inside_quest && !random_quest_number(caster_ptr->current_floor_ptr->dun_level)) || caster_ptr->current_floor_ptr->inside_arena || caster_ptr->phase_out)
1227         {
1228                 return (FALSE);
1229         }
1230
1231         /* Delete the (nearby) monsters */
1232         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1233         {
1234                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1235                 if (!monster_is_valid(m_ptr)) continue;
1236
1237                 /* Skip distant monsters */
1238                 if (m_ptr->cdis > MAX_SIGHT) continue;
1239
1240                 /* Note effect */
1241                 result |= genocide_aux(caster_ptr, i, power, player_cast, 3, _("周辺抹殺", "Mass Genocide"));
1242         }
1243
1244         if (result)
1245         {
1246                 chg_virtue(caster_ptr, V_VITALITY, -2);
1247                 chg_virtue(caster_ptr, V_CHANCE, -1);
1248         }
1249
1250         return result;
1251 }
1252
1253
1254 /*!
1255  * @brief アンデッド・モンスターへの周辺抹殺処理ルーチン / Delete all nearby (non-unique) undead
1256  * @param power 抹殺の威力
1257  * @param player_cast プレイヤーの魔法によるものならば TRUE
1258  * @return 効力があった場合TRUEを返す
1259  */
1260 bool mass_genocide_undead(player_type *caster_ptr, int power, bool player_cast)
1261 {
1262         MONSTER_IDX i;
1263         bool result = FALSE;
1264
1265         /* Prevent mass genocide in quest levels */
1266         if ((caster_ptr->current_floor_ptr->inside_quest && !random_quest_number(caster_ptr->current_floor_ptr->dun_level)) || caster_ptr->current_floor_ptr->inside_arena || caster_ptr->phase_out)
1267         {
1268                 return (FALSE);
1269         }
1270
1271         /* Delete the (nearby) monsters */
1272         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1273         {
1274                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1275                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
1276                 if (!monster_is_valid(m_ptr)) continue;
1277
1278                 if (!(r_ptr->flags3 & RF3_UNDEAD)) continue;
1279
1280                 /* Skip distant monsters */
1281                 if (m_ptr->cdis > MAX_SIGHT) continue;
1282
1283                 /* Note effect */
1284                 result |= genocide_aux(caster_ptr, i, power, player_cast, 3, _("アンデッド消滅", "Annihilate Undead"));
1285         }
1286
1287         if (result)
1288         {
1289                 chg_virtue(caster_ptr, V_UNLIFE, -2);
1290                 chg_virtue(caster_ptr, V_CHANCE, -1);
1291         }
1292
1293         return result;
1294 }
1295
1296
1297 /*!
1298  * @brief 周辺モンスターを調査する / Probe nearby monsters
1299  * @return 効力があった場合TRUEを返す
1300  */
1301 bool probing(player_type *caster_ptr)
1302 {
1303         int i;
1304         int speed; /* TODO */
1305         bool_hack cu, cv;
1306         bool probe = FALSE;
1307         char buf[256];
1308         concptr align;
1309
1310         cu = Term->scr->cu;
1311         cv = Term->scr->cv;
1312         Term->scr->cu = 0;
1313         Term->scr->cv = 1;
1314
1315         /* Probe all (nearby) monsters */
1316         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1317         {
1318                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1319                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
1320                 if (!monster_is_valid(m_ptr)) continue;
1321
1322                 /* Require line of sight */
1323                 if (!player_has_los_bold(caster_ptr, m_ptr->fy, m_ptr->fx)) continue;
1324
1325                 /* Probe visible monsters */
1326                 if (m_ptr->ml)
1327                 {
1328                         GAME_TEXT m_name[MAX_NLEN];
1329
1330                         /* Start the message */
1331                         if (!probe)
1332                         {
1333                                 msg_print(_("調査中...", "Probing..."));
1334                         }
1335
1336                         msg_print(NULL);
1337
1338                         if (!is_original_ap(m_ptr))
1339                         {
1340                                 if (m_ptr->mflag2 & MFLAG2_KAGE)
1341                                         m_ptr->mflag2 &= ~(MFLAG2_KAGE);
1342
1343                                 m_ptr->ap_r_idx = m_ptr->r_idx;
1344                                 lite_spot(m_ptr->fy, m_ptr->fx);
1345                         }
1346                         /* Get "the monster" or "something" */
1347                         monster_desc(m_name, m_ptr, MD_IGNORE_HALLU | MD_INDEF_HIDDEN);
1348
1349                         speed = m_ptr->mspeed - 110;
1350                         if (MON_FAST(m_ptr)) speed += 10;
1351                         if (MON_SLOW(m_ptr)) speed -= 10;
1352                         if (ironman_nightmare) speed += 5;
1353
1354                         /* Get the monster's alignment */
1355                         if ((r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)) == (RF3_EVIL | RF3_GOOD)) align = _("善悪", "good&evil");
1356                         else if (r_ptr->flags3 & RF3_EVIL) align = _("邪悪", "evil");
1357                         else if (r_ptr->flags3 & RF3_GOOD) align = _("善良", "good");
1358                         else if ((m_ptr->sub_align & (SUB_ALIGN_EVIL | SUB_ALIGN_GOOD)) == (SUB_ALIGN_EVIL | SUB_ALIGN_GOOD)) align = _("中立(善悪)", "neutral(good&evil)");
1359                         else if (m_ptr->sub_align & SUB_ALIGN_EVIL) align = _("中立(邪悪)", "neutral(evil)");
1360                         else if (m_ptr->sub_align & SUB_ALIGN_GOOD) align = _("中立(善良)", "neutral(good)");
1361                         else align = _("中立", "neutral");
1362
1363                         sprintf(buf,_("%s ... 属性:%s HP:%d/%d AC:%d 速度:%s%d 経験:", "%s ... align:%s HP:%d/%d AC:%d speed:%s%d exp:"),
1364                                 m_name, align, (int)m_ptr->hp, (int)m_ptr->maxhp, r_ptr->ac, (speed > 0) ? "+" : "", speed);
1365
1366                         if (r_ptr->next_r_idx)
1367                         {
1368                                 strcat(buf, format("%d/%d ", m_ptr->exp, r_ptr->next_exp));
1369                         }
1370                         else
1371                         {
1372                                 strcat(buf, "xxx ");
1373                         }
1374
1375                         if (MON_CSLEEP(m_ptr)) strcat(buf,_("睡眠 ", "sleeping "));
1376                         if (MON_STUNNED(m_ptr)) strcat(buf, _("朦朧 ", "stunned "));
1377                         if (MON_MONFEAR(m_ptr)) strcat(buf, _("恐怖 ", "scared "));
1378                         if (MON_CONFUSED(m_ptr)) strcat(buf, _("混乱 ", "confused "));
1379                         if (MON_INVULNER(m_ptr)) strcat(buf, _("無敵 ", "invulnerable "));
1380                         buf[strlen(buf)-1] = '\0';
1381                         prt(buf, 0, 0);
1382
1383                         /* HACK : Add the line to message buffer */
1384                         message_add(buf);
1385
1386                         caster_ptr->window |= (PW_MESSAGE);
1387                         handle_stuff();
1388
1389                         if (m_ptr->ml) move_cursor_relative(m_ptr->fy, m_ptr->fx);
1390                         inkey();
1391
1392                         Term_erase(0, 0, 255);
1393
1394                         /* Learn everything about this monster */
1395                         if (lore_do_probe(m_ptr->r_idx))
1396                         {
1397                                 /* Get base name of monster */
1398                                 strcpy(buf, (r_name + r_ptr->name));
1399
1400 #ifdef JP
1401                                 /* Note that we learnt some new flags  -Mogami- */
1402                                 msg_format("%sについてさらに詳しくなった気がする。", buf);
1403 #else
1404                                 /* Pluralize it */
1405                                 plural_aux(buf);
1406
1407                                 /* Note that we learnt some new flags  -Mogami- */
1408                                 msg_format("You now know more about %s.", buf);
1409 #endif
1410                                 /* Clear -more- prompt */
1411                                 msg_print(NULL);
1412                         }
1413
1414                         /* Probe worked */
1415                         probe = TRUE;
1416                 }
1417         }
1418
1419         Term->scr->cu = cu;
1420         Term->scr->cv = cv;
1421         Term_fresh();
1422
1423         if (probe)
1424         {
1425                 chg_virtue(caster_ptr, V_KNOWLEDGE, 1);
1426                 msg_print(_("これで全部です。", "That's all."));
1427         }
1428
1429         return (probe);
1430 }
1431
1432
1433 /*!
1434  * @brief ペット爆破処理 /
1435  * @return なし
1436  */
1437 void discharge_minion(player_type *caster_ptr)
1438 {
1439         MONSTER_IDX i;
1440         bool okay = TRUE;
1441
1442         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1443         {
1444                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1445                 if (!m_ptr->r_idx || !is_pet(m_ptr)) continue;
1446                 if (m_ptr->nickname) okay = FALSE;
1447         }
1448
1449         if (!okay || caster_ptr->riding)
1450         {
1451                 if (!get_check(_("本当に全ペットを爆破しますか?", "You will blast all pets. Are you sure? ")))
1452                         return;
1453         }
1454
1455         for (i = 1; i < caster_ptr->current_floor_ptr->m_max; i++)
1456         {
1457                 HIT_POINT dam;
1458                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
1459                 monster_race *r_ptr;
1460
1461                 if (!m_ptr->r_idx || !is_pet(m_ptr)) continue;
1462                 r_ptr = &r_info[m_ptr->r_idx];
1463
1464                 /* Uniques resist discharging */
1465                 if (r_ptr->flags1 & RF1_UNIQUE)
1466                 {
1467                         GAME_TEXT m_name[MAX_NLEN];
1468                         monster_desc(m_name, m_ptr, 0x00);
1469                         msg_format(_("%sは爆破されるのを嫌がり、勝手に自分の世界へと帰った。", "%^s resists to be blasted, and run away."), m_name);
1470                         delete_monster_idx(i);
1471                         continue;
1472                 }
1473                 dam = m_ptr->maxhp / 2;
1474                 if (dam > 100) dam = (dam - 100) / 2 + 100;
1475                 if (dam > 400) dam = (dam - 400) / 2 + 400;
1476                 if (dam > 800) dam = 800;
1477                 project(caster_ptr, i, 2 + (r_ptr->level / 20), m_ptr->fy, m_ptr->fx, dam, GF_PLASMA, 
1478                         PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL, -1);
1479
1480                 if (record_named_pet && m_ptr->nickname)
1481                 {
1482                         GAME_TEXT m_name[MAX_NLEN];
1483
1484                         monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE);
1485                         exe_write_diary(caster_ptr, NIKKI_NAMED_PET, RECORD_NAMED_PET_BLAST, m_name);
1486                 }
1487
1488                 delete_monster_idx(i);
1489         }
1490 }
1491
1492
1493 /*!
1494  * todo この辺、xとyが引数になっているが、caster_ptr->xとcaster_ptr->yで全て置き換えが効くはず……
1495  * @brief 部屋全体を照らすサブルーチン
1496  * @param caster_ptr プレーヤーへの参照ポインタ
1497  * @return なし
1498  * @details
1499  * <pre>
1500  * This routine clears the entire "temp" set.
1501  * This routine will Perma-Lite all "temp" grids.
1502  * This routine is used (only) by "lite_room()"
1503  * Dark grids are illuminated.
1504  * Also, process all affected monsters.
1505  *
1506  * SMART monsters always wake up when illuminated
1507  * NORMAL monsters wake up 1/4 the time when illuminated
1508  * STUPID monsters wake up 1/10 the time when illuminated
1509  * </pre>
1510  */
1511 static void cave_temp_room_lite(player_type *caster_ptr)
1512 {
1513         int i;
1514
1515         /* Clear them all */
1516         for (i = 0; i < tmp_pos.n; i++)
1517         {
1518                 POSITION y = tmp_pos.y[i];
1519                 POSITION x = tmp_pos.x[i];
1520
1521                 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
1522
1523                 /* No longer in the array */
1524                 g_ptr->info &= ~(CAVE_TEMP);
1525
1526                 /* Update only non-CAVE_GLOW grids */
1527                 /* if (g_ptr->info & (CAVE_GLOW)) continue; */
1528
1529                 /* Perma-Lite */
1530                 g_ptr->info |= (CAVE_GLOW);
1531
1532                 /* Process affected monsters */
1533                 if (g_ptr->m_idx)
1534                 {
1535                         PERCENTAGE chance = 25;
1536                         monster_type    *m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
1537                         monster_race    *r_ptr = &r_info[m_ptr->r_idx];
1538                         update_monster(caster_ptr, g_ptr->m_idx, FALSE);
1539
1540                         /* Stupid monsters rarely wake up */
1541                         if (r_ptr->flags2 & (RF2_STUPID)) chance = 10;
1542
1543                         /* Smart monsters always wake up */
1544                         if (r_ptr->flags2 & (RF2_SMART)) chance = 100;
1545
1546                         /* Sometimes monsters wake up */
1547                         if (MON_CSLEEP(m_ptr) && (randint0(100) < chance))
1548                         {
1549                                 /* Wake up! */
1550                                 (void)set_monster_csleep(g_ptr->m_idx, 0);
1551
1552                                 /* Notice the "waking up" */
1553                                 if (m_ptr->ml)
1554                                 {
1555                                         GAME_TEXT m_name[MAX_NLEN];
1556                                         monster_desc(m_name, m_ptr, 0);
1557                                         msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
1558                                 }
1559                         }
1560                 }
1561
1562                 note_spot(y, x);
1563                 lite_spot(y, x);
1564                 update_local_illumination(caster_ptr, y, x);
1565         }
1566
1567         tmp_pos.n = 0;
1568 }
1569
1570
1571 /*!
1572  * todo この辺、xとyが引数になっているが、caster_ptr->xとcaster_ptr->yで全て置き換えが効くはず……
1573  * @brief 部屋全体を暗くするサブルーチン
1574  * @param caster_ptr プレーヤーへの参照ポインタ
1575  * @return なし
1576  * @details
1577  * <pre>
1578  * This routine clears the entire "temp" set.
1579  * This routine will "darken" all "temp" grids.
1580  * In addition, some of these grids will be "unmarked".
1581  * This routine is used (only) by "unlite_room()"
1582  * Also, process all affected monsters
1583  * </pre>
1584  */
1585 static void cave_temp_room_unlite(player_type *caster_ptr)
1586 {
1587         int i;
1588
1589         /* Clear them all */
1590         for (i = 0; i < tmp_pos.n; i++)
1591         {
1592                 POSITION y = tmp_pos.y[i];
1593                 POSITION x = tmp_pos.x[i];
1594                 int j;
1595
1596                 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
1597                 bool do_dark = !is_mirror_grid(g_ptr);
1598
1599                 /* No longer in the array */
1600                 g_ptr->info &= ~(CAVE_TEMP);
1601
1602                 /* Darken the grid */
1603                 if (do_dark)
1604                 {
1605                         if (caster_ptr->current_floor_ptr->dun_level || !is_daytime())
1606                         {
1607                                 for (j = 0; j < 9; j++)
1608                                 {
1609                                         POSITION by = y + ddy_ddd[j];
1610                                         POSITION bx = x + ddx_ddd[j];
1611
1612                                         if (in_bounds2(caster_ptr->current_floor_ptr, by, bx))
1613                                         {
1614                                                 grid_type *cc_ptr = &caster_ptr->current_floor_ptr->grid_array[by][bx];
1615
1616                                                 if (have_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW))
1617                                                 {
1618                                                         do_dark = FALSE;
1619                                                         break;
1620                                                 }
1621                                         }
1622                                 }
1623
1624                                 if (!do_dark) continue;
1625                         }
1626
1627                         g_ptr->info &= ~(CAVE_GLOW);
1628
1629                         /* Hack -- Forget "boring" grids */
1630                         if (!have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_REMEMBER))
1631                         {
1632                                 /* Forget the grid */
1633                                 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
1634                                 note_spot(y, x);
1635                         }
1636
1637                         /* Process affected monsters */
1638                         if (g_ptr->m_idx)
1639                         {
1640                                 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
1641                         }
1642
1643                         lite_spot(y, x);
1644                         update_local_illumination(caster_ptr, y, x);
1645                 }
1646         }
1647
1648         tmp_pos.n = 0;
1649 }
1650
1651
1652 /*!
1653  * @brief 周辺に関数ポインタの条件に該当する地形がいくつあるかを計算する / Determine how much contiguous open space this grid is next to
1654  * @param floor_ptr 配置するフロアの参照ポインタ
1655  * @param cy Y座標
1656  * @param cx X座標
1657  * @param pass_bold 地形条件を返す関数ポインタ
1658  * @return 該当地形の数
1659  */
1660 static int next_to_open(floor_type *floor_ptr, POSITION cy, POSITION cx, bool (*pass_bold)(floor_type*, POSITION, POSITION))
1661 {
1662         int i;
1663         POSITION y, x;
1664         int len = 0;
1665         int blen = 0;
1666
1667         for (i = 0; i < 16; i++)
1668         {
1669                 y = cy + ddy_cdd[i % 8];
1670                 x = cx + ddx_cdd[i % 8];
1671
1672                 /* Found a wall, break the length */
1673                 if (!pass_bold(floor_ptr, y, x))
1674                 {
1675                         /* Track best length */
1676                         if (len > blen)
1677                         {
1678                                 blen = len;
1679                         }
1680
1681                         len = 0;
1682                 }
1683                 else
1684                 {
1685                         len++;
1686                 }
1687         }
1688
1689         return (MAX(len, blen));
1690 }
1691
1692
1693 /*!
1694  * @brief 周辺に関数ポインタの条件に該当する地形がいくつあるかを計算する / Determine how much contiguous open space this grid is next to
1695  * @param floor_ptr 配置するフロアの参照ポインタ
1696  * @param cy Y座標
1697  * @param cx X座標
1698  * @param pass_bold 地形条件を返す関数ポインタ
1699  * @return 該当地形の数
1700  */
1701 static int next_to_walls_adj(floor_type *floor_ptr, POSITION cy, POSITION cx, bool (*pass_bold)(floor_type*, POSITION, POSITION))
1702 {
1703         DIRECTION i;
1704         POSITION y, x;
1705         int c = 0;
1706
1707         for (i = 0; i < 8; i++)
1708         {
1709                 y = cy + ddy_ddd[i];
1710                 x = cx + ddx_ddd[i];
1711
1712                 if (!pass_bold(floor_ptr, y, x)) c++;
1713         }
1714
1715         return c;
1716 }
1717
1718
1719 /*!
1720  * @brief 部屋内にある一点の周囲に該当する地形数かいくつあるかをグローバル変数tmp_pos.nに返す / Aux function -- see below
1721  * @param caster_ptr プレーヤーへの参照ポインタ
1722  * @param y 部屋内のy座標1点
1723  * @param x 部屋内のx座標1点
1724  * @param only_room 部屋内地形のみをチェック対象にするならば TRUE
1725  * @param pass_bold 地形条件を返す関数ポインタ
1726  * @return 該当地形の数
1727  */
1728 static void cave_temp_room_aux(player_type *caster_ptr, POSITION y, POSITION x, bool only_room, bool (*pass_bold)(floor_type*, POSITION, POSITION))
1729 {
1730         grid_type *g_ptr;
1731         floor_type *floor_ptr = caster_ptr->current_floor_ptr;
1732         g_ptr = &floor_ptr->grid_array[y][x];
1733
1734         /* Avoid infinite recursion */
1735         if (g_ptr->info & (CAVE_TEMP)) return;
1736
1737         /* Do not "leave" the current room */
1738         if (!(g_ptr->info & (CAVE_ROOM)))
1739         {
1740                 if (only_room) return;
1741
1742                 /* Verify */
1743                 if (!in_bounds2(floor_ptr, y, x)) return;
1744
1745                 /* Do not exceed the maximum spell range */
1746                 if (distance(caster_ptr->y, caster_ptr->x, y, x) > MAX_RANGE) return;
1747
1748                 /* Verify this grid */
1749                 /*
1750                  * The reason why it is ==6 instead of >5 is that 8 is impossible
1751                  * due to the check for cave_bold above.
1752                  * 7 lights dead-end corridors (you need to do this for the
1753                  * checkboard interesting rooms, so that the boundary is lit
1754                  * properly.
1755                  * This leaves only a check for 6 bounding walls!
1756                  */
1757                 if (in_bounds(floor_ptr, y, x) && pass_bold(floor_ptr, y, x) &&
1758                     (next_to_walls_adj(floor_ptr, y, x, pass_bold) == 6) && (next_to_open(floor_ptr, y, x, pass_bold) <= 1)) return;
1759         }
1760
1761         /* Paranoia -- verify space */
1762         if (tmp_pos.n == TEMP_MAX) return;
1763
1764         /* Mark the grid as "seen" */
1765         g_ptr->info |= (CAVE_TEMP);
1766
1767         /* Add it to the "seen" set */
1768         tmp_pos.y[tmp_pos.n] = y;
1769         tmp_pos.x[tmp_pos.n] = x;
1770         tmp_pos.n++;
1771 }
1772
1773
1774 /*!
1775  * todo このシンタックスシュガーは不要だが、関数ポインタなので安易には消せず……
1776  * @brief 指定のマスが光を通すか(LOSフラグを持つか)を返す。 / Aux function -- see below
1777  * @param floor_ptr 配置するフロアの参照ポインタ
1778  * @param y 指定Y座標
1779  * @param x 指定X座標
1780  * @return 光を通すならばtrueを返す。
1781  */
1782 static bool cave_pass_lite_bold(floor_type *floor_ptr, POSITION y, POSITION x)
1783 {
1784         return cave_los_bold(floor_ptr, y, x);
1785 }
1786
1787
1788 /*!
1789  * @brief 部屋内にある一点の周囲がいくつ光を通すかをグローバル変数tmp_pos.nに返す / Aux function -- see below
1790 * @param caster_ptr プレーヤーへの参照ポインタ
1791   * @param y 指定Y座標
1792  * @param x 指定X座標
1793  * @return なし
1794  */
1795 static void cave_temp_lite_room_aux(player_type *caster_ptr, POSITION y, POSITION x)
1796 {
1797         cave_temp_room_aux(caster_ptr, y, x, FALSE, cave_pass_lite_bold);
1798 }
1799
1800
1801 /*!
1802  * @brief 指定のマスが光を通さず射線のみを通すかを返す。 / Aux function -- see below
1803  * @param floor_ptr 配置するフロアの参照ポインタ
1804  * @param y 指定Y座標
1805  * @param x 指定X座標
1806  * @return 射線を通すならばtrueを返す。
1807  */
1808 static bool cave_pass_dark_bold(floor_type *floor_ptr, POSITION y, POSITION x)
1809 {
1810         return cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT);
1811 }
1812
1813
1814 /*!
1815  * @brief 部屋内にある一点の周囲がいくつ射線を通すかをグローバル変数tmp_pos.nに返す / Aux function -- see below
1816  * @param caster_ptr プレーヤーへの参照ポインタ
1817  * @param y 指定Y座標
1818  * @param x 指定X座標
1819  * @return なし
1820  */
1821 static void cave_temp_unlite_room_aux(player_type *caster_ptr, POSITION y, POSITION x)
1822 {
1823         cave_temp_room_aux(caster_ptr, y, x, TRUE, cave_pass_dark_bold);
1824 }
1825
1826
1827 /*!
1828  * @brief 指定された部屋内を照らす / Illuminate any room containing the given location.
1829  * @param caster_ptr プレーヤーへの参照ポインタ
1830  * @param y1 指定Y座標
1831  * @param x1 指定X座標
1832  * @return なし
1833  */
1834 void lite_room(player_type *caster_ptr, POSITION y1, POSITION x1)
1835 {
1836         int i;
1837         POSITION x, y;
1838
1839         /* Add the initial grid */
1840         cave_temp_lite_room_aux(caster_ptr, y1, x1);
1841
1842         /* While grids are in the queue, add their neighbors */
1843         floor_type *floor_ptr = caster_ptr->current_floor_ptr;
1844         for (i = 0; i < tmp_pos.n; i++)
1845         {
1846                 x = tmp_pos.x[i], y = tmp_pos.y[i];
1847
1848                 /* Walls get lit, but stop light */
1849                 if (!cave_pass_lite_bold(floor_ptr, y, x)) continue;
1850
1851                 /* Spread adjacent */
1852                 cave_temp_lite_room_aux(caster_ptr, y + 1, x);
1853                 cave_temp_lite_room_aux(caster_ptr, y - 1, x);
1854                 cave_temp_lite_room_aux(caster_ptr, y, x + 1);
1855                 cave_temp_lite_room_aux(caster_ptr, y, x - 1);
1856
1857                 /* Spread diagonal */
1858                 cave_temp_lite_room_aux(caster_ptr, y + 1, x + 1);
1859                 cave_temp_lite_room_aux(caster_ptr, y - 1, x - 1);
1860                 cave_temp_lite_room_aux(caster_ptr, y - 1, x + 1);
1861                 cave_temp_lite_room_aux(caster_ptr, y + 1, x - 1);
1862         }
1863
1864         /* Now, lite them all up at once */
1865         cave_temp_room_lite(caster_ptr);
1866
1867         if (caster_ptr->special_defense & NINJA_S_STEALTH)
1868         {
1869                 if (floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW) set_superstealth(caster_ptr, FALSE);
1870         }
1871 }
1872
1873
1874 /*!
1875  * @brief 指定された部屋内を暗くする / Darken all rooms containing the given location
1876  * @param caster_ptr プレーヤーへの参照ポインタ
1877  * @param y1 指定Y座標
1878  * @param x1 指定X座標
1879  * @return なし
1880  */
1881 void unlite_room(player_type *caster_ptr, POSITION y1, POSITION x1)
1882 {
1883         int i;
1884         POSITION x, y;
1885
1886         /* Add the initial grid */
1887         cave_temp_unlite_room_aux(caster_ptr, y1, x1);
1888
1889         /* Spread, breadth first */
1890         for (i = 0; i < tmp_pos.n; i++)
1891         {
1892                 x = tmp_pos.x[i], y = tmp_pos.y[i];
1893
1894                 /* Walls get dark, but stop darkness */
1895                 if (!cave_pass_dark_bold(caster_ptr->current_floor_ptr, y, x)) continue;
1896
1897                 /* Spread adjacent */
1898                 cave_temp_unlite_room_aux(caster_ptr, y + 1, x);
1899                 cave_temp_unlite_room_aux(caster_ptr, y - 1, x);
1900                 cave_temp_unlite_room_aux(caster_ptr, y, x + 1);
1901                 cave_temp_unlite_room_aux(caster_ptr, y, x - 1);
1902
1903                 /* Spread diagonal */
1904                 cave_temp_unlite_room_aux(caster_ptr, y + 1, x + 1);
1905                 cave_temp_unlite_room_aux(caster_ptr, y - 1, x - 1);
1906                 cave_temp_unlite_room_aux(caster_ptr, y - 1, x + 1);
1907                 cave_temp_unlite_room_aux(caster_ptr, y + 1, x - 1);
1908         }
1909
1910         /* Now, darken them all at once */
1911         cave_temp_room_unlite(caster_ptr);
1912 }
1913
1914
1915 /*!
1916  * @brief スターライトの効果を発生させる
1917  * @param caster_ptr プレーヤーへの参照ポインタ
1918  * @param magic 魔法による効果であればTRUE、スターライトの杖による効果であればFALSE
1919  * @return 常にTRUE
1920  */
1921 bool starlight(player_type *caster_ptr, bool magic)
1922 {
1923         HIT_POINT num = damroll(5, 3);
1924         POSITION y = 0, x = 0;
1925         int k;
1926         int attempts;
1927
1928         if (!caster_ptr->blind && !magic)
1929         {
1930                 msg_print(_("杖の先が明るく輝いた...", "The end of the staff glows brightly..."));
1931         }
1932
1933         for (k = 0; k < num; k++)
1934         {
1935                 attempts = 1000;
1936
1937                 while (attempts--)
1938                 {
1939                         scatter(&y, &x, caster_ptr->y, caster_ptr->x, 4, PROJECT_LOS);
1940                         if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)) continue;
1941                         if (!player_bold(caster_ptr, y, x)) break;
1942                 }
1943
1944                 project(caster_ptr, 0, 0, y, x, damroll(6 + caster_ptr->lev / 8, 10), GF_LITE_WEAK,
1945                         (PROJECT_BEAM | PROJECT_THRU | PROJECT_GRID | PROJECT_KILL | PROJECT_LOS), -1);
1946         }
1947
1948         return TRUE;
1949 }
1950
1951
1952 /*!
1953  * @brief プレイヤー位置を中心にLITE_WEAK属性を通じた照明処理を行う / Hack -- call light around the player Affect all monsters in the projection radius
1954  * @param caster_ptr プレーヤーへの参照ポインタ
1955  * @param dam 威力
1956  * @param rad 効果半径
1957  * @return 作用が実際にあった場合TRUEを返す
1958  */
1959 bool lite_area(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
1960 {
1961         BIT_FLAGS flg = PROJECT_GRID | PROJECT_KILL;
1962
1963         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
1964         {
1965                 msg_print(_("ダンジョンが光を吸収した。", "The darkness of this dungeon absorb your light."));
1966                 return FALSE;
1967         }
1968
1969         if (!caster_ptr->blind)
1970         {
1971                 msg_print(_("白い光が辺りを覆った。", "You are surrounded by a white light."));
1972         }
1973
1974         /* Hook into the "project()" function */
1975         (void)project(caster_ptr, 0, rad, caster_ptr->y, caster_ptr->x, dam, GF_LITE_WEAK, flg, -1);
1976
1977         lite_room(caster_ptr, caster_ptr->y, caster_ptr->x);
1978
1979         /* Assume seen */
1980         return (TRUE);
1981 }
1982
1983
1984 /*!
1985  * @brief プレイヤー位置を中心にLITE_DARK属性を通じた消灯処理を行う / Hack -- call light around the player Affect all monsters in the projection radius
1986  * @param caster_ptr プレーヤーへの参照ポインタ
1987  * @param dam 威力
1988  * @param rad 効果半径
1989  * @return 作用が実際にあった場合TRUEを返す
1990  */
1991 bool unlite_area(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
1992 {
1993         BIT_FLAGS flg = PROJECT_GRID | PROJECT_KILL;
1994
1995         if (!caster_ptr->blind)
1996         {
1997                 msg_print(_("暗闇が辺りを覆った。", "Darkness surrounds you."));
1998         }
1999
2000         /* Hook into the "project()" function */
2001         (void)project(caster_ptr, 0, rad, caster_ptr->y, caster_ptr->x, dam, GF_DARK_WEAK, flg, -1);
2002
2003         unlite_room(caster_ptr, caster_ptr->y, caster_ptr->x);
2004
2005         /* Assume seen */
2006         return (TRUE);
2007 }
2008
2009
2010 /*!
2011  * @brief ボール系スペルの発動 / Cast a ball spell
2012  * @param caster_ptr プレーヤーへの参照ポインタ
2013  * @param typ 効果属性
2014  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2015  * @param dam 威力
2016  * @param rad 半径
2017  * @return 作用が実際にあった場合TRUEを返す
2018  * @details
2019  * <pre>
2020  * Stop if we hit a monster, act as a "ball"
2021  * Allow "target" mode to pass over monsters
2022  * Affect grids, objects, and monsters
2023  * </pre>
2024  */
2025 bool fire_ball(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad)
2026 {
2027         POSITION tx, ty;
2028
2029         BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
2030
2031         if (typ == GF_CHARM_LIVING) flg|= PROJECT_HIDE;
2032         /* Use the given direction */
2033         tx = caster_ptr->x + 99 * ddx[dir];
2034         ty = caster_ptr->y + 99 * ddy[dir];
2035
2036         /* Hack -- Use an actual "target" */
2037         if ((dir == 5) && target_okay())
2038         {
2039                 flg &= ~(PROJECT_STOP);
2040                 tx = target_col;
2041                 ty = target_row;
2042         }
2043
2044         /* Analyze the "dir" and the "target".  Hurt items on floor. */
2045         return (project(caster_ptr, 0, rad, ty, tx, dam, typ, flg, -1));
2046 }
2047
2048
2049 /*!
2050 * @brief ブレス系スペルの発動 / Cast a breath spell
2051 * @param caster_ptr プレーヤーへの参照ポインタ
2052 * @param typ 効果属性
2053 * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2054 * @param dam 威力
2055 * @param rad 半径
2056 * @return 作用が実際にあった場合TRUEを返す
2057 * @details
2058 * <pre>
2059 * Stop if we hit a monster, act as a "ball"
2060 * Allow "target" mode to pass over monsters
2061 * Affect grids, objects, and monsters
2062 * </pre>
2063 */
2064 bool fire_breath(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad)
2065 {
2066         return fire_ball(caster_ptr, typ, dir, dam, -rad);
2067 }
2068
2069
2070 /*!
2071  * @brief ロケット系スペルの発動(詳細な差は確認中) / Cast a ball spell
2072  * @param caster_ptr プレーヤーへの参照ポインタ
2073  * @param typ 効果属性
2074  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2075  * @param dam 威力
2076  * @param rad 半径
2077  * @return 作用が実際にあった場合TRUEを返す
2078  * @details
2079  * <pre>
2080  * Stop if we hit a monster, act as a "ball"
2081  * Allow "target" mode to pass over monsters
2082  * Affect grids, objects, and monsters
2083  * </pre>
2084  */
2085 bool fire_rocket(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad)
2086 {
2087         POSITION tx, ty;
2088         BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
2089
2090         /* Use the given direction */
2091         tx = caster_ptr->x + 99 * ddx[dir];
2092         ty = caster_ptr->y + 99 * ddy[dir];
2093
2094         /* Hack -- Use an actual "target" */
2095         if ((dir == 5) && target_okay())
2096         {
2097                 tx = target_col;
2098                 ty = target_row;
2099         }
2100
2101         /* Analyze the "dir" and the "target".  Hurt items on floor. */
2102         return (project(caster_ptr, 0, rad, ty, tx, dam, typ, flg, -1));
2103 }
2104
2105
2106 /*!
2107  * @brief ボール(ハイド)系スペルの発動 / Cast a ball spell
2108  * @param caster_ptr プレーヤーへの参照ポインタ
2109  * @param typ 効果属性
2110  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2111  * @param dam 威力
2112  * @param rad 半径
2113  * @return 作用が実際にあった場合TRUEを返す
2114  * @details
2115  * <pre>
2116  * Stop if we hit a monster, act as a "ball"
2117  * Allow "target" mode to pass over monsters
2118  * Affect grids, objects, and monsters
2119  * </pre>
2120  */
2121 bool fire_ball_hide(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad)
2122 {
2123         POSITION tx, ty;
2124         BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_HIDE;
2125
2126         /* Use the given direction */
2127         tx = caster_ptr->x + 99 * ddx[dir];
2128         ty = caster_ptr->y + 99 * ddy[dir];
2129
2130         /* Hack -- Use an actual "target" */
2131         if ((dir == 5) && target_okay())
2132         {
2133                 flg &= ~(PROJECT_STOP);
2134                 tx = target_col;
2135                 ty = target_row;
2136         }
2137
2138         /* Analyze the "dir" and the "target".  Hurt items on floor. */
2139         return (project(caster_ptr, 0, rad, ty, tx, dam, typ, flg, -1));
2140 }
2141
2142
2143 /*!
2144  * @brief メテオ系スペルの発動 / Cast a meteor spell
2145  * @param caster_ptr プレーヤーへの参照ポインタ
2146  * @param who スぺル詠唱者のモンスターID(0=プレイヤー)
2147  * @param typ 効果属性
2148  * @param dam 威力
2149  * @param rad 半径
2150  * @param y 中心点Y座標
2151  * @param x 中心点X座標
2152  * @return 作用が実際にあった場合TRUEを返す
2153  * @details
2154  * <pre>
2155  * Cast a meteor spell, defined as a ball spell cast by an arbitary monster, 
2156  * player, or outside source, that starts out at an arbitrary location, and 
2157  * leaving no trail from the "caster" to the target.  This function is 
2158  * especially useful for bombardments and similar. -LM-
2159  * Option to hurt the player.
2160  * </pre>
2161  */
2162 bool fire_meteor(player_type *caster_ptr, MONSTER_IDX who, EFFECT_ID typ, POSITION y, POSITION x, HIT_POINT dam, POSITION rad)
2163 {
2164         BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
2165
2166         /* Analyze the "target" and the caster. */
2167         return (project(caster_ptr, who, rad, y, x, dam, typ, flg, -1));
2168 }
2169
2170
2171 /*!
2172  * @brief ブラスト系スペルの発動 / Cast a blast spell
2173  * @param caster_ptr プレーヤーへの参照ポインタ
2174  * @param typ 効果属性
2175  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2176  * @param dd 威力ダイス数
2177  * @param ds 威力ダイス目
2178  * @param num 基本回数
2179  * @param dev 回数分散
2180  * @return 作用が実際にあった場合TRUEを返す
2181  */
2182 bool fire_blast(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, DICE_NUMBER dd, DICE_SID ds, int num, int dev)
2183 {
2184         POSITION ly, lx;
2185         int ld;
2186         POSITION ty, tx, y, x;
2187         int i;
2188
2189         BIT_FLAGS flg = PROJECT_FAST | PROJECT_THRU | PROJECT_STOP | PROJECT_KILL | PROJECT_REFLECTABLE | PROJECT_GRID;
2190
2191         /* Assume okay */
2192         bool result = TRUE;
2193
2194         /* Use the given direction */
2195         if (dir != 5)
2196         {
2197                 ly = ty = caster_ptr->y + 20 * ddy[dir];
2198                 lx = tx = caster_ptr->x + 20 * ddx[dir];
2199         }
2200
2201         /* Use an actual "target" */
2202         else /* if (dir == 5) */
2203         {
2204                 tx = target_col;
2205                 ty = target_row;
2206
2207                 lx = 20 * (tx - caster_ptr->x) + caster_ptr->x;
2208                 ly = 20 * (ty - caster_ptr->y) + caster_ptr->y;
2209         }
2210
2211         ld = distance(caster_ptr->y, caster_ptr->x, ly, lx);
2212
2213         /* Blast */
2214         for (i = 0; i < num; i++)
2215         {
2216                 while (1)
2217                 {
2218                         /* Get targets for some bolts */
2219                         y = rand_spread(ly, ld * dev / 20);
2220                         x = rand_spread(lx, ld * dev / 20);
2221
2222                         if (distance(ly, lx, y, x) <= ld * dev / 20) break;
2223                 }
2224
2225                 /* Analyze the "dir" and the "target". */
2226                 if (!project(caster_ptr, 0, 0, y, x, damroll(dd, ds), typ, flg, -1))
2227                 {
2228                         result = FALSE;
2229                 }
2230         }
2231
2232         return (result);
2233 }
2234
2235
2236 /*!
2237  * @brief モンスターとの位置交換処理 / Switch position with a monster.
2238  * @param caster_ptr プレーヤーへの参照ポインタ
2239  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2240  * @return 作用が実際にあった場合TRUEを返す
2241  */
2242 bool teleport_swap(player_type *caster_ptr, DIRECTION dir)
2243 {
2244         POSITION tx, ty;
2245         grid_type* g_ptr;
2246         monster_type* m_ptr;
2247         monster_race* r_ptr;
2248
2249         if ((dir == 5) && target_okay())
2250         {
2251                 tx = target_col;
2252                 ty = target_row;
2253         }
2254         else
2255         {
2256                 tx = caster_ptr->x + ddx[dir];
2257                 ty = caster_ptr->y + ddy[dir];
2258         }
2259         g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
2260
2261         if (caster_ptr->anti_tele)
2262         {
2263                 msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
2264                 return FALSE;
2265         }
2266
2267         if (!g_ptr->m_idx || (g_ptr->m_idx == caster_ptr->riding))
2268         {
2269                 msg_print(_("それとは場所を交換できません。", "You can't trade places with that!"));
2270                 return FALSE;
2271         }
2272
2273         if ((g_ptr->info & CAVE_ICKY) || (distance(ty, tx, caster_ptr->y, caster_ptr->x) > caster_ptr->lev * 3 / 2 + 10))
2274         {
2275                 msg_print(_("失敗した。", "Failed to swap."));
2276                 return FALSE;
2277         }
2278
2279         m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
2280         r_ptr = &r_info[m_ptr->r_idx];
2281
2282         (void)set_monster_csleep(g_ptr->m_idx, 0);
2283
2284         if (r_ptr->flagsr & RFR_RES_TELE)
2285         {
2286                 msg_print(_("テレポートを邪魔された!", "Your teleportation is blocked!"));
2287                 if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE;
2288                 return FALSE;
2289         }
2290
2291         sound(SOUND_TELEPORT);
2292
2293         /* Swap the player and monster */
2294         (void)move_player_effect(caster_ptr, ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
2295
2296         /* Success */
2297         return TRUE;
2298 }
2299
2300
2301 /*!
2302  * @brief 指定方向に飛び道具を飛ばす(フラグ任意指定) / Hack -- apply a "project()" in a direction (or at the target)
2303  * @param caster_ptr プレーヤーへの参照ポインタ
2304  * @param typ 効果属性
2305  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2306  * @param dam 威力
2307  * @param flg フラグ
2308  * @return 作用が実際にあった場合TRUEを返す
2309  */
2310 bool project_hook(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, BIT_FLAGS flg)
2311 {
2312         POSITION tx, ty;
2313
2314         /* Pass through the target if needed */
2315         flg |= (PROJECT_THRU);
2316
2317         /* Use the given direction */
2318         tx = caster_ptr->x + ddx[dir];
2319         ty = caster_ptr->y + ddy[dir];
2320
2321         /* Hack -- Use an actual "target" */
2322         if ((dir == 5) && target_okay())
2323         {
2324                 tx = target_col;
2325                 ty = target_row;
2326         }
2327
2328         /* Analyze the "dir" and the "target", do NOT explode */
2329         return (project(caster_ptr, 0, 0, ty, tx, dam, typ, flg, -1));
2330 }
2331
2332
2333 /*!
2334  * @brief ボルト系スペルの発動 / Cast a bolt spell.
2335  * @param caster_ptr プレーヤーへの参照ポインタ
2336  * @param typ 効果属性
2337  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2338  * @param dam 威力
2339  * @return 作用が実際にあった場合TRUEを返す
2340  * @details
2341  * <pre>
2342  * Stop if we hit a monster, as a "bolt".
2343  * Affect monsters and grids (not objects).
2344  * </pre>
2345  */
2346 bool fire_bolt(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam)
2347 {
2348         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL | PROJECT_GRID;
2349         if (typ != GF_ARROW) flg |= PROJECT_REFLECTABLE;
2350         return (project_hook(caster_ptr, typ, dir, dam, flg));
2351 }
2352
2353
2354 /*!
2355  * @brief ビーム系スペルの発動 / Cast a beam spell.
2356  * @param caster_ptr プレーヤーへの参照ポインタ
2357  * @param typ 効果属性
2358  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2359  * @param dam 威力
2360  * @return 作用が実際にあった場合TRUEを返す
2361  * @details
2362  * <pre>
2363  * Pass through monsters, as a "beam".
2364  * Affect monsters, grids and objects.
2365  * </pre>
2366  */
2367 bool fire_beam(player_type *caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam)
2368 {
2369         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM;
2370         return (project_hook(caster_ptr, typ, dir, dam, flg));
2371 }
2372
2373
2374 /*!
2375  * @brief 確率に応じたボルト系/ビーム系スペルの発動 / Cast a bolt spell, or rarely, a beam spell.
2376  * @param caster_ptr プレーヤーへの参照ポインタ
2377  * @param prob ビーム化する確率(%)
2378  * @param typ 効果属性
2379  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2380  * @param dam 威力
2381  * @return 作用が実際にあった場合TRUEを返す
2382  * @details
2383  * <pre>
2384  * Pass through monsters, as a "beam".
2385  * Affect monsters, grids and objects.
2386  * </pre>
2387  */
2388 bool fire_bolt_or_beam(player_type *caster_ptr, PERCENTAGE prob, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam)
2389 {
2390         if (randint0(100) < prob)
2391         {
2392                 return (fire_beam(caster_ptr, typ, dir, dam));
2393         }
2394         else
2395         {
2396                 return (fire_bolt(caster_ptr, typ, dir, dam));
2397         }
2398 }
2399
2400
2401 /*!
2402  * @brief LITE_WEAK属性による光源ビーム処理
2403  * @param caster_ptr プレーヤーへの参照ポインタ
2404  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2405  * @param dam 威力
2406  * @return 作用が実際にあった場合TRUEを返す
2407  */
2408 bool lite_line(player_type *caster_ptr, DIRECTION dir, HIT_POINT dam)
2409 {
2410         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_KILL;
2411         return (project_hook(caster_ptr, GF_LITE_WEAK, dir, dam, flg));
2412 }
2413
2414
2415 /*!
2416  * @brief 衰弱ボルト処理
2417  * @param caster_ptr プレーヤーへの参照ポインタ
2418  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2419  * @param dam 威力
2420  * @return 作用が実際にあった場合TRUEを返す
2421  */
2422 bool hypodynamic_bolt(player_type *caster_ptr, DIRECTION dir, HIT_POINT dam)
2423 {
2424         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL | PROJECT_REFLECTABLE;
2425         return (project_hook(caster_ptr, GF_HYPODYNAMIA, dir, dam, flg));
2426 }
2427
2428
2429 /*!
2430  * @brief 岩石溶解処理
2431  * @param caster_ptr プレーヤーへの参照ポインタ
2432  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2433  * @param dam 威力
2434  * @return 作用が実際にあった場合TRUEを返す
2435  */
2436 bool wall_to_mud(player_type *caster_ptr, DIRECTION dir, HIT_POINT dam)
2437 {
2438         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
2439         return (project_hook(caster_ptr, GF_KILL_WALL, dir, dam, flg));
2440 }
2441
2442
2443 /*!
2444  * @brief 魔法の施錠処理
2445  * @param caster_ptr プレーヤーへの参照ポインタ
2446  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2447  * @return 作用が実際にあった場合TRUEを返す
2448  */
2449 bool wizard_lock(player_type *caster_ptr, DIRECTION dir)
2450 {
2451         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
2452         return (project_hook(caster_ptr, GF_JAM_DOOR, dir, 20 + randint1(30), flg));
2453 }
2454
2455
2456 /*!
2457  * @brief ドア破壊処理
2458  * @param caster_ptr プレーヤーへの参照ポインタ
2459  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2460  * @return 作用が実際にあった場合TRUEを返す
2461  */
2462 bool destroy_door(player_type *caster_ptr, DIRECTION dir)
2463 {
2464         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM;
2465         return (project_hook(caster_ptr, GF_KILL_DOOR, dir, 0, flg));
2466 }
2467
2468
2469 /*!
2470  * @brief トラップ解除処理
2471  * @param caster_ptr プレーヤーへの参照ポインタ
2472  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2473  * @return 作用が実際にあった場合TRUEを返す
2474  */
2475 bool disarm_trap(player_type *caster_ptr, DIRECTION dir)
2476 {
2477         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM;
2478         return (project_hook(caster_ptr, GF_KILL_TRAP, dir, 0, flg));
2479 }
2480
2481
2482 /*!
2483  * @brief 死の光線処理
2484  * @param caster_ptr プレーヤーへの参照ポインタ
2485  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2486  * @param plev プレイヤーレベル(効力はplev*200)
2487  * @return 作用が実際にあった場合TRUEを返す
2488  */
2489 bool death_ray(player_type *caster_ptr, DIRECTION dir, PLAYER_LEVEL plev)
2490 {
2491         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL | PROJECT_REFLECTABLE;
2492         return (project_hook(caster_ptr, GF_DEATH_RAY, dir, plev * 200, flg));
2493 }
2494
2495
2496 /*!
2497  * @brief モンスター用テレポート処理
2498  * @param caster_ptr プレーヤーへの参照ポインタ
2499  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
2500  * @param distance 移動距離
2501  * @return 作用が実際にあった場合TRUEを返す
2502  */
2503 bool teleport_monster(player_type *caster_ptr, DIRECTION dir, int distance)
2504 {
2505         BIT_FLAGS flg = PROJECT_BEAM | PROJECT_KILL;
2506         return (project_hook(caster_ptr, GF_AWAY_ALL, dir, distance, flg));
2507 }
2508
2509
2510 /*!
2511  * @brief ドア生成処理(プレイヤー中心に周囲1マス) / Hooks -- affect adjacent grids (radius 1 ball attack)
2512  * @param caster_ptr プレーヤーへの参照ポインタ
2513  * @return 作用が実際にあった場合TRUEを返す
2514  */
2515 bool door_creation(player_type *caster_ptr, POSITION y, POSITION x)
2516 {
2517         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
2518         return (project(caster_ptr, 0, 1, y, x, 0, GF_MAKE_DOOR, flg, -1));
2519 }
2520
2521
2522 /*!
2523  * @brief トラップ生成処理(起点から周囲1マス)
2524  * @param caster_ptr プレーヤーへの参照ポインタ
2525  * @param y 起点Y座標
2526  * @param x 起点X座標
2527  * @return 作用が実際にあった場合TRUEを返す
2528  */
2529 bool trap_creation(player_type *caster_ptr, POSITION y, POSITION x)
2530 {
2531         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
2532         return (project(caster_ptr, 0, 1, y, x, 0, GF_MAKE_TRAP, flg, -1));
2533 }
2534
2535
2536 /*!
2537  * @brief 森林生成処理(プレイヤー中心に周囲1マス)
2538  * @param caster_ptr プレーヤーへの参照ポインタ
2539  * @return 作用が実際にあった場合TRUEを返す
2540  */
2541 bool tree_creation(player_type *caster_ptr, POSITION y, POSITION x)
2542 {
2543         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
2544         return (project(caster_ptr, 0, 1, y, x, 0, GF_MAKE_TREE, flg, -1));
2545 }
2546
2547
2548 /*!
2549  * @brief 魔法のルーン生成処理(プレイヤー中心に周囲1マス)
2550  * @param caster_ptr プレーヤーへの参照ポインタ
2551  * @return 作用が実際にあった場合TRUEを返す
2552  */
2553 bool glyph_creation(player_type *caster_ptr, POSITION y, POSITION x)
2554 {
2555         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM;
2556         return (project(caster_ptr, 0, 1, y, x, 0, GF_MAKE_GLYPH, flg, -1));
2557 }
2558
2559
2560 /*!
2561  * @brief 壁生成処理(プレイヤー中心に周囲1マス)
2562  * @param caster_ptr プレーヤーへの参照ポインタ
2563  * @return 作用が実際にあった場合TRUEを返す
2564  */
2565 bool wall_stone(player_type *caster_ptr)
2566 {
2567         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
2568         bool dummy = (project(caster_ptr, 0, 1, caster_ptr->y, caster_ptr->x, 0, GF_STONE_WALL, flg, -1));
2569         caster_ptr->update |= (PU_FLOW);
2570         caster_ptr->redraw |= (PR_MAP);
2571         return dummy;
2572 }
2573
2574
2575 /*!
2576  * @brief ドア破壊処理(プレイヤー中心に周囲1マス)
2577  * @param caster_ptr プレーヤーへの参照ポインタ
2578  * @return 作用が実際にあった場合TRUEを返す
2579  */
2580 bool destroy_doors_touch(player_type *caster_ptr)
2581 {
2582         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
2583         return (project(caster_ptr, 0, 1, caster_ptr->y, caster_ptr->x, 0, GF_KILL_DOOR, flg, -1));
2584 }
2585
2586
2587 /*!
2588  * @brief トラップ解除処理(プレイヤー中心に周囲1マス)
2589  * @param caster_ptr プレーヤーへの参照ポインタ
2590  * @return 作用が実際にあった場合TRUEを返す
2591  */
2592 bool disarm_traps_touch(player_type *caster_ptr)
2593 {
2594         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
2595         return (project(caster_ptr, 0, 1, caster_ptr->y, caster_ptr->x, 0, GF_KILL_TRAP, flg, -1));
2596 }
2597
2598
2599 /*!
2600  * @brief スリープモンスター処理(プレイヤー中心に周囲1マス)
2601  * @param caster_ptr プレーヤーへの参照ポインタ
2602  * @return 作用が実際にあった場合TRUEを返す
2603  */
2604 bool sleep_monsters_touch(player_type *caster_ptr)
2605 {
2606         BIT_FLAGS flg = PROJECT_KILL | PROJECT_HIDE;
2607         return (project(caster_ptr, 0, 1, caster_ptr->y, caster_ptr->x, caster_ptr->lev, GF_OLD_SLEEP, flg, -1));
2608 }
2609
2610
2611 /*!
2612  * @brief 死者復活処理(起点より周囲5マス)
2613  * @param caster_ptr プレーヤーへの参照ポインタ
2614  * @param who 術者モンスターID(0ならばプレイヤー)
2615  * @param y 起点Y座標
2616  * @param x 起点X座標
2617  * @return 作用が実際にあった場合TRUEを返す
2618  */
2619 bool animate_dead(player_type *caster_ptr, MONSTER_IDX who, POSITION y, POSITION x)
2620 {
2621         BIT_FLAGS flg = PROJECT_ITEM | PROJECT_HIDE;
2622         return (project(caster_ptr, who, 5, y, x, 0, GF_ANIM_DEAD, flg, -1));
2623 }
2624
2625
2626 /*!
2627  * @brief 混沌招来処理
2628  * @return 作用が実際にあった場合TRUEを返す
2629  */
2630 void call_chaos(player_type *caster_ptr)
2631 {
2632         int Chaos_type, dummy, dir;
2633         PLAYER_LEVEL plev = caster_ptr->lev;
2634         bool line_chaos = FALSE;
2635
2636         int hurt_types[31] =
2637         {
2638                 GF_ELEC,      GF_POIS,    GF_ACID,    GF_COLD,
2639                 GF_FIRE,      GF_MISSILE, GF_ARROW,   GF_PLASMA,
2640                 GF_HOLY_FIRE, GF_WATER,   GF_LITE,    GF_DARK,
2641                 GF_FORCE,     GF_INERTIAL, GF_MANA,    GF_METEOR,
2642                 GF_ICE,       GF_CHAOS,   GF_NETHER,  GF_DISENCHANT,
2643                 GF_SHARDS,    GF_SOUND,   GF_NEXUS,   GF_CONFUSION,
2644                 GF_TIME,      GF_GRAVITY, GF_ROCKET,  GF_NUKE,
2645                 GF_HELL_FIRE, GF_DISINTEGRATE, GF_PSY_SPEAR
2646         };
2647
2648         Chaos_type = hurt_types[randint0(31)];
2649         if (one_in_(4)) line_chaos = TRUE;
2650
2651         if (one_in_(6))
2652         {
2653                 for (dummy = 1; dummy < 10; dummy++)
2654                 {
2655                         if (dummy - 5)
2656                         {
2657                                 if (line_chaos)
2658                                         fire_beam(caster_ptr, Chaos_type, dummy, 150);
2659                                 else
2660                                         fire_ball(caster_ptr, Chaos_type, dummy, 150, 2);
2661                         }
2662                 }
2663         }
2664         else if (one_in_(3))
2665         {
2666                 fire_ball(caster_ptr, Chaos_type, 0, 500, 8);
2667         }
2668         else
2669         {
2670                 if (!get_aim_dir(&dir)) return;
2671                 if (line_chaos)
2672                         fire_beam(caster_ptr, Chaos_type, dir, 250);
2673                 else
2674                         fire_ball(caster_ptr, Chaos_type, dir, 250, 3 + (plev / 35));
2675         }
2676 }
2677
2678
2679 /*!
2680  * @brief TY_CURSE処理発動 / Activate the evil Topi Ylinen curse
2681  * @param target_ptr プレーヤーへの参照ポインタ
2682  * @param stop_ty 再帰処理停止フラグ
2683  * @param count 発動回数
2684  * @return 作用が実際にあった場合TRUEを返す
2685  * @details
2686  * <pre>
2687  * rr9: Stop the nasty things when a Cyberdemon is summoned
2688  * or the player gets paralyzed.
2689  * </pre>
2690  */
2691 bool activate_ty_curse(player_type *target_ptr, bool stop_ty, int *count)
2692 {
2693         BIT_FLAGS flg = (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP);
2694
2695         bool is_first_curse = TRUE;
2696         while (is_first_curse || one_in_(3) && !stop_ty)
2697         {
2698                 is_first_curse = FALSE;
2699                 switch (randint1(34))
2700                 {
2701                 case 28: case 29:
2702                         if (!(*count))
2703                         {
2704                                 msg_print(_("地面が揺れた...", "The ground trembles..."));
2705                                 earthquake(target_ptr, target_ptr->y, target_ptr->x, 5 + randint0(10), 0);
2706                                 if (!one_in_(6)) break;
2707                         }
2708                 case 30: case 31:
2709                         if (!(*count))
2710                         {
2711                                 HIT_POINT dam = damroll(10, 10);
2712                                 msg_print(_("純粋な魔力の次元への扉が開いた!", "A portal opens to a plane of raw mana!"));
2713                                 project(target_ptr, 0, 8, target_ptr->y, target_ptr->x, dam, GF_MANA, flg, -1);
2714                                 take_hit(target_ptr, DAMAGE_NOESCAPE, dam, _("純粋な魔力の解放", "released pure mana"), -1);
2715                                 if (!one_in_(6)) break;
2716                         }
2717                 case 32: case 33:
2718                         if (!(*count))
2719                         {
2720                                 msg_print(_("周囲の空間が歪んだ!", "Space warps about you!"));
2721                                 teleport_player(target_ptr, damroll(10, 10), TELEPORT_PASSIVE);
2722                                 if (randint0(13)) (*count) += activate_hi_summon(target_ptr, target_ptr->y, target_ptr->x, FALSE);
2723                                 if (!one_in_(6)) break;
2724                         }
2725                 case 34:
2726                         msg_print(_("エネルギーのうねりを感じた!", "You feel a surge of energy!"));
2727                         wall_breaker(target_ptr);
2728                         if (!randint0(7))
2729                         {
2730                                 project(target_ptr, 0, 7, target_ptr->y, target_ptr->x, 50, GF_KILL_WALL, flg, -1);
2731                                 take_hit(target_ptr, DAMAGE_NOESCAPE, 50, _("エネルギーのうねり", "surge of energy"), -1);
2732                         }
2733
2734                         if (!one_in_(6)) break;
2735                 case 1: case 2: case 3: case 16: case 17:
2736                         aggravate_monsters(target_ptr, 0);
2737                         if (!one_in_(6)) break;
2738                 case 4: case 5: case 6:
2739                         (*count) += activate_hi_summon(target_ptr, target_ptr->y, target_ptr->x, FALSE);
2740                         if (!one_in_(6)) break;
2741                 case 7: case 8: case 9: case 18:
2742                         (*count) += summon_specific(0, target_ptr->y, target_ptr->x, target_ptr->current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
2743                         if (!one_in_(6)) break;
2744                 case 10: case 11: case 12:
2745                         msg_print(_("経験値が体から吸い取られた気がする!", "You feel your experience draining away..."));
2746                         lose_exp(target_ptr, target_ptr->exp / 16);
2747                         if (!one_in_(6)) break;
2748                 case 13: case 14: case 15: case 19: case 20:
2749                         if (stop_ty || (target_ptr->free_act && (randint1(125) < target_ptr->skill_sav)) || (target_ptr->pclass == CLASS_BERSERKER))
2750                         {
2751                                 /* Do nothing */ ;
2752                         }
2753                         else
2754                         {
2755                                 msg_print(_("彫像になった気分だ!", "You feel like a statue!"));
2756                                 if (target_ptr->free_act)
2757                                         set_paralyzed(target_ptr, target_ptr->paralyzed + randint1(3));
2758                                 else
2759                                         set_paralyzed(target_ptr, target_ptr->paralyzed + randint1(13));
2760                                 stop_ty = TRUE;
2761                         }
2762
2763                         if (!one_in_(6)) break;
2764                 case 21: case 22: case 23:
2765                         (void)do_dec_stat(target_ptr, randint0(6));
2766                         if (!one_in_(6)) break;
2767                 case 24:
2768                         msg_print(_("ほえ?私は誰?ここで何してる?", "Huh? Who am I? What am I doing here?"));
2769                         lose_all_info(target_ptr);
2770                         if (!one_in_(6)) break;
2771                 case 25:
2772                         /*
2773                          * Only summon Cyberdemons deep in the dungeon.
2774                          */
2775                         if ((target_ptr->current_floor_ptr->dun_level > 65) && !stop_ty)
2776                         {
2777                                 (*count) += summon_cyber(-1, target_ptr->y, target_ptr->x);
2778                                 stop_ty = TRUE;
2779                                 break;
2780                         }
2781
2782                         if (!one_in_(6)) break;
2783                 default:
2784                         for (int i = 0; i < A_MAX; i++)
2785                         {
2786                                 bool is_first_dec_stat = TRUE;
2787                                 while (is_first_dec_stat || one_in_(2))
2788                                 {
2789                                         is_first_dec_stat = FALSE;
2790                                         (void)do_dec_stat(target_ptr, i);
2791                                 }
2792                         }
2793                 }
2794         }
2795
2796         return stop_ty;
2797 }
2798
2799
2800 /*!
2801  * todo 引数にPOSITION x/yは必要か? 要調査
2802  * @brief HI_SUMMON(上級召喚)処理発動
2803  * @param caster_ptr プレーヤーへの参照ポインタ
2804  * @param y 召喚位置Y座標
2805  * @param x 召喚位置X座標
2806  * @param can_pet プレイヤーのペットとなる可能性があるならばTRUEにする
2807  * @return 作用が実際にあった場合TRUEを返す
2808  */
2809 int activate_hi_summon(player_type *caster_ptr, POSITION y, POSITION x, bool can_pet)
2810 {
2811         int count = 0;
2812         DEPTH summon_lev;
2813         BIT_FLAGS mode = PM_ALLOW_GROUP;
2814         bool pet = FALSE;
2815
2816         if (can_pet)
2817         {
2818                 if (one_in_(4))
2819                 {
2820                         mode |= PM_FORCE_FRIENDLY;
2821                 }
2822                 else
2823                 {
2824                         mode |= PM_FORCE_PET;
2825                         pet = TRUE;
2826                 }
2827         }
2828
2829         if (!pet) mode |= PM_NO_PET;
2830
2831         summon_lev = (pet ? caster_ptr->lev * 2 / 3 + randint1(caster_ptr->lev / 2) : caster_ptr->current_floor_ptr->dun_level);
2832
2833         for (int i = 0; i < (randint1(7) + (caster_ptr->current_floor_ptr->dun_level / 40)); i++)
2834         {
2835                 switch (randint1(25) + (caster_ptr->current_floor_ptr->dun_level / 20))
2836                 {
2837                         case 1: case 2:
2838                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_ANT, mode);
2839                                 break;
2840                         case 3: case 4:
2841                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_SPIDER, mode);
2842                                 break;
2843                         case 5: case 6:
2844                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HOUND, mode);
2845                                 break;
2846                         case 7: case 8:
2847                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HYDRA, mode);
2848                                 break;
2849                         case 9: case 10:
2850                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_ANGEL, mode);
2851                                 break;
2852                         case 11: case 12:
2853                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_UNDEAD, mode);
2854                                 break;
2855                         case 13: case 14:
2856                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_DRAGON, mode);
2857                                 break;
2858                         case 15: case 16:
2859                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_DEMON, mode);
2860                                 break;
2861                         case 17:
2862                                 if (can_pet) break;
2863                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_AMBERITES, (mode | PM_ALLOW_UNIQUE));
2864                                 break;
2865                         case 18: case 19:
2866                                 if (can_pet) break;
2867                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_UNIQUE, (mode | PM_ALLOW_UNIQUE));
2868                                 break;
2869                         case 20: case 21:
2870                                 if (!can_pet) mode |= PM_ALLOW_UNIQUE;
2871                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HI_UNDEAD, mode);
2872                                 break;
2873                         case 22: case 23:
2874                                 if (!can_pet) mode |= PM_ALLOW_UNIQUE;
2875                                 count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HI_DRAGON, mode);
2876                                 break;
2877                         case 24:
2878                                 count += summon_specific((pet ? -1 : 0), y, x, 100, SUMMON_CYBER, mode);
2879                                 break;
2880                         default:
2881                                 if (!can_pet) mode |= PM_ALLOW_UNIQUE;
2882                                 count += summon_specific((pet ? -1 : 0), y, x,pet ? summon_lev : (((summon_lev * 3) / 2) + 5), 0, mode);
2883                 }
2884         }
2885
2886         return count;
2887 }
2888
2889
2890 /*!
2891  * @brief 周辺破壊効果(プレイヤー中心)
2892  * @param caster_ptr プレーヤーへの参照ポインタ
2893  * @return 作用が実際にあった場合TRUEを返す
2894  */
2895 void wall_breaker(player_type *caster_ptr)
2896 {
2897         int i;
2898         POSITION y = 0, x = 0;
2899         int attempts = 1000;
2900
2901         if (randint1(80 + caster_ptr->lev) < 70)
2902         {
2903                 while (attempts--)
2904                 {
2905                         scatter(&y, &x, caster_ptr->y, caster_ptr->x, 4, 0);
2906
2907                         if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)) continue;
2908
2909                         if (!player_bold(caster_ptr, y, x)) break;
2910                 }
2911
2912                 project(caster_ptr, 0, 0, y, x, 20 + randint1(30), GF_KILL_WALL,
2913                                   (PROJECT_BEAM | PROJECT_THRU | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL), -1);
2914         }
2915         else if (randint1(100) > 30)
2916         {
2917                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, 1, 0);
2918         }
2919         else
2920         {
2921                 int num = damroll(5, 3);
2922
2923                 for (i = 0; i < num; i++)
2924                 {
2925                         while (1)
2926                         {
2927                                 scatter(&y, &x, caster_ptr->y, caster_ptr->x, 10, 0);
2928
2929                                 if (!player_bold(caster_ptr, y, x)) break;
2930                         }
2931
2932                         project(caster_ptr, 0, 0, y, x, 20 + randint1(30), GF_KILL_WALL,
2933                                           (PROJECT_BEAM | PROJECT_THRU | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL), -1);
2934                 }
2935         }
2936 }
2937
2938
2939 /*!
2940  * @brief パニック・モンスター効果(プレイヤー視界範囲内) / Confuse monsters
2941  * @param caster_ptr プレーヤーへの参照ポインタ
2942  * @param dam 効力
2943  * @return 作用が実際にあった場合TRUEを返す
2944  */
2945 bool confuse_monsters(player_type *caster_ptr, HIT_POINT dam)
2946 {
2947         return (project_all_los(caster_ptr, GF_OLD_CONF, dam));
2948 }
2949
2950
2951 /*!
2952  * @brief チャーム・モンスター効果(プレイヤー視界範囲内) / Charm monsters
2953  * @param caster_ptr プレーヤーへの参照ポインタ
2954  * @param dam 効力
2955  * @return 作用が実際にあった場合TRUEを返す
2956  */
2957 bool charm_monsters(player_type *caster_ptr, HIT_POINT dam)
2958 {
2959         return (project_all_los(caster_ptr, GF_CHARM, dam));
2960 }
2961
2962
2963 /*!
2964  * @brief 動物魅了効果(プレイヤー視界範囲内) / Charm Animals
2965  * @param caster_ptr プレーヤーへの参照ポインタ
2966  * @param dam 効力
2967  * @return 作用が実際にあった場合TRUEを返す
2968  */
2969 bool charm_animals(player_type *caster_ptr, HIT_POINT dam)
2970 {
2971         return (project_all_los(caster_ptr, GF_CONTROL_ANIMAL, dam));
2972 }
2973
2974
2975 /*!
2976  * @brief モンスター朦朧効果(プレイヤー視界範囲内) / Stun monsters
2977  * @param caster_ptr プレーヤーへの参照ポインタ
2978  * @param dam 効力
2979  * @return 作用が実際にあった場合TRUEを返す
2980  */
2981 bool stun_monsters(player_type *caster_ptr, HIT_POINT dam)
2982 {
2983         return (project_all_los(caster_ptr, GF_STUN, dam));
2984 }
2985
2986
2987 /*!
2988  * @brief モンスター停止効果(プレイヤー視界範囲内) / Stasis monsters
2989  * @param caster_ptr プレーヤーへの参照ポインタ
2990  * @param dam 効力
2991  * @return 作用が実際にあった場合TRUEを返す
2992  */
2993 bool stasis_monsters(player_type *caster_ptr, HIT_POINT dam)
2994 {
2995         return (project_all_los(caster_ptr, GF_STASIS, dam));
2996 }
2997
2998
2999 /*!
3000  * @brief モンスター精神攻撃効果(プレイヤー視界範囲内) / Mindblast monsters
3001  * @param caster_ptr プレーヤーへの参照ポインタ
3002  * @param dam 効力
3003  * @return 作用が実際にあった場合TRUEを返す
3004  */
3005 bool mindblast_monsters(player_type *caster_ptr, HIT_POINT dam)
3006 {
3007         return (project_all_los(caster_ptr, GF_PSI, dam));
3008 }
3009
3010
3011 /*!
3012  * @brief モンスター追放効果(プレイヤー視界範囲内) / Banish all monsters
3013  * @param caster_ptr プレーヤーへの参照ポインタ
3014  * @param dist 効力(距離)
3015  * @return 作用が実際にあった場合TRUEを返す
3016  */
3017 bool banish_monsters(player_type *caster_ptr, int dist)
3018 {
3019         return (project_all_los(caster_ptr, GF_AWAY_ALL, dist));
3020 }
3021
3022
3023 /*!
3024  * @brief 邪悪退散効果(プレイヤー視界範囲内) / Turn evil
3025  * @param caster_ptr プレーヤーへの参照ポインタ
3026  * @param dam 効力
3027  * @return 作用が実際にあった場合TRUEを返す
3028  */
3029 bool turn_evil(player_type *caster_ptr, HIT_POINT dam)
3030 {
3031         return (project_all_los(caster_ptr, GF_TURN_EVIL, dam));
3032 }
3033
3034
3035 /*!
3036  * @brief 全モンスター退散効果(プレイヤー視界範囲内) / Turn everyone
3037  * @param caster_ptr プレーヤーへの参照ポインタ
3038  * @param dam 効力
3039  * @return 作用が実際にあった場合TRUEを返す
3040  */
3041 bool turn_monsters(player_type *caster_ptr, HIT_POINT dam)
3042 {
3043         return (project_all_los(caster_ptr, GF_TURN_ALL, dam));
3044 }
3045
3046
3047 /*!
3048  * @brief 死の光線(プレイヤー視界範囲内) / Death-ray all monsters (note: OBSCENELY powerful)
3049  * @param caster_ptr プレーヤーへの参照ポインタ
3050  * @return 作用が実際にあった場合TRUEを返す
3051  */
3052 bool deathray_monsters(player_type *caster_ptr)
3053 {
3054         return (project_all_los(caster_ptr, GF_DEATH_RAY, caster_ptr->lev * 200));
3055 }
3056
3057
3058 /*!
3059  * @brief チャーム・モンスター(1体)
3060  * @param caster_ptr プレーヤーへの参照ポインタ
3061  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
3062  * @param plev パワー
3063  * @return 作用が実際にあった場合TRUEを返す
3064  */
3065 bool charm_monster(player_type *caster_ptr, DIRECTION dir, PLAYER_LEVEL plev)
3066 {
3067         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL;
3068         return (project_hook(caster_ptr, GF_CHARM, dir, plev, flg));
3069 }
3070
3071
3072 /*!
3073  * @brief アンデッド支配(1体)
3074  * @param caster_ptr プレーヤーへの参照ポインタ
3075  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
3076  * @param plev パワー
3077  * @return 作用が実際にあった場合TRUEを返す
3078  */
3079 bool control_one_undead(player_type *caster_ptr, DIRECTION dir, PLAYER_LEVEL plev)
3080 {
3081         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL;
3082         return (project_hook(caster_ptr, GF_CONTROL_UNDEAD, dir, plev, flg));
3083 }
3084
3085
3086 /*!
3087  * @brief 悪魔支配(1体)
3088  * @param caster_ptr プレーヤーへの参照ポインタ
3089  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
3090  * @param plev パワー
3091  * @return 作用が実際にあった場合TRUEを返す
3092  */
3093 bool control_one_demon(player_type *caster_ptr, DIRECTION dir, PLAYER_LEVEL plev)
3094 {
3095         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL;
3096         return (project_hook(caster_ptr, GF_CONTROL_DEMON, dir, plev, flg));
3097 }
3098
3099
3100 /*!
3101  * @brief 動物支配(1体)
3102  * @param caster_ptr プレーヤーへの参照ポインタ
3103  * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
3104  * @param plev パワー
3105  * @return 作用が実際にあった場合TRUEを返す
3106  */
3107 bool charm_animal(player_type *caster_ptr, DIRECTION dir, PLAYER_LEVEL plev)
3108 {
3109         BIT_FLAGS flg = PROJECT_STOP | PROJECT_KILL;
3110         return (project_hook(caster_ptr, GF_CONTROL_ANIMAL, dir, plev, flg));
3111 }
3112
3113
3114 /*!
3115  * @brief 変わり身処理
3116  * @param caster_ptr プレーヤーへの参照ポインタ
3117  * @param success 判定成功上の処理ならばTRUE
3118  * @return 作用が実際にあった場合TRUEを返す
3119  */
3120 bool kawarimi(player_type *caster_ptr, bool success)
3121 {
3122         object_type forge;
3123         object_type *q_ptr = &forge;
3124         POSITION y, x;
3125
3126         if (caster_ptr->is_dead) return FALSE;
3127         if (caster_ptr->confused || caster_ptr->blind || caster_ptr->paralyzed || caster_ptr->image) return FALSE;
3128         if (randint0(200) < caster_ptr->stun) return FALSE;
3129
3130         if (!success && one_in_(3))
3131         {
3132                 msg_print(_("失敗!逃げられなかった。", "Failed! You couldn't run away."));
3133                 caster_ptr->special_defense &= ~(NINJA_KAWARIMI);
3134                 caster_ptr->redraw |= (PR_STATUS);
3135                 return FALSE;
3136         }
3137
3138         y = caster_ptr->y;
3139         x = caster_ptr->x;
3140
3141         teleport_player(caster_ptr, 10 + randint1(90), 0L);
3142         object_wipe(q_ptr);
3143         object_prep(q_ptr, lookup_kind(TV_STATUE, SV_WOODEN_STATUE));
3144
3145         q_ptr->pval = MON_NINJA;
3146         (void)drop_near(q_ptr, -1, y, x);
3147
3148         if (success) msg_print(_("攻撃を受ける前に素早く身をひるがえした。", "You have turned around just before the attack hit you."));
3149         else msg_print(_("失敗!攻撃を受けてしまった。", "Failed! You are hit by the attack."));
3150
3151         caster_ptr->special_defense &= ~(NINJA_KAWARIMI);
3152         caster_ptr->redraw |= (PR_STATUS);
3153
3154         /* Teleported */
3155         return TRUE;
3156 }
3157
3158
3159 /*!
3160  * @brief 入身処理 / "Rush Attack" routine for Samurai or Ninja
3161  * @param caster_ptr プレーヤーへの参照ポインタ
3162  * @param mdeath 目標モンスターが死亡したかを返す
3163  * @return 作用が実際にあった場合TRUEを返す /  Return value is for checking "done"
3164  */
3165 bool rush_attack(player_type *attacker_ptr, bool *mdeath)
3166 {
3167         DIRECTION dir;
3168         int tx, ty;
3169         int tm_idx = 0;
3170         u16b path_g[32];
3171         int path_n, i;
3172         bool tmp_mdeath = FALSE;
3173         bool moved = FALSE;
3174
3175         if (mdeath) *mdeath = FALSE;
3176
3177         project_length = 5;
3178         if (!get_aim_dir(&dir)) return FALSE;
3179
3180         /* Use the given direction */
3181         tx = attacker_ptr->x + project_length * ddx[dir];
3182         ty = attacker_ptr->y + project_length * ddy[dir];
3183
3184         /* Hack -- Use an actual "target" */
3185         if ((dir == 5) && target_okay())
3186         {
3187                 tx = target_col;
3188                 ty = target_row;
3189         }
3190
3191         if (in_bounds(attacker_ptr->current_floor_ptr, ty, tx)) tm_idx = attacker_ptr->current_floor_ptr->grid_array[ty][tx].m_idx;
3192
3193         path_n = project_path(attacker_ptr->current_floor_ptr, path_g, project_length, attacker_ptr->y, attacker_ptr->x, ty, tx, PROJECT_STOP | PROJECT_KILL);
3194         project_length = 0;
3195
3196         /* No need to move */
3197         if (!path_n) return TRUE;
3198
3199         /* Use ty and tx as to-move point */
3200         ty = attacker_ptr->y;
3201         tx = attacker_ptr->x;
3202
3203         /* Project along the path */
3204         for (i = 0; i < path_n; i++)
3205         {
3206                 monster_type *m_ptr;
3207
3208                 int ny = GRID_Y(path_g[i]);
3209                 int nx = GRID_X(path_g[i]);
3210
3211                 if (cave_empty_bold(attacker_ptr->current_floor_ptr, ny, nx) && player_can_enter(attacker_ptr, attacker_ptr->current_floor_ptr->grid_array[ny][nx].feat, 0))
3212                 {
3213                         ty = ny;
3214                         tx = nx;
3215
3216                         /* Go to next grid */
3217                         continue;
3218                 }
3219
3220                 if (!attacker_ptr->current_floor_ptr->grid_array[ny][nx].m_idx)
3221                 {
3222                         if (tm_idx)
3223                         {
3224                                 msg_print(_("失敗!", "Failed!"));
3225                         }
3226                         else
3227                         {
3228                                 msg_print(_("ここには入身では入れない。", "You can't move to that place."));
3229                         }
3230
3231                         /* Exit loop */
3232                         break;
3233                 }
3234
3235                 /* Move player before updating the monster */
3236                 if (!player_bold(attacker_ptr, ty, tx)) teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
3237                 update_monster(attacker_ptr, attacker_ptr->current_floor_ptr->grid_array[ny][nx].m_idx, TRUE);
3238
3239                 /* Found a monster */
3240                 m_ptr = &attacker_ptr->current_floor_ptr->m_list[attacker_ptr->current_floor_ptr->grid_array[ny][nx].m_idx];
3241
3242                 if (tm_idx != attacker_ptr->current_floor_ptr->grid_array[ny][nx].m_idx)
3243                 {
3244 #ifdef JP
3245                         msg_format("%s%sが立ちふさがっている!", tm_idx ? "別の" : "", m_ptr->ml ? "モンスター" : "何か");
3246 #else
3247                         msg_format("There is %s in the way!", m_ptr->ml ? (tm_idx ? "another monster" : "a monster") : "someone");
3248 #endif
3249                 }
3250                 else if (!player_bold(attacker_ptr, ty, tx))
3251                 {
3252                         /* Hold the monster name */
3253                         GAME_TEXT m_name[MAX_NLEN];
3254
3255                         /* Get the monster name (BEFORE polymorphing) */
3256                         monster_desc(m_name, m_ptr, 0);
3257                         msg_format(_("素早く%sの懐に入り込んだ!", "You quickly jump in and attack %s!"), m_name);
3258                 }
3259
3260                 if (!player_bold(attacker_ptr, ty, tx)) teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
3261                 moved = TRUE;
3262                 tmp_mdeath = py_attack(attacker_ptr, ny, nx, HISSATSU_NYUSIN);
3263
3264                 break;
3265         }
3266
3267         if (!moved && !player_bold(attacker_ptr, ty, tx)) teleport_player_to(attacker_ptr, ty, tx, TELEPORT_NONMAGICAL);
3268
3269         if (mdeath) *mdeath = tmp_mdeath;
3270         return TRUE;
3271 }
3272
3273
3274 /*!
3275  * @brief 全鏡の消去 / Remove all mirrors in this floor
3276  * @param caster_ptr プレーヤーへの参照ポインタ
3277  * @param explode 爆発処理を伴うならばTRUE
3278  * @return なし
3279  */
3280 void remove_all_mirrors(player_type *caster_ptr, bool explode)
3281 {
3282         POSITION x, y;
3283
3284         for (x = 0; x < caster_ptr->current_floor_ptr->width; x++)
3285         {
3286                 for (y = 0; y < caster_ptr->current_floor_ptr->height; y++)
3287                 {
3288                         if (is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[y][x]))
3289                         {
3290                                 remove_mirror(caster_ptr, y, x);
3291                                 if (explode)
3292                                         project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS,
3293                                                 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1);
3294                         }
3295                 }
3296         }
3297 }
3298
3299
3300 /*!
3301  * @brief 『一つの指輪』の効果処理 /
3302  * Hack -- activate the ring of power
3303  * @param caster_ptr プレーヤーへの参照ポインタ
3304  * @param dir 発動の方向ID
3305  * @return なし
3306  */
3307 void ring_of_power(player_type *caster_ptr, DIRECTION dir)
3308 {
3309         /* Pick a random effect */
3310         switch (randint1(10))
3311         {
3312         case 1:
3313         case 2:
3314         {
3315                 msg_print(_("あなたは悪性のオーラに包み込まれた。", "You are surrounded by a malignant aura."));
3316                 sound(SOUND_EVIL);
3317
3318                 /* Decrease all stats (permanently) */
3319                 (void)dec_stat(caster_ptr, A_STR, 50, TRUE);
3320                 (void)dec_stat(caster_ptr, A_INT, 50, TRUE);
3321                 (void)dec_stat(caster_ptr, A_WIS, 50, TRUE);
3322                 (void)dec_stat(caster_ptr, A_DEX, 50, TRUE);
3323                 (void)dec_stat(caster_ptr, A_CON, 50, TRUE);
3324                 (void)dec_stat(caster_ptr, A_CHR, 50, TRUE);
3325
3326                 /* Lose some experience (permanently) */
3327                 caster_ptr->exp -= (caster_ptr->exp / 4);
3328                 caster_ptr->max_exp -= (caster_ptr->exp / 4);
3329                 check_experience(caster_ptr);
3330
3331                 break;
3332         }
3333
3334         case 3:
3335         {
3336                 msg_print(_("あなたは強力なオーラに包み込まれた。", "You are surrounded by a powerful aura."));
3337                 dispel_monsters(caster_ptr, 1000);
3338                 break;
3339         }
3340
3341         case 4:
3342         case 5:
3343         case 6:
3344         {
3345                 fire_ball(caster_ptr, GF_MANA, dir, 600, 3);
3346                 break;
3347         }
3348
3349         case 7:
3350         case 8:
3351         case 9:
3352         case 10:
3353         {
3354                 fire_bolt(caster_ptr, GF_MANA, dir, 500);
3355                 break;
3356         }
3357         }
3358 }
3359
3360
3361 /*!
3362 * @brief 運命の輪、並びにカオス的な効果の発動
3363 * @param caster_ptr プレーヤーへの参照ポインタ
3364 * @param spell ランダムな効果を選択するための基準ID
3365 * @return なし
3366 */
3367 void wild_magic(player_type *caster_ptr, int spell)
3368 {
3369         int counter = 0;
3370         int type = SUMMON_MOLD + randint0(6);
3371
3372         if (type < SUMMON_MOLD) type = SUMMON_MOLD;
3373         else if (type > SUMMON_MIMIC) type = SUMMON_MIMIC;
3374
3375         switch (randint1(spell) + randint1(8) + 1)
3376         {
3377         case 1:
3378         case 2:
3379         case 3:
3380                 teleport_player(caster_ptr, 10, TELEPORT_PASSIVE);
3381                 break;
3382         case 4:
3383         case 5:
3384         case 6:
3385                 teleport_player(caster_ptr, 100, TELEPORT_PASSIVE);
3386                 break;
3387         case 7:
3388         case 8:
3389                 teleport_player(caster_ptr, 200, TELEPORT_PASSIVE);
3390                 break;
3391         case 9:
3392         case 10:
3393         case 11:
3394                 unlite_area(caster_ptr, 10, 3);
3395                 break;
3396         case 12:
3397         case 13:
3398         case 14:
3399                 lite_area(caster_ptr, damroll(2, 3), 2);
3400                 break;
3401         case 15:
3402                 destroy_doors_touch(caster_ptr);
3403                 break;
3404         case 16: case 17:
3405                 wall_breaker(caster_ptr);
3406         case 18:
3407                 sleep_monsters_touch(caster_ptr);
3408                 break;
3409         case 19:
3410         case 20:
3411                 trap_creation(caster_ptr, caster_ptr->y, caster_ptr->x);
3412                 break;
3413         case 21:
3414         case 22:
3415                 door_creation(caster_ptr, caster_ptr->y, caster_ptr->x);
3416                 break;
3417         case 23:
3418         case 24:
3419         case 25:
3420                 aggravate_monsters(caster_ptr, 0);
3421                 break;
3422         case 26:
3423                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, 5, 0);
3424                 break;
3425         case 27:
3426         case 28:
3427                 (void)gain_mutation(caster_ptr, 0);
3428                 break;
3429         case 29:
3430         case 30:
3431                 apply_disenchant(caster_ptr, 1);
3432                 break;
3433         case 31:
3434                 lose_all_info(caster_ptr);
3435                 break;
3436         case 32:
3437                 fire_ball(caster_ptr, GF_CHAOS, 0, spell + 5, 1 + (spell / 10));
3438                 break;
3439         case 33:
3440                 wall_stone(caster_ptr);
3441                 break;
3442         case 34:
3443         case 35:
3444                 while (counter++ < 8)
3445                 {
3446                         (void)summon_specific(0, caster_ptr->y, caster_ptr->x, (caster_ptr->current_floor_ptr->dun_level * 3) / 2, type, (PM_ALLOW_GROUP | PM_NO_PET));
3447                 }
3448                 break;
3449         case 36:
3450         case 37:
3451                 activate_hi_summon(caster_ptr, caster_ptr->y, caster_ptr->x, FALSE);
3452                 break;
3453         case 38:
3454                 (void)summon_cyber(-1, caster_ptr->y, caster_ptr->x);
3455                 break;
3456         default:
3457         {
3458                 int count = 0;
3459                 (void)activate_ty_curse(caster_ptr, FALSE, &count);
3460                 break;
3461         }
3462         }
3463 }
3464
3465
3466 /*!
3467 * @brief カオス魔法「流星群」の処理としてプレイヤーを中心に隕石落下処理を10+1d10回繰り返す。
3468 * / Drop 10+1d10 meteor ball at random places near the player
3469 * @param caster_ptr プレーヤーへの参照ポインタ
3470 * @param dam ダメージ
3471 * @param rad 効力の半径
3472 * @return なし
3473 */
3474 void cast_meteor(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
3475 {
3476         int i;
3477         int b = 10 + randint1(10);
3478
3479         for (i = 0; i < b; i++)
3480         {
3481                 POSITION y = 0, x = 0;
3482                 int count;
3483
3484                 for (count = 0; count <= 20; count++)
3485                 {
3486                         int dy, dx, d;
3487
3488                         x = caster_ptr->x - 8 + randint0(17);
3489                         y = caster_ptr->y - 8 + randint0(17);
3490
3491                         dx = (caster_ptr->x > x) ? (caster_ptr->x - x) : (x - caster_ptr->x);
3492                         dy = (caster_ptr->y > y) ? (caster_ptr->y - y) : (y - caster_ptr->y);
3493
3494                         /* Approximate distance */
3495                         d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
3496
3497                         if (d >= 9) continue;
3498
3499                         if (!in_bounds(caster_ptr->current_floor_ptr, y, x) || !projectable(caster_ptr->current_floor_ptr, caster_ptr->y, caster_ptr->x, y, x)
3500                                 || !cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)) continue;
3501
3502                         /* Valid position */
3503                         break;
3504                 }
3505
3506                 if (count > 20) continue;
3507
3508                 project(caster_ptr, 0, rad, y, x, dam, GF_METEOR, PROJECT_KILL | PROJECT_JUMP | PROJECT_ITEM, -1);
3509         }
3510 }
3511
3512
3513 /*!
3514 * @brief 破邪魔法「神の怒り」の処理としてターゲットを指定した後分解のボールを最大20回発生させる。
3515 * @param caster_ptr プレーヤーへの参照ポインタ
3516 * @param dam ダメージ
3517 * @param rad 効力の半径
3518 * @return ターゲットを指定し、実行したならばTRUEを返す。
3519 */
3520 bool cast_wrath_of_the_god(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
3521 {
3522         POSITION x, y, tx, ty;
3523         POSITION nx, ny;
3524         DIRECTION dir;
3525         int i;
3526         int b = 10 + randint1(10);
3527
3528         if (!get_aim_dir(&dir)) return FALSE;
3529
3530         /* Use the given direction */
3531         tx = caster_ptr->x + 99 * ddx[dir];
3532         ty = caster_ptr->y + 99 * ddy[dir];
3533
3534         /* Hack -- Use an actual "target" */
3535         if ((dir == 5) && target_okay())
3536         {
3537                 tx = target_col;
3538                 ty = target_row;
3539         }
3540
3541         x = caster_ptr->x;
3542         y = caster_ptr->y;
3543
3544         while (1)
3545         {
3546                 /* Hack -- Stop at the target */
3547                 if ((y == ty) && (x == tx)) break;
3548
3549                 ny = y;
3550                 nx = x;
3551                 mmove2(&ny, &nx, caster_ptr->y, caster_ptr->x, ty, tx);
3552
3553                 /* Stop at maximum range */
3554                 if (MAX_RANGE <= distance(caster_ptr->y, caster_ptr->x, ny, nx)) break;
3555
3556                 /* Stopped by walls/doors */
3557                 if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, ny, nx, FF_PROJECT)) break;
3558
3559                 /* Stopped by monsters */
3560                 if ((dir != 5) && caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx != 0) break;
3561
3562                 /* Save the new location */
3563                 x = nx;
3564                 y = ny;
3565         }
3566
3567         tx = x;
3568         ty = y;
3569
3570         for (i = 0; i < b; i++)
3571         {
3572                 int count = 20, d = 0;
3573
3574                 while (count--)
3575                 {
3576                         int dx, dy;
3577
3578                         x = tx - 5 + randint0(11);
3579                         y = ty - 5 + randint0(11);
3580
3581                         dx = (tx > x) ? (tx - x) : (x - tx);
3582                         dy = (ty > y) ? (ty - y) : (y - ty);
3583
3584                         /* Approximate distance */
3585                         d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
3586                         /* Within the radius */
3587                         if (d < 5) break;
3588                 }
3589
3590                 if (count < 0) continue;
3591
3592                 /* Cannot penetrate perm walls */
3593                 if (!in_bounds(caster_ptr->current_floor_ptr, y, x) ||
3594                         cave_stop_disintegration(caster_ptr->current_floor_ptr, y, x) ||
3595                         !in_disintegration_range(caster_ptr->current_floor_ptr, ty, tx, y, x))
3596                         continue;
3597
3598                 project(caster_ptr, 0, rad, y, x, dam, GF_DISINTEGRATE, PROJECT_JUMP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL, -1);
3599         }
3600
3601         return TRUE;
3602 }
3603
3604 /*!
3605 * @brief 「ワンダー」のランダムな効果を決定して処理する。
3606 * @param caster_ptr プレーヤーへの参照ポインタ
3607 * @param dir 方向ID
3608 * @return なし
3609 * @details
3610 * This spell should become more useful (more controlled) as the\n
3611 * player gains experience levels.  Thus, add 1/5 of the player's\n
3612 * level to the die roll.  This eliminates the worst effects later on,\n
3613 * while keeping the results quite random.  It also allows some potent\n
3614 * effects only at high level.
3615 */
3616 void cast_wonder(player_type *caster_ptr, DIRECTION dir)
3617 {
3618         PLAYER_LEVEL plev = caster_ptr->lev;
3619         int die = randint1(100) + plev / 5;
3620         int vir = virtue_number(caster_ptr, V_CHANCE);
3621
3622         if (vir)
3623         {
3624                 if (caster_ptr->virtues[vir - 1] > 0)
3625                 {
3626                         while (randint1(400) < caster_ptr->virtues[vir - 1]) die++;
3627                 }
3628                 else
3629                 {
3630                         while (randint1(400) < (0 - caster_ptr->virtues[vir - 1])) die--;
3631                 }
3632         }
3633
3634         if (die < 26)
3635                 chg_virtue(caster_ptr, V_CHANCE, 1);
3636
3637         if (die > 100)
3638         {
3639                 msg_print(_("あなたは力がみなぎるのを感じた!", "You feel a surge of power!"));
3640         }
3641
3642         if (die < 8) clone_monster(dir);
3643         else if (die < 14) speed_monster(dir, plev);
3644         else if (die < 26) heal_monster(dir, damroll(4, 6));
3645         else if (die < 31) poly_monster(dir, plev);
3646         else if (die < 36)
3647                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_MISSILE, dir,
3648                         damroll(3 + ((plev - 1) / 5), 4));
3649         else if (die < 41) confuse_monster(dir, plev);
3650         else if (die < 46) fire_ball(caster_ptr, GF_POIS, dir, 20 + (plev / 2), 3);
3651         else if (die < 51) (void)lite_line(caster_ptr, dir, damroll(6, 8));
3652         else if (die < 56)
3653                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_ELEC, dir,
3654                         damroll(3 + ((plev - 5) / 4), 8));
3655         else if (die < 61)
3656                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_COLD, dir,
3657                         damroll(5 + ((plev - 5) / 4), 8));
3658         else if (die < 66)
3659                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr), GF_ACID, dir,
3660                         damroll(6 + ((plev - 5) / 4), 8));
3661         else if (die < 71)
3662                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr), GF_FIRE, dir,
3663                         damroll(8 + ((plev - 5) / 4), 8));
3664         else if (die < 76) hypodynamic_bolt(caster_ptr, dir, 75);
3665         else if (die < 81) fire_ball(caster_ptr, GF_ELEC, dir, 30 + plev / 2, 2);
3666         else if (die < 86) fire_ball(caster_ptr, GF_ACID, dir, 40 + plev, 2);
3667         else if (die < 91) fire_ball(caster_ptr, GF_ICE, dir, 70 + plev, 3);
3668         else if (die < 96) fire_ball(caster_ptr, GF_FIRE, dir, 80 + plev, 3);
3669         else if (die < 101) hypodynamic_bolt(caster_ptr, dir, 100 + plev);
3670         else if (die < 104)
3671         {
3672                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, 12, 0);
3673         }
3674         else if (die < 106)
3675         {
3676                 (void)destroy_area(caster_ptr->current_floor_ptr, caster_ptr->y, caster_ptr->x, 13 + randint0(5), FALSE);
3677         }
3678         else if (die < 108)
3679         {
3680                 symbol_genocide(caster_ptr, plev + 50, TRUE);
3681         }
3682         else if (die < 110)
3683         {
3684                 dispel_monsters(caster_ptr, 120);
3685         }
3686         else /* RARE */
3687         {
3688                 dispel_monsters(caster_ptr, 150);
3689                 slow_monsters(caster_ptr, plev);
3690                 sleep_monsters(caster_ptr, plev);
3691                 hp_player(caster_ptr, 300);
3692         }
3693 }
3694
3695
3696 /*!
3697 * @brief 「悪霊召喚」のランダムな効果を決定して処理する。
3698 * @param caster_ptr プレーヤーへの参照ポインタ
3699 * @param dir 方向ID
3700 * @return なし
3701 */
3702 void cast_invoke_spirits(player_type *caster_ptr, DIRECTION dir)
3703 {
3704         PLAYER_LEVEL plev = caster_ptr->lev;
3705         int die = randint1(100) + plev / 5;
3706         int vir = virtue_number(caster_ptr, V_CHANCE);
3707
3708         if (vir)
3709         {
3710                 if (caster_ptr->virtues[vir - 1] > 0)
3711                 {
3712                         while (randint1(400) < caster_ptr->virtues[vir - 1]) die++;
3713                 }
3714                 else
3715                 {
3716                         while (randint1(400) < (0 - caster_ptr->virtues[vir - 1])) die--;
3717                 }
3718         }
3719
3720         msg_print(_("あなたは死者たちの力を招集した...", "You call on the power of the dead..."));
3721         if (die < 26)
3722                 chg_virtue(caster_ptr, V_CHANCE, 1);
3723
3724         if (die > 100)
3725         {
3726                 msg_print(_("あなたはおどろおどろしい力のうねりを感じた!", "You feel a surge of eldritch force!"));
3727         }
3728
3729         if (die < 8)
3730         {
3731                 msg_print(_("なんてこった!あなたの周りの地面から朽ちた人影が立ち上がってきた!",
3732                         "Oh no! Mouldering forms rise from the earth around you!"));
3733
3734                 (void)summon_specific(0, caster_ptr->y, caster_ptr->x, caster_ptr->current_floor_ptr->dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
3735                 chg_virtue(caster_ptr, V_UNLIFE, 1);
3736         }
3737         else if (die < 14)
3738         {
3739                 msg_print(_("名状し難い邪悪な存在があなたの心を通り過ぎて行った...", "An unnamable evil brushes against your mind..."));
3740
3741                 set_afraid(caster_ptr, caster_ptr->afraid + randint1(4) + 4);
3742         }
3743         else if (die < 26)
3744         {
3745                 msg_print(_("あなたの頭に大量の幽霊たちの騒々しい声が押し寄せてきた...",
3746                         "Your head is invaded by a horde of gibbering spectral voices..."));
3747
3748                 set_confused(caster_ptr, caster_ptr->confused + randint1(4) + 4);
3749         }
3750         else if (die < 31)
3751         {
3752                 poly_monster(dir, plev);
3753         }
3754         else if (die < 36)
3755         {
3756                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_MISSILE, dir,
3757                         damroll(3 + ((plev - 1) / 5), 4));
3758         }
3759         else if (die < 41)
3760         {
3761                 confuse_monster(dir, plev);
3762         }
3763         else if (die < 46)
3764         {
3765                 fire_ball(caster_ptr, GF_POIS, dir, 20 + (plev / 2), 3);
3766         }
3767         else if (die < 51)
3768         {
3769                 (void)lite_line(caster_ptr, dir, damroll(6, 8));
3770         }
3771         else if (die < 56)
3772         {
3773                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_ELEC, dir,
3774                         damroll(3 + ((plev - 5) / 4), 8));
3775         }
3776         else if (die < 61)
3777         {
3778                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_COLD, dir,
3779                         damroll(5 + ((plev - 5) / 4), 8));
3780         }
3781         else if (die < 66)
3782         {
3783                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr), GF_ACID, dir,
3784                         damroll(6 + ((plev - 5) / 4), 8));
3785         }
3786         else if (die < 71)
3787         {
3788                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr), GF_FIRE, dir,
3789                         damroll(8 + ((plev - 5) / 4), 8));
3790         }
3791         else if (die < 76)
3792         {
3793                 hypodynamic_bolt(caster_ptr, dir, 75);
3794         }
3795         else if (die < 81)
3796         {
3797                 fire_ball(caster_ptr, GF_ELEC, dir, 30 + plev / 2, 2);
3798         }
3799         else if (die < 86)
3800         {
3801                 fire_ball(caster_ptr, GF_ACID, dir, 40 + plev, 2);
3802         }
3803         else if (die < 91)
3804         {
3805                 fire_ball(caster_ptr, GF_ICE, dir, 70 + plev, 3);
3806         }
3807         else if (die < 96)
3808         {
3809                 fire_ball(caster_ptr, GF_FIRE, dir, 80 + plev, 3);
3810         }
3811         else if (die < 101)
3812         {
3813                 hypodynamic_bolt(caster_ptr, dir, 100 + plev);
3814         }
3815         else if (die < 104)
3816         {
3817                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, 12, 0);
3818         }
3819         else if (die < 106)
3820         {
3821                 (void)destroy_area(caster_ptr->current_floor_ptr, caster_ptr->y, caster_ptr->x, 13 + randint0(5), FALSE);
3822         }
3823         else if (die < 108)
3824         {
3825                 symbol_genocide(caster_ptr, plev + 50, TRUE);
3826         }
3827         else if (die < 110)
3828         {
3829                 dispel_monsters(caster_ptr, 120);
3830         }
3831         else
3832         { /* RARE */
3833                 dispel_monsters(caster_ptr, 150);
3834                 slow_monsters(caster_ptr, plev);
3835                 sleep_monsters(caster_ptr, plev);
3836                 hp_player(caster_ptr, 300);
3837         }
3838
3839         if (die < 31)
3840         {
3841                 msg_print(_("陰欝な声がクスクス笑う。「もうすぐおまえは我々の仲間になるだろう。弱き者よ。」",
3842                         "Sepulchral voices chuckle. 'Soon you will join us, mortal.'"));
3843         }
3844 }
3845
3846 /*!
3847 * @brief トランプ領域の「シャッフル」の効果をランダムに決めて処理する。
3848 * @param caster_ptr プレーヤーへの参照ポインタ
3849 * @return なし
3850 */
3851 void cast_shuffle(player_type *caster_ptr)
3852 {
3853         PLAYER_LEVEL plev = caster_ptr->lev;
3854         DIRECTION dir;
3855         int die;
3856         int vir = virtue_number(caster_ptr, V_CHANCE);
3857         int i;
3858
3859         /* Card sharks and high mages get a level bonus */
3860         if ((caster_ptr->pclass == CLASS_ROGUE) ||
3861                 (caster_ptr->pclass == CLASS_HIGH_MAGE) ||
3862                 (caster_ptr->pclass == CLASS_SORCERER))
3863                 die = (randint1(110)) + plev / 5;
3864         else
3865                 die = randint1(120);
3866         
3867         if (vir)
3868         {
3869                 if (caster_ptr->virtues[vir - 1] > 0)
3870                 {
3871                         while (randint1(400) < caster_ptr->virtues[vir - 1]) die++;
3872                 }
3873                 else
3874                 {
3875                         while (randint1(400) < (0 - caster_ptr->virtues[vir - 1])) die--;
3876                 }
3877         }
3878
3879         msg_print(_("あなたはカードを切って一枚引いた...", "You shuffle the deck and draw a card..."));
3880
3881         if (die < 30)
3882                 chg_virtue(caster_ptr, V_CHANCE, 1);
3883
3884         if (die < 7)
3885         {
3886                 msg_print(_("なんてこった!《死》だ!", "Oh no! It's Death!"));
3887
3888                 for (i = 0; i < randint1(3); i++)
3889                         activate_hi_summon(caster_ptr, caster_ptr->y, caster_ptr->x, FALSE);
3890         }
3891         else if (die < 14)
3892         {
3893                 msg_print(_("なんてこった!《悪魔》だ!", "Oh no! It's the Devil!"));
3894                 summon_specific(0, caster_ptr->y, caster_ptr->x, caster_ptr->current_floor_ptr->dun_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
3895         }
3896         else if (die < 18)
3897         {
3898                 int count = 0;
3899                 msg_print(_("なんてこった!《吊られた男》だ!", "Oh no! It's the Hanged Man."));
3900                 activate_ty_curse(caster_ptr, FALSE, &count);
3901         }
3902         else if (die < 22)
3903         {
3904                 msg_print(_("《不調和の剣》だ。", "It's the swords of discord."));
3905                 aggravate_monsters(caster_ptr, 0);
3906         }
3907         else if (die < 26)
3908         {
3909                 msg_print(_("《愚者》だ。", "It's the Fool."));
3910                 do_dec_stat(caster_ptr, A_INT);
3911                 do_dec_stat(caster_ptr, A_WIS);
3912         }
3913         else if (die < 30)
3914         {
3915                 msg_print(_("奇妙なモンスターの絵だ。", "It's the picture of a strange monster."));
3916                 trump_summoning(caster_ptr, 1, FALSE, caster_ptr->y, caster_ptr->x, (caster_ptr->current_floor_ptr->dun_level * 3 / 2), (32 + randint1(6)), PM_ALLOW_GROUP | PM_ALLOW_UNIQUE);
3917         }
3918         else if (die < 33)
3919         {
3920                 msg_print(_("《月》だ。", "It's the Moon."));
3921                 unlite_area(caster_ptr, 10, 3);
3922         }
3923         else if (die < 38)
3924         {
3925                 msg_print(_("《運命の輪》だ。", "It's the Wheel of Fortune."));
3926                 wild_magic(caster_ptr, randint0(32));
3927         }
3928         else if (die < 40)
3929         {
3930                 msg_print(_("テレポート・カードだ。", "It's a teleport trump card."));
3931                 teleport_player(caster_ptr, 10, TELEPORT_PASSIVE);
3932         }
3933         else if (die < 42)
3934         {
3935                 msg_print(_("《正義》だ。", "It's Justice."));
3936                 set_blessed(caster_ptr, caster_ptr->lev, FALSE);
3937         }
3938         else if (die < 47)
3939         {
3940                 msg_print(_("テレポート・カードだ。", "It's a teleport trump card."));
3941                 teleport_player(caster_ptr, 100, TELEPORT_PASSIVE);
3942         }
3943         else if (die < 52)
3944         {
3945                 msg_print(_("テレポート・カードだ。", "It's a teleport trump card."));
3946                 teleport_player(caster_ptr, 200, TELEPORT_PASSIVE);
3947         }
3948         else if (die < 60)
3949         {
3950                 msg_print(_("《塔》だ。", "It's the Tower."));
3951                 wall_breaker(caster_ptr);
3952         }
3953         else if (die < 72)
3954         {
3955                 msg_print(_("《節制》だ。", "It's Temperance."));
3956                 sleep_monsters_touch(caster_ptr);
3957         }
3958         else if (die < 80)
3959         {
3960                 msg_print(_("《塔》だ。", "It's the Tower."));
3961
3962                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, 5, 0);
3963         }
3964         else if (die < 82)
3965         {
3966                 msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
3967                 trump_summoning(caster_ptr, 1, TRUE, caster_ptr->y, caster_ptr->x, (caster_ptr->current_floor_ptr->dun_level * 3 / 2), SUMMON_MOLD, 0L);
3968         }
3969         else if (die < 84)
3970         {
3971                 msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
3972                 trump_summoning(caster_ptr, 1, TRUE, caster_ptr->y, caster_ptr->x, (caster_ptr->current_floor_ptr->dun_level * 3 / 2), SUMMON_BAT, 0L);
3973         }
3974         else if (die < 86)
3975         {
3976                 msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
3977                 trump_summoning(caster_ptr, 1, TRUE, caster_ptr->y, caster_ptr->x, (caster_ptr->current_floor_ptr->dun_level * 3 / 2), SUMMON_VORTEX, 0L);
3978         }
3979         else if (die < 88)
3980         {
3981                 msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster."));
3982                 trump_summoning(caster_ptr, 1, TRUE, caster_ptr->y, caster_ptr->x, (caster_ptr->current_floor_ptr->dun_level * 3 / 2), SUMMON_COIN_MIMIC, 0L);
3983         }
3984         else if (die < 96)
3985         {
3986                 msg_print(_("《恋人》だ。", "It's the Lovers."));
3987
3988                 if (get_aim_dir(&dir))
3989                         charm_monster(caster_ptr, dir, MIN(caster_ptr->lev, 20));
3990         }
3991         else if (die < 101)
3992         {
3993                 msg_print(_("《隠者》だ。", "It's the Hermit."));
3994                 wall_stone(caster_ptr);
3995         }
3996         else if (die < 111)
3997         {
3998                 msg_print(_("《審判》だ。", "It's the Judgement."));
3999                 roll_hitdice(caster_ptr, 0L);
4000                 lose_all_mutations(caster_ptr);
4001         }
4002         else if (die < 120)
4003         {
4004                 msg_print(_("《太陽》だ。", "It's the Sun."));
4005                 chg_virtue(caster_ptr, V_KNOWLEDGE, 1);
4006                 chg_virtue(caster_ptr, V_ENLIGHTEN, 1);
4007                 wiz_lite(caster_ptr, FALSE);
4008         }
4009         else
4010         {
4011                 msg_print(_("《世界》だ。", "It's the World."));
4012                 if (caster_ptr->exp < PY_MAX_EXP)
4013                 {
4014                         s32b ee = (caster_ptr->exp / 25) + 1;
4015                         if (ee > 5000) ee = 5000;
4016                         msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
4017                         gain_exp(caster_ptr, ee);
4018                 }
4019         }
4020 }
4021
4022 /*!
4023  * @brief 口を使う継続的な処理を中断する
4024  * @param caster_ptr プレーヤーへの参照ポインタ
4025  * @return なし
4026  */
4027 void stop_mouth(player_type *caster_ptr)
4028 {
4029         if (music_singing_any(caster_ptr)) stop_singing(caster_ptr);
4030         if (hex_spelling_any(caster_ptr)) stop_hex_spell_all(caster_ptr);
4031 }
4032
4033
4034 bool_hack vampirism(player_type *caster_ptr)
4035 {
4036         DIRECTION dir;
4037         POSITION x, y;
4038         int dummy;
4039         grid_type *g_ptr;
4040
4041         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_NO_MELEE)
4042         {
4043                 msg_print(_("なぜか攻撃することができない。", "Something prevent you from attacking."));
4044                 return FALSE;
4045         }
4046
4047         /* Only works on adjacent monsters */
4048         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return FALSE;
4049         y = caster_ptr->y + ddy[dir];
4050         x = caster_ptr->x + ddx[dir];
4051         g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
4052
4053         stop_mouth(caster_ptr);
4054
4055         if (!(g_ptr->m_idx))
4056         {
4057                 msg_print(_("何もない場所に噛みついた!", "You bite into thin air!"));
4058                 return FALSE;
4059         }
4060
4061         msg_print(_("あなたはニヤリとして牙をむいた...", "You grin and bare your fangs..."));
4062
4063         dummy = caster_ptr->lev * 2;
4064
4065         if (hypodynamic_bolt(caster_ptr, dir, dummy))
4066         {
4067                 if (caster_ptr->food < PY_FOOD_FULL)
4068                         /* No heal if we are "full" */
4069                         (void)hp_player(caster_ptr, dummy);
4070                 else
4071                         msg_print(_("あなたは空腹ではありません。", "You were not hungry."));
4072
4073                 /* Gain nutritional sustenance: 150/hp drained */
4074                 /* A Food ration gives 5000 food points (by contrast) */
4075                 /* Don't ever get more than "Full" this way */
4076                 /* But if we ARE Gorged,  it won't cure us */
4077                 dummy = caster_ptr->food + MIN(5000, 100 * dummy);
4078                 if (caster_ptr->food < PY_FOOD_MAX)   /* Not gorged already */
4079                         (void)set_food(caster_ptr, dummy >= PY_FOOD_MAX ? PY_FOOD_MAX - 1 : dummy);
4080         }
4081         else
4082                 msg_print(_("げぇ!ひどい味だ。", "Yechh. That tastes foul."));
4083         return TRUE;
4084 }
4085
4086
4087 bool panic_hit(void)
4088 {
4089         DIRECTION dir;
4090         POSITION x, y;
4091
4092         if (!get_direction(p_ptr, &dir, FALSE, FALSE)) return FALSE;
4093         y = p_ptr->y + ddy[dir];
4094         x = p_ptr->x + ddx[dir];
4095         if (p_ptr->current_floor_ptr->grid_array[y][x].m_idx)
4096         {
4097                 py_attack(p_ptr, y, x, 0);
4098                 if (randint0(p_ptr->skill_dis) < 7)
4099                         msg_print(_("うまく逃げられなかった。", "You failed to run away."));
4100                 else
4101                         teleport_player(p_ptr, 30, 0L);
4102                 return TRUE;
4103         }
4104         else
4105         {
4106                 msg_print(_("その方向にはモンスターはいません。", "You don't see any monster in this direction"));
4107                 msg_print(NULL);
4108                 return FALSE;
4109         }
4110 }
4111
4112
4113 /*!
4114 * @brief 超能力者のサイコメトリー処理/ Forcibly pseudo-identify an object in the inventory (or on the floor)
4115 * @param caster_ptr プレーヤーへの参照ポインタ
4116 * @return なし
4117 * @note
4118 * currently this function allows pseudo-id of any object,
4119 * including silly ones like potions & scrolls, which always
4120 * get '{average}'. This should be changed, either to stop such
4121 * items from being pseudo-id'd, or to allow psychometry to
4122 * detect whether the unidentified potion/scroll/etc is
4123 * good (Cure Light Wounds, Restore Strength, etc) or
4124 * bad (Poison, Weakness etc) or 'useless' (Slime Mold Juice, etc).
4125 */
4126 bool psychometry(player_type *caster_ptr)
4127 {
4128         OBJECT_IDX      item;
4129         object_type *o_ptr;
4130         GAME_TEXT o_name[MAX_NLEN];
4131         byte            feel;
4132         concptr            q, s;
4133         bool okay = FALSE;
4134
4135         q = _("どのアイテムを調べますか?", "Meditate on which item? ");
4136         s = _("調べるアイテムがありません。", "You have nothing appropriate.");
4137
4138         o_ptr = choose_object(caster_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
4139         if (!o_ptr) return (FALSE);
4140
4141         /* It is fully known, no information needed */
4142         if (object_is_known(o_ptr))
4143         {
4144                 msg_print(_("何も新しいことは判らなかった。", "You cannot find out anything more about that."));
4145                 return TRUE;
4146         }
4147
4148         /* Check for a feeling */
4149         feel = value_check_aux1(o_ptr);
4150
4151         /* Get an object description */
4152         object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
4153
4154         /* Skip non-feelings */
4155         if (!feel)
4156         {
4157                 msg_format(_("%sからは特に変わった事は感じとれなかった。", "You do not perceive anything unusual about the %s."), o_name);
4158                 return TRUE;
4159         }
4160
4161 #ifdef JP
4162         msg_format("%sは%sという感じがする...", o_name, game_inscriptions[feel]);
4163 #else
4164         msg_format("You feel that the %s %s %s...",
4165                 o_name, ((o_ptr->number == 1) ? "is" : "are"), game_inscriptions[feel]);
4166 #endif
4167
4168
4169         o_ptr->ident |= (IDENT_SENSE);
4170         o_ptr->feeling = feel;
4171         o_ptr->marked |= OM_TOUCHED;
4172
4173         caster_ptr->update |= (PU_COMBINE | PU_REORDER);
4174         caster_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
4175
4176         /* Valid "tval" codes */
4177         switch (o_ptr->tval)
4178         {
4179         case TV_SHOT:
4180         case TV_ARROW:
4181         case TV_BOLT:
4182         case TV_BOW:
4183         case TV_DIGGING:
4184         case TV_HAFTED:
4185         case TV_POLEARM:
4186         case TV_SWORD:
4187         case TV_BOOTS:
4188         case TV_GLOVES:
4189         case TV_HELM:
4190         case TV_CROWN:
4191         case TV_SHIELD:
4192         case TV_CLOAK:
4193         case TV_SOFT_ARMOR:
4194         case TV_HARD_ARMOR:
4195         case TV_DRAG_ARMOR:
4196         case TV_CARD:
4197         case TV_RING:
4198         case TV_AMULET:
4199         case TV_LITE:
4200         case TV_FIGURINE:
4201                 okay = TRUE;
4202                 break;
4203         }
4204
4205         /* Auto-inscription/destroy */
4206         autopick_alter_item(item, (bool)(okay && destroy_feeling));
4207
4208         /* Something happened */
4209         return (TRUE);
4210 }
4211
4212
4213 bool draconian_breath(player_type *creature_ptr)
4214 {
4215         DIRECTION dir;
4216         int Type = (one_in_(3) ? GF_COLD : GF_FIRE);
4217         concptr Type_desc = ((Type == GF_COLD) ? _("冷気", "cold") : _("炎", "fire"));
4218
4219         if (!get_aim_dir(&dir)) return FALSE;
4220
4221         if (randint1(100) < creature_ptr->lev)
4222         {
4223                 switch (creature_ptr->pclass)
4224                 {
4225                 case CLASS_WARRIOR:
4226                 case CLASS_BERSERKER:
4227                 case CLASS_RANGER:
4228                 case CLASS_TOURIST:
4229                 case CLASS_IMITATOR:
4230                 case CLASS_ARCHER:
4231                 case CLASS_SMITH:
4232                         if (one_in_(3))
4233                         {
4234                                 Type = GF_MISSILE;
4235                                 Type_desc = _("エレメント", "the elements");
4236                         }
4237                         else
4238                         {
4239                                 Type = GF_SHARDS;
4240                                 Type_desc = _("破片", "shards");
4241                         }
4242
4243                         break;
4244                 case CLASS_MAGE:
4245                 case CLASS_WARRIOR_MAGE:
4246                 case CLASS_HIGH_MAGE:
4247                 case CLASS_SORCERER:
4248                 case CLASS_MAGIC_EATER:
4249                 case CLASS_RED_MAGE:
4250                 case CLASS_BLUE_MAGE:
4251                 case CLASS_MIRROR_MASTER:
4252                         if (one_in_(3))
4253                         {
4254                                 Type = GF_MANA;
4255                                 Type_desc = _("魔力", "mana");
4256                         }
4257                         else
4258                         {
4259                                 Type = GF_DISENCHANT;
4260                                 Type_desc = _("劣化", "disenchantment");
4261                         }
4262
4263                         break;
4264                 case CLASS_CHAOS_WARRIOR:
4265                         if (!one_in_(3))
4266                         {
4267                                 Type = GF_CONFUSION;
4268                                 Type_desc = _("混乱", "confusion");
4269                         }
4270                         else
4271                         {
4272                                 Type = GF_CHAOS;
4273                                 Type_desc = _("カオス", "chaos");
4274                         }
4275
4276                         break;
4277                 case CLASS_MONK:
4278                 case CLASS_SAMURAI:
4279                 case CLASS_FORCETRAINER:
4280                         if (!one_in_(3))
4281                         {
4282                                 Type = GF_CONFUSION;
4283                                 Type_desc = _("混乱", "confusion");
4284                         }
4285                         else
4286                         {
4287                                 Type = GF_SOUND;
4288                                 Type_desc = _("轟音", "sound");
4289                         }
4290
4291                         break;
4292                 case CLASS_MINDCRAFTER:
4293                         if (!one_in_(3))
4294                         {
4295                                 Type = GF_CONFUSION;
4296                                 Type_desc = _("混乱", "confusion");
4297                         }
4298                         else
4299                         {
4300                                 Type = GF_PSI;
4301                                 Type_desc = _("精神エネルギー", "mental energy");
4302                         }
4303
4304                         break;
4305                 case CLASS_PRIEST:
4306                 case CLASS_PALADIN:
4307                         if (one_in_(3))
4308                         {
4309                                 Type = GF_HELL_FIRE;
4310                                 Type_desc = _("地獄の劫火", "hellfire");
4311                         }
4312                         else
4313                         {
4314                                 Type = GF_HOLY_FIRE;
4315                                 Type_desc = _("聖なる炎", "holy fire");
4316                         }
4317
4318                         break;
4319                 case CLASS_ROGUE:
4320                 case CLASS_NINJA:
4321                         if (one_in_(3))
4322                         {
4323                                 Type = GF_DARK;
4324                                 Type_desc = _("暗黒", "darkness");
4325                         }
4326                         else
4327                         {
4328                                 Type = GF_POIS;
4329                                 Type_desc = _("毒", "poison");
4330                         }
4331
4332                         break;
4333                 case CLASS_BARD:
4334                         if (!one_in_(3))
4335                         {
4336                                 Type = GF_SOUND;
4337                                 Type_desc = _("轟音", "sound");
4338                         }
4339                         else
4340                         {
4341                                 Type = GF_CONFUSION;
4342                                 Type_desc = _("混乱", "confusion");
4343                         }
4344
4345                         break;
4346                 }
4347         }
4348
4349         stop_mouth(creature_ptr);
4350         msg_format(_("あなたは%sのブレスを吐いた。", "You breathe %s."), Type_desc);
4351
4352         fire_breath(creature_ptr, Type, dir, creature_ptr->lev * 2, (creature_ptr->lev / 15) + 1);
4353         return TRUE;
4354 }
4355
4356
4357 bool android_inside_weapon(player_type *creature_ptr)
4358 {
4359         DIRECTION dir;
4360         if (!get_aim_dir(&dir)) return FALSE;
4361         if (creature_ptr->lev < 10)
4362         {
4363                 msg_print(_("レイガンを発射した。", "You fire your ray gun."));
4364                 fire_bolt(creature_ptr, GF_MISSILE, dir, (creature_ptr->lev + 1) / 2);
4365         }
4366         else if (creature_ptr->lev < 25)
4367         {
4368                 msg_print(_("ブラスターを発射した。", "You fire your blaster."));
4369                 fire_bolt(creature_ptr, GF_MISSILE, dir, creature_ptr->lev);
4370         }
4371         else if (creature_ptr->lev < 35)
4372         {
4373                 msg_print(_("バズーカを発射した。", "You fire your bazooka."));
4374                 fire_ball(creature_ptr, GF_MISSILE, dir, creature_ptr->lev * 2, 2);
4375         }
4376         else if (creature_ptr->lev < 45)
4377         {
4378                 msg_print(_("ビームキャノンを発射した。", "You fire a beam cannon."));
4379                 fire_beam(creature_ptr, GF_MISSILE, dir, creature_ptr->lev * 2);
4380         }
4381         else
4382         {
4383                 msg_print(_("ロケットを発射した。", "You fire a rocket."));
4384                 fire_rocket(creature_ptr, GF_ROCKET, dir, creature_ptr->lev * 5, 2);
4385         }
4386
4387         return TRUE;
4388 }
4389
4390
4391 bool create_ration(player_type *crature_ptr)
4392 {
4393         object_type *q_ptr;
4394         object_type forge;
4395         q_ptr = &forge;
4396
4397         /* Create the food ration */
4398         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION));
4399
4400         /* Drop the object from heaven */
4401         (void)drop_near(q_ptr, -1, crature_ptr->y, crature_ptr->x);
4402         msg_print(_("食事を料理して作った。", "You cook some food."));
4403         return TRUE;
4404 }
4405
4406
4407 void hayagake(player_type *creature_ptr)
4408 {
4409         if (creature_ptr->action == ACTION_HAYAGAKE)
4410         {
4411                 set_action(creature_ptr, ACTION_NONE);
4412         }
4413         else
4414         {
4415                 grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x];
4416                 feature_type *f_ptr = &f_info[g_ptr->feat];
4417
4418                 if (!have_flag(f_ptr->flags, FF_PROJECT) ||
4419                         (!creature_ptr->levitation && have_flag(f_ptr->flags, FF_DEEP)))
4420                 {
4421                         msg_print(_("ここでは素早く動けない。", "You cannot run in here."));
4422                 }
4423                 else
4424                 {
4425                         set_action(creature_ptr, ACTION_HAYAGAKE);
4426                 }
4427         }
4428
4429         creature_ptr->energy_use = 0;
4430 }
4431
4432
4433 bool double_attack(player_type *creature_ptr)
4434 {
4435         DIRECTION dir;
4436         POSITION x, y;
4437
4438         if (!get_rep_dir(&dir, FALSE)) return FALSE;
4439         y = creature_ptr->y + ddy[dir];
4440         x = creature_ptr->x + ddx[dir];
4441         if (creature_ptr->current_floor_ptr->grid_array[y][x].m_idx)
4442         {
4443                 if (one_in_(3))
4444                         msg_print(_("あーたたたたたたたたたたたたたたたたたたたたたた!!!",
4445                                 "Ahhhtatatatatatatatatatatatatatataatatatatattaaaaa!!!!"));
4446                 else if(one_in_(2))
4447                         msg_print(_("無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄!!!",
4448                                 "Mudamudamudamudamudamudamudamudamudamudamudamudamuda!!!!"));
4449                 else
4450                         msg_print(_("オラオラオラオラオラオラオラオラオラオラオラオラ!!!",
4451                                 "Oraoraoraoraoraoraoraoraoraoraoraoraoraoraoraoraora!!!!"));
4452
4453                 py_attack(creature_ptr, y, x, 0);
4454                 if (creature_ptr->current_floor_ptr->grid_array[y][x].m_idx)
4455                 {
4456                         handle_stuff();
4457                         py_attack(creature_ptr, y, x, 0);
4458                 }
4459                 creature_ptr->energy_need += ENERGY_NEED();
4460         }
4461         else
4462         {
4463                 msg_print(_("その方向にはモンスターはいません。", "You don't see any monster in this direction"));
4464                 msg_print(NULL);
4465         }
4466
4467         return TRUE;
4468 }
4469
4470
4471 bool comvert_hp_to_mp(player_type *creature_ptr)
4472 {
4473         int gain_sp = take_hit(p_ptr, DAMAGE_USELIFE, creature_ptr->lev, _("HPからMPへの無謀な変換", "thoughtless convertion from HP to SP"), -1) / 5;
4474         if (gain_sp)
4475         {
4476                 creature_ptr->csp += gain_sp;
4477                 if (creature_ptr->csp > creature_ptr->msp)
4478                 {
4479                         creature_ptr->csp = creature_ptr->msp;
4480                         creature_ptr->csp_frac = 0;
4481                 }
4482         }
4483         else
4484         {
4485                 msg_print(_("変換に失敗した。", "You failed to convert."));
4486         }
4487
4488         creature_ptr->redraw |= (PR_HP | PR_MANA);
4489         return TRUE;
4490 }
4491
4492
4493 bool comvert_mp_to_hp(player_type *creature_ptr)
4494 {
4495         if (creature_ptr->csp >= creature_ptr->lev / 5)
4496         {
4497                 creature_ptr->csp -= creature_ptr->lev / 5;
4498                 hp_player(p_ptr, creature_ptr->lev);
4499         }
4500         else
4501         {
4502                 msg_print(_("変換に失敗した。", "You failed to convert."));
4503         }
4504
4505         creature_ptr->redraw |= (PR_HP | PR_MANA);
4506         return TRUE;
4507 }
4508
4509
4510 bool demonic_breath(player_type *creature_ptr)
4511 {
4512         DIRECTION dir;
4513         int type = (one_in_(2) ? GF_NETHER : GF_FIRE);
4514         if (!get_aim_dir(&dir)) return FALSE;
4515         stop_mouth(creature_ptr);
4516         msg_format(_("あなたは%sのブレスを吐いた。", "You breathe %s."), ((type == GF_NETHER) ? _("地獄", "nether") : _("火炎", "fire")));
4517         fire_breath(creature_ptr, type, dir, creature_ptr->lev * 3, (creature_ptr->lev / 15) + 1);
4518         return TRUE;
4519 }
4520
4521
4522 bool mirror_concentration(player_type *creature_ptr)
4523 {
4524         if (total_friends)
4525         {
4526                 msg_print(_("今はペットを操ることに集中していないと。", "You need concentration on the pets now."));
4527                 return FALSE;
4528         }
4529
4530         if (is_mirror_grid(&p_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x]))
4531         {
4532                 msg_print(_("少し頭がハッキリした。", "You feel your head clear a little."));
4533
4534                 creature_ptr->csp += (5 + creature_ptr->lev * creature_ptr->lev / 100);
4535                 if (creature_ptr->csp >= creature_ptr->msp)
4536                 {
4537                         creature_ptr->csp = creature_ptr->msp;
4538                         creature_ptr->csp_frac = 0;
4539                 }
4540                 creature_ptr->redraw |= (PR_MANA);
4541         }
4542         else
4543         {
4544                 msg_print(_("鏡の上でないと集中できない!", "Here are not any mirrors!"));
4545         }
4546
4547         return TRUE;
4548 }
4549
4550
4551 bool sword_dancing(player_type *creature_ptr)
4552 {
4553         DIRECTION dir;
4554         POSITION y = 0, x = 0;
4555         int i;
4556         grid_type *g_ptr;
4557
4558         for (i = 0; i < 6; i++)
4559         {
4560                 dir = randint0(8);
4561                 y = creature_ptr->y + ddy_ddd[dir];
4562                 x = creature_ptr->x + ddx_ddd[dir];
4563                 g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
4564
4565                 /* Hack -- attack monsters */
4566                 if (g_ptr->m_idx)
4567                         py_attack(creature_ptr, y, x, 0);
4568                 else
4569                 {
4570                         msg_print(_("攻撃が空をきった。", "You attack the empty air."));
4571                 }
4572         }
4573
4574         return TRUE;
4575 }
4576
4577 /*!
4578  * 幻惑の光
4579  * @param creature_ptr プレーヤーへの参照ポインタ
4580  * @return 常にTRUE
4581 */
4582 bool confusing_light(player_type *creature_ptr)
4583 {
4584         msg_print(_("辺りを睨んだ...", "You glare nearby monsters..."));
4585         slow_monsters(creature_ptr, creature_ptr->lev);
4586         stun_monsters(creature_ptr, creature_ptr->lev * 4);
4587         confuse_monsters(creature_ptr, creature_ptr->lev * 4);
4588         turn_monsters(creature_ptr, creature_ptr->lev * 4);
4589         stasis_monsters(creature_ptr, creature_ptr->lev * 4);
4590         return TRUE;
4591 }
4592
4593
4594 /*!
4595  * 荒馬慣らし
4596  * @param creature_ptr プレーヤーへの参照ポインタ
4597  * @return 結果はどうあれ騎乗したらTRUE
4598 */
4599 bool rodeo(player_type *creature_ptr)
4600 {
4601         GAME_TEXT m_name[MAX_NLEN];
4602         monster_type *m_ptr;
4603         monster_race *r_ptr;
4604         int rlev;
4605
4606         if (creature_ptr->riding)
4607         {
4608                 msg_print(_("今は乗馬中だ。", "You ARE riding."));
4609                 return FALSE;
4610         }
4611
4612         if (!do_cmd_riding(creature_ptr, TRUE)) return TRUE;
4613
4614         m_ptr = &p_ptr->current_floor_ptr->m_list[creature_ptr->riding];
4615         r_ptr = &r_info[m_ptr->r_idx];
4616         monster_desc(m_name, m_ptr, 0);
4617         msg_format(_("%sに乗った。", "You ride on %s."), m_name);
4618
4619         if (is_pet(m_ptr)) return TRUE;
4620
4621         rlev = r_ptr->level;
4622
4623         if (r_ptr->flags1 & RF1_UNIQUE) rlev = rlev * 3 / 2;
4624         if (rlev > 60) rlev = 60 + (rlev - 60) / 2;
4625         if ((randint1(creature_ptr->skill_exp[GINOU_RIDING] / 120 + creature_ptr->lev * 2 / 3) > rlev)
4626                 && one_in_(2) && !creature_ptr->current_floor_ptr->inside_arena && !creature_ptr->phase_out
4627                 && !(r_ptr->flags7 & (RF7_GUARDIAN)) && !(r_ptr->flags1 & (RF1_QUESTOR))
4628                 && (rlev < creature_ptr->lev * 3 / 2 + randint0(creature_ptr->lev / 5)))
4629         {
4630                 msg_format(_("%sを手なずけた。", "You tame %s."), m_name);
4631                 set_pet(m_ptr);
4632         }
4633         else
4634         {
4635                 msg_format(_("%sに振り落とされた!", "You have thrown off by %s."), m_name);
4636                 rakuba(p_ptr, 1, TRUE);
4637                 /* 落馬処理に失敗してもとにかく乗馬解除 */
4638                 creature_ptr->riding = 0;
4639         }
4640
4641         return TRUE;
4642 }
4643
4644
4645 bool clear_mind(player_type *creature_ptr)
4646 {
4647         if (total_friends)
4648         {
4649                 msg_print(_("今はペットを操ることに集中していないと。", "You need concentration on the pets now."));
4650                 return FALSE;
4651         }
4652         msg_print(_("少し頭がハッキリした。", "You feel your head clear a little."));
4653
4654         creature_ptr->csp += (3 + creature_ptr->lev / 20);
4655         if (creature_ptr->csp >= creature_ptr->msp)
4656         {
4657                 creature_ptr->csp = creature_ptr->msp;
4658                 creature_ptr->csp_frac = 0;
4659         }
4660
4661         creature_ptr->redraw |= (PR_MANA);
4662         return TRUE;
4663 }
4664
4665
4666 bool concentration(player_type *creature_ptr)
4667 {
4668         int max_csp = MAX(creature_ptr->msp * 4, creature_ptr->lev * 5 + 5);
4669
4670         if (total_friends)
4671         {
4672                 msg_print(_("今はペットを操ることに集中していないと。", "You need concentration on the pets now."));
4673                 return FALSE;
4674         }
4675
4676         if (creature_ptr->special_defense & KATA_MASK)
4677         {
4678                 msg_print(_("今は構えに集中している。", "You need concentration on your form."));
4679                 return FALSE;
4680         }
4681
4682         msg_print(_("精神を集中して気合いを溜めた。", "You concentrate to charge your power."));
4683
4684         creature_ptr->csp += creature_ptr->msp / 2;
4685         if (creature_ptr->csp >= max_csp)
4686         {
4687                 creature_ptr->csp = max_csp;
4688                 creature_ptr->csp_frac = 0;
4689         }
4690
4691         creature_ptr->redraw |= (PR_MANA);
4692         return TRUE;
4693 }