OSDN Git Service

[Refactor] #40414 Moved wall_breaker() from spells2.c/h to spells-neighbor.c/h
[hengband/hengband.git] / src / spell-kind / spells-detection.c
1 #include "spell/spells-detection.h"
2 #include "core/player-processor.h"
3 #include "dungeon/dungeon.h"
4 #include "floor/floor.h"
5 #include "grid/grid.h"
6 #include "grid/trap.h"
7 #include "monster/monster-race-hook.h"
8 #include "monster/monster-status.h"
9 #include "object/object-hook.h"
10 #include "object/object-mark-types.h"
11 #include "realm/realm-song-numbers.h"
12 #include "realm/realm-song.h"
13
14 /*!
15  * @brief プレイヤー周辺の地形を感知する
16  * @param caster_ptr プレーヤーへの参照ポインタ
17  * @param range 効果範囲
18  * @param flag 特定地形ID
19  * @param known 地形から危険フラグを外すならTRUE
20  * @return 効力があった場合TRUEを返す
21  */
22 static bool detect_feat_flag(player_type *caster_ptr, POSITION range, int flag, bool known)
23 {
24     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
25         range /= 3;
26
27     grid_type *g_ptr;
28     bool detect = FALSE;
29     for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++) {
30         for (POSITION x = 1; x <= caster_ptr->current_floor_ptr->width - 1; x++) {
31             int dist = distance(caster_ptr->y, caster_ptr->x, y, x);
32             if (dist > range)
33                 continue;
34             g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
35             if (flag == FF_TRAP) {
36                 /* Mark as detected */
37                 if (dist <= range && known) {
38                     if (dist <= range - 1)
39                         g_ptr->info |= (CAVE_IN_DETECT);
40
41                     g_ptr->info &= ~(CAVE_UNSAFE);
42
43                     lite_spot(caster_ptr, y, x);
44                 }
45             }
46
47             if (cave_have_flag_grid(g_ptr, flag)) {
48                 disclose_grid(caster_ptr, y, x);
49                 g_ptr->info |= (CAVE_MARK);
50                 lite_spot(caster_ptr, y, x);
51                 detect = TRUE;
52             }
53         }
54     }
55
56     return detect;
57 }
58
59 /*!
60  * @brief プレイヤー周辺のトラップを感知する / Detect all traps on current panel
61  * @param caster_ptr プレーヤーへの参照ポインタ
62  * @param range 効果範囲
63  * @param known 感知外範囲を超える警告フラグを立てる場合TRUEを返す
64  * @return 効力があった場合TRUEを返す
65  */
66 bool detect_traps(player_type *caster_ptr, POSITION range, bool known)
67 {
68     bool detect = detect_feat_flag(caster_ptr, range, FF_TRAP, known);
69
70     if (known)
71         caster_ptr->dtrap = TRUE;
72
73     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 0)
74         detect = FALSE;
75     if (detect) {
76         msg_print(_("トラップの存在を感じとった!", "You sense the presence of traps!"));
77     }
78
79     return detect;
80 }
81
82 /*!
83  * @brief プレイヤー周辺のドアを感知する / Detect all doors on current panel
84  * @param caster_ptr プレーヤーへの参照ポインタ
85  * @param range 効果範囲
86  * @return 効力があった場合TRUEを返す
87  */
88 bool detect_doors(player_type *caster_ptr, POSITION range)
89 {
90     bool detect = detect_feat_flag(caster_ptr, range, FF_DOOR, TRUE);
91
92     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 0)
93         detect = FALSE;
94     if (detect) {
95         msg_print(_("ドアの存在を感じとった!", "You sense the presence of doors!"));
96     }
97
98     return detect;
99 }
100
101 /*!
102  * @brief プレイヤー周辺の階段を感知する / Detect all stairs on current panel
103  * @param caster_ptr プレーヤーへの参照ポインタ
104  * @param range 効果範囲
105  * @return 効力があった場合TRUEを返す
106  */
107 bool detect_stairs(player_type *caster_ptr, POSITION range)
108 {
109     bool detect = detect_feat_flag(caster_ptr, range, FF_STAIRS, TRUE);
110
111     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 0)
112         detect = FALSE;
113     if (detect) {
114         msg_print(_("階段の存在を感じとった!", "You sense the presence of stairs!"));
115     }
116
117     return detect;
118 }
119
120 /*!
121  * @brief プレイヤー周辺の地形財宝を感知する / Detect any treasure on the current panel
122  * @param caster_ptr プレーヤーへの参照ポインタ
123  * @param range 効果範囲
124  * @return 効力があった場合TRUEを返す
125  */
126 bool detect_treasure(player_type *caster_ptr, POSITION range)
127 {
128     bool detect = detect_feat_flag(caster_ptr, range, FF_HAS_GOLD, TRUE);
129
130     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 6)
131         detect = FALSE;
132     if (detect) {
133         msg_print(_("埋蔵された財宝の存在を感じとった!", "You sense the presence of buried treasure!"));
134     }
135
136     return detect;
137 }
138 /*!
139  * @brief プレイヤー周辺のアイテム財宝を感知する / Detect all "gold" objects on the current panel
140  * @param caster_ptr プレーヤーへの参照ポインタ
141  * @param range 効果範囲
142  * @return 効力があった場合TRUEを返す
143  */
144 bool detect_objects_gold(player_type *caster_ptr, POSITION range)
145 {
146     POSITION range2 = range;
147     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
148         range2 /= 3;
149
150     /* Scan objects */
151     bool detect = FALSE;
152     POSITION y, x;
153     for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++) {
154         object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
155
156         if (!OBJECT_IS_VALID(o_ptr))
157             continue;
158         if (OBJECT_IS_HELD_MONSTER(o_ptr))
159             continue;
160
161         y = o_ptr->iy;
162         x = o_ptr->ix;
163         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range2)
164             continue;
165
166         if (o_ptr->tval == TV_GOLD) {
167             o_ptr->marked |= OM_FOUND;
168             lite_spot(caster_ptr, y, x);
169             detect = TRUE;
170         }
171     }
172
173     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 6)
174         detect = FALSE;
175     if (detect) {
176         msg_print(_("財宝の存在を感じとった!", "You sense the presence of treasure!"));
177     }
178
179     if (detect_monsters_string(caster_ptr, range, "$")) {
180         detect = TRUE;
181     }
182
183     return detect;
184 }
185
186 /*!
187  * @brief 通常のアイテムオブジェクトを感知する / Detect all "normal" objects on the current panel
188  * @param caster_ptr プレーヤーへの参照ポインタ
189  * @param range 効果範囲
190  * @return 効力があった場合TRUEを返す
191  */
192 bool detect_objects_normal(player_type *caster_ptr, POSITION range)
193 {
194     POSITION range2 = range;
195     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
196         range2 /= 3;
197
198     bool detect = FALSE;
199     for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++) {
200         object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
201
202         if (!OBJECT_IS_VALID(o_ptr))
203             continue;
204         if (OBJECT_IS_HELD_MONSTER(o_ptr))
205             continue;
206
207         POSITION y = o_ptr->iy;
208         POSITION x = o_ptr->ix;
209
210         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range2)
211             continue;
212
213         if (o_ptr->tval != TV_GOLD) {
214             o_ptr->marked |= OM_FOUND;
215             lite_spot(caster_ptr, y, x);
216             detect = TRUE;
217         }
218     }
219
220     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 6)
221         detect = FALSE;
222     if (detect) {
223         msg_print(_("アイテムの存在を感じとった!", "You sense the presence of objects!"));
224     }
225
226     if (detect_monsters_string(caster_ptr, range, "!=?|/`")) {
227         detect = TRUE;
228     }
229
230     return detect;
231 }
232
233 /*!
234  * @brief 魔法効果のあるのアイテムオブジェクトを感知する / Detect all "magic" objects on the current panel.
235  * @param caster_ptr プレーヤーへの参照ポインタ
236  * @param range 効果範囲
237  * @return 効力があった場合TRUEを返す
238  * @details
239  * <pre>
240  * This will light up all spaces with "magic" items, including artifacts,
241  * ego-items, potions, scrolls, books, rods, wands, staffs, amulets, rings,
242  * and "enchanted" items of the "good" variety.
243  *
244  * It can probably be argued that this function is now too powerful.
245  * </pre>
246  */
247 bool detect_objects_magic(player_type *caster_ptr, POSITION range)
248 {
249     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
250         range /= 3;
251
252     tval_type tv;
253     bool detect = FALSE;
254     for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++) {
255         object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
256
257         if (!OBJECT_IS_VALID(o_ptr))
258             continue;
259         if (OBJECT_IS_HELD_MONSTER(o_ptr))
260             continue;
261
262         POSITION y = o_ptr->iy;
263         POSITION x = o_ptr->ix;
264
265         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
266             continue;
267
268         tv = o_ptr->tval;
269         if (object_is_artifact(o_ptr) || object_is_ego(o_ptr) || (tv == TV_WHISTLE) || (tv == TV_AMULET) || (tv == TV_RING) || (tv == TV_STAFF)
270             || (tv == TV_WAND) || (tv == TV_ROD) || (tv == TV_SCROLL) || (tv == TV_POTION) || (tv == TV_LIFE_BOOK) || (tv == TV_SORCERY_BOOK)
271             || (tv == TV_NATURE_BOOK) || (tv == TV_CHAOS_BOOK) || (tv == TV_DEATH_BOOK) || (tv == TV_TRUMP_BOOK) || (tv == TV_ARCANE_BOOK)
272             || (tv == TV_CRAFT_BOOK) || (tv == TV_DAEMON_BOOK) || (tv == TV_CRUSADE_BOOK) || (tv == TV_MUSIC_BOOK) || (tv == TV_HISSATSU_BOOK)
273             || (tv == TV_HEX_BOOK) || ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0))) {
274             o_ptr->marked |= OM_FOUND;
275             lite_spot(caster_ptr, y, x);
276             detect = TRUE;
277         }
278     }
279
280     if (detect) {
281         msg_print(_("魔法のアイテムの存在を感じとった!", "You sense the presence of magic objects!"));
282     }
283
284     return detect;
285 }
286
287 /*!
288  * @brief 一般のモンスターを感知する / Detect all "normal" monsters on the current panel
289  * @param caster_ptr プレーヤーへの参照ポインタ
290  * @param range 効果範囲
291  * @return 効力があった場合TRUEを返す
292  */
293 bool detect_monsters_normal(player_type *caster_ptr, POSITION range)
294 {
295     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
296         range /= 3;
297
298     bool flag = FALSE;
299     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
300         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
301         monster_race *r_ptr = &r_info[m_ptr->r_idx];
302         if (!monster_is_valid(m_ptr))
303             continue;
304
305         POSITION y = m_ptr->fy;
306         POSITION x = m_ptr->fx;
307         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
308             continue;
309
310         if (!(r_ptr->flags2 & RF2_INVISIBLE) || caster_ptr->see_inv) {
311             repair_monsters = TRUE;
312             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
313             update_monster(caster_ptr, i, FALSE);
314             flag = TRUE;
315         }
316     }
317
318     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 3)
319         flag = FALSE;
320     if (flag) {
321         msg_print(_("モンスターの存在を感じとった!", "You sense the presence of monsters!"));
322     }
323
324     return flag;
325 }
326
327 /*!
328  * @brief 不可視のモンスターを感知する / Detect all "invisible" monsters around the player
329  * @param caster_ptr プレーヤーへの参照ポインタ
330  * @param range 効果範囲
331  * @return 効力があった場合TRUEを返す
332  */
333 bool detect_monsters_invis(player_type *caster_ptr, POSITION range)
334 {
335     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
336         range /= 3;
337
338     bool flag = FALSE;
339     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
340         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
341         monster_race *r_ptr = &r_info[m_ptr->r_idx];
342
343         if (!monster_is_valid(m_ptr))
344             continue;
345
346         POSITION y = m_ptr->fy;
347         POSITION x = m_ptr->fx;
348
349         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
350             continue;
351
352         if (r_ptr->flags2 & RF2_INVISIBLE) {
353             if (caster_ptr->monster_race_idx == m_ptr->r_idx) {
354                 caster_ptr->window |= (PW_MONSTER);
355             }
356
357             repair_monsters = TRUE;
358             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
359             update_monster(caster_ptr, i, FALSE);
360             flag = TRUE;
361         }
362     }
363
364     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 3)
365         flag = FALSE;
366     if (flag) {
367         msg_print(_("透明な生物の存在を感じとった!", "You sense the presence of invisible creatures!"));
368     }
369
370     return flag;
371 }
372
373 /*!
374  * @brief 邪悪なモンスターを感知する / Detect all "evil" monsters on current panel
375  * @param caster_ptr プレーヤーへの参照ポインタ
376  * @param range 効果範囲
377  * @return 効力があった場合TRUEを返す
378  */
379 bool detect_monsters_evil(player_type *caster_ptr, POSITION range)
380 {
381     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
382         range /= 3;
383
384     bool flag = FALSE;
385     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
386         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
387         monster_race *r_ptr = &r_info[m_ptr->r_idx];
388         if (!monster_is_valid(m_ptr))
389             continue;
390
391         POSITION y = m_ptr->fy;
392         POSITION x = m_ptr->fx;
393
394         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
395             continue;
396
397         if (r_ptr->flags3 & RF3_EVIL) {
398             if (is_original_ap(m_ptr)) {
399                 r_ptr->r_flags3 |= (RF3_EVIL);
400                 if (caster_ptr->monster_race_idx == m_ptr->r_idx) {
401                     caster_ptr->window |= (PW_MONSTER);
402                 }
403             }
404
405             repair_monsters = TRUE;
406             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
407             update_monster(caster_ptr, i, FALSE);
408             flag = TRUE;
409         }
410     }
411
412     if (flag) {
413         msg_print(_("邪悪なる生物の存在を感じとった!", "You sense the presence of evil creatures!"));
414     }
415
416     return flag;
417 }
418
419 /*!
420  * @brief 無生命のモンスターを感知する(アンデッド、悪魔系を含む) / Detect all "nonliving", "undead" or "demonic" monsters on current panel
421  * @param caster_ptr プレーヤーへの参照ポインタ
422  * @param range 効果範囲
423  * @return 効力があった場合TRUEを返す
424  */
425 bool detect_monsters_nonliving(player_type *caster_ptr, POSITION range)
426 {
427     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
428         range /= 3;
429
430     bool flag = FALSE;
431     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
432         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
433         if (!monster_is_valid(m_ptr))
434             continue;
435
436         POSITION y = m_ptr->fy;
437         POSITION x = m_ptr->fx;
438         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
439             continue;
440
441         if (!monster_living(m_ptr->r_idx)) {
442             if (caster_ptr->monster_race_idx == m_ptr->r_idx) {
443                 caster_ptr->window |= (PW_MONSTER);
444             }
445
446             repair_monsters = TRUE;
447             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
448             update_monster(caster_ptr, i, FALSE);
449             flag = TRUE;
450         }
451     }
452
453     if (flag) {
454         msg_print(_("自然でないモンスターの存在を感じた!", "You sense the presence of unnatural beings!"));
455     }
456
457     return flag;
458 }
459
460 /*!
461  * @brief 精神のあるモンスターを感知する / Detect all monsters it has mind on current panel
462  * @param caster_ptr プレーヤーへの参照ポインタ
463  * @param range 効果範囲
464  * @return 効力があった場合TRUEを返す
465  */
466 bool detect_monsters_mind(player_type *caster_ptr, POSITION range)
467 {
468     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
469         range /= 3;
470
471     bool flag = FALSE;
472     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
473         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
474         monster_race *r_ptr = &r_info[m_ptr->r_idx];
475         if (!monster_is_valid(m_ptr))
476             continue;
477
478         POSITION y = m_ptr->fy;
479         POSITION x = m_ptr->fx;
480
481         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
482             continue;
483
484         if (!(r_ptr->flags2 & RF2_EMPTY_MIND)) {
485             if (caster_ptr->monster_race_idx == m_ptr->r_idx) {
486                 caster_ptr->window |= (PW_MONSTER);
487             }
488
489             repair_monsters = TRUE;
490             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
491             update_monster(caster_ptr, i, FALSE);
492             flag = TRUE;
493         }
494     }
495
496     if (flag) {
497         msg_print(_("殺気を感じとった!", "You sense the presence of someone's mind!"));
498     }
499
500     return flag;
501 }
502
503 /*!
504  * @brief 該当シンボルのモンスターを感知する / Detect all (string) monsters on current panel
505  * @param caster_ptr プレーヤーへの参照ポインタ
506  * @param range 効果範囲
507  * @param Match 対応シンボルの混じったモンスター文字列(複数指定化)
508  * @return 効力があった場合TRUEを返す
509  */
510 bool detect_monsters_string(player_type *caster_ptr, POSITION range, concptr Match)
511 {
512     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
513         range /= 3;
514
515     bool flag = FALSE;
516     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
517         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
518         monster_race *r_ptr = &r_info[m_ptr->r_idx];
519         if (!monster_is_valid(m_ptr))
520             continue;
521
522         POSITION y = m_ptr->fy;
523         POSITION x = m_ptr->fx;
524
525         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
526             continue;
527
528         if (my_strchr(Match, r_ptr->d_char)) {
529             if (caster_ptr->monster_race_idx == m_ptr->r_idx) {
530                 caster_ptr->window |= (PW_MONSTER);
531             }
532
533             repair_monsters = TRUE;
534             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
535             update_monster(caster_ptr, i, FALSE);
536             flag = TRUE;
537         }
538     }
539
540     if (music_singing(caster_ptr, MUSIC_DETECT) && SINGING_COUNT(caster_ptr) > 3)
541         flag = FALSE;
542     if (flag) {
543         msg_print(_("モンスターの存在を感じとった!", "You sense the presence of monsters!"));
544     }
545
546     return flag;
547 }
548
549 /*!
550  * @brief flags3に対応するモンスターを感知する / A "generic" detect monsters routine, tagged to flags3
551  * @param caster_ptr プレーヤーへの参照ポインタ
552  * @param range 効果範囲
553  * @param match_flag 感知フラグ
554  * @return 効力があった場合TRUEを返す
555  */
556 bool detect_monsters_xxx(player_type *caster_ptr, POSITION range, u32b match_flag)
557 {
558     if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
559         range /= 3;
560
561     bool flag = FALSE;
562     for (MONSTER_IDX i = 1; i < caster_ptr->current_floor_ptr->m_max; i++) {
563         monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[i];
564         monster_race *r_ptr = &r_info[m_ptr->r_idx];
565         if (!monster_is_valid(m_ptr))
566             continue;
567
568         POSITION y = m_ptr->fy;
569         POSITION x = m_ptr->fx;
570
571         if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
572             continue;
573
574         if (r_ptr->flags3 & (match_flag)) {
575             if (is_original_ap(m_ptr)) {
576                 r_ptr->r_flags3 |= (match_flag);
577                 if (caster_ptr->monster_race_idx == m_ptr->r_idx) {
578                     caster_ptr->window |= (PW_MONSTER);
579                 }
580             }
581
582             repair_monsters = TRUE;
583             m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW);
584             update_monster(caster_ptr, i, FALSE);
585             flag = TRUE;
586         }
587     }
588
589     concptr desc_monsters = _("変なモンスター", "weird monsters");
590     if (flag) {
591         switch (match_flag) {
592         case RF3_DEMON:
593             desc_monsters = _("デーモン", "demons");
594             break;
595         case RF3_UNDEAD:
596             desc_monsters = _("アンデッド", "the undead");
597             break;
598         }
599
600         msg_format(_("%sの存在を感じとった!", "You sense the presence of %s!"), desc_monsters);
601         msg_print(NULL);
602     }
603
604     return flag;
605 }
606
607 /*!
608  * @brief 全感知処理 / Detect everything
609  * @param caster_ptr プレーヤーへの参照ポインタ
610  * @param range 効果範囲
611  * @return 効力があった場合TRUEを返す
612  */
613 bool detect_all(player_type *caster_ptr, POSITION range)
614 {
615     bool detect = FALSE;
616     if (detect_traps(caster_ptr, range, TRUE))
617         detect = TRUE;
618     if (detect_doors(caster_ptr, range))
619         detect = TRUE;
620     if (detect_stairs(caster_ptr, range))
621         detect = TRUE;
622     if (detect_objects_gold(caster_ptr, range))
623         detect = TRUE;
624     if (detect_objects_normal(caster_ptr, range))
625         detect = TRUE;
626     if (detect_monsters_invis(caster_ptr, range))
627         detect = TRUE;
628     if (detect_monsters_normal(caster_ptr, range))
629         detect = TRUE;
630     return (detect);
631 }