OSDN Git Service

[Refactor] #40571 Removed unused headers in target-checker.c
[hengbandforosx/hengbandosx.git] / src / target / target-preparation.c
1 #include "target/target-preparation.h"
2 #include "floor/cave.h"
3 #include "floor/floor.h" // todo projectable() が相互依存.
4 #include "game-option/input-options.h"
5 #include "grid/feature.h"
6 #include "grid/grid.h"
7 #include "monster/monster-info.h"
8 #include "monster/monster-status.h"
9 #include "object/object-mark-types.h"
10 #include "system/floor-type-definition.h"
11 #include "system/object-type-definition.h"
12 #include "target/target-types.h"
13 #include "util/bit-flags-calculator.h"
14 #include "util/sort.h"
15 #include "window/main-window-util.h"
16
17 /*
18  * Determine is a monster makes a reasonable target
19  *
20  * The concept of "targeting" was stolen from "Morgul" (?)
21  *
22  * The player can target any location, or any "target-able" monster.
23  *
24  * Currently, a monster is "target_able" if it is visible, and if
25  * the player can hit it with a projection, and the player is not
26  * hallucinating.  This allows use of "use closest target" macros.
27  *
28  * Future versions may restrict the ability to target "trappers"
29  * and "mimics", but the semantics is a little bit weird.
30  */
31 bool target_able(player_type *creature_ptr, MONSTER_IDX m_idx)
32 {
33     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
34     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
35     if (!monster_is_valid(m_ptr))
36         return FALSE;
37
38     if (creature_ptr->image)
39         return FALSE;
40
41     if (!m_ptr->ml)
42         return FALSE;
43
44     if (creature_ptr->riding && (creature_ptr->riding == m_idx))
45         return TRUE;
46
47     if (!projectable(creature_ptr, creature_ptr->y, creature_ptr->x, m_ptr->fy, m_ptr->fx))
48         return FALSE;
49
50     return TRUE;
51 }
52
53 /*!
54  * @briefプレイヤーの攻撃射程(マス) / Maximum range (spells, etc)
55  * @param creature_ptr プレーヤーへの参照ポインタ
56  * @return 射程
57  */
58 int get_max_range(player_type *creature_ptr) { return creature_ptr->phase_out ? 36 : 18; }
59
60 /*
61  * Determine if a given location is "interesting"
62  */
63 static bool target_set_accept(player_type *creature_ptr, POSITION y, POSITION x)
64 {
65     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
66     if (!(in_bounds(floor_ptr, y, x)))
67         return FALSE;
68
69     if (player_bold(creature_ptr, y, x))
70         return TRUE;
71
72     if (creature_ptr->image)
73         return FALSE;
74
75     grid_type *g_ptr;
76     g_ptr = &floor_ptr->grid_array[y][x];
77     if (g_ptr->m_idx) {
78         monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
79         if (m_ptr->ml)
80             return TRUE;
81     }
82
83     OBJECT_IDX next_o_idx = 0;
84     for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
85         object_type *o_ptr;
86         o_ptr = &floor_ptr->o_list[this_o_idx];
87         next_o_idx = o_ptr->next_o_idx;
88         if (o_ptr->marked & OM_FOUND)
89             return TRUE;
90     }
91
92     if (g_ptr->info & (CAVE_MARK)) {
93         if (g_ptr->info & CAVE_OBJECT)
94             return TRUE;
95
96         if (have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_NOTICE))
97             return TRUE;
98     }
99
100     return FALSE;
101 }
102
103 /*
104  * Prepare the "temp" array for "target_set"
105  *
106  * Return the number of target_able monsters in the set.
107  */
108 void target_set_prepare(player_type *creature_ptr, BIT_FLAGS mode)
109 {
110     POSITION min_hgt, max_hgt, min_wid, max_wid;
111     if (mode & TARGET_KILL) {
112         min_hgt = MAX((creature_ptr->y - get_max_range(creature_ptr)), 0);
113         max_hgt = MIN((creature_ptr->y + get_max_range(creature_ptr)), creature_ptr->current_floor_ptr->height - 1);
114         min_wid = MAX((creature_ptr->x - get_max_range(creature_ptr)), 0);
115         max_wid = MIN((creature_ptr->x + get_max_range(creature_ptr)), creature_ptr->current_floor_ptr->width - 1);
116     } else {
117         min_hgt = panel_row_min;
118         max_hgt = panel_row_max;
119         min_wid = panel_col_min;
120         max_wid = panel_col_max;
121     }
122
123     tmp_pos.n = 0;
124     for (POSITION y = min_hgt; y <= max_hgt; y++) {
125         for (POSITION x = min_wid; x <= max_wid; x++) {
126             grid_type *g_ptr;
127             if (!target_set_accept(creature_ptr, y, x))
128                 continue;
129
130             g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
131             if ((mode & (TARGET_KILL)) && !target_able(creature_ptr, g_ptr->m_idx))
132                 continue;
133
134             if ((mode & (TARGET_KILL)) && !target_pet && is_pet(&creature_ptr->current_floor_ptr->m_list[g_ptr->m_idx]))
135                 continue;
136
137             tmp_pos.x[tmp_pos.n] = x;
138             tmp_pos.y[tmp_pos.n] = y;
139             tmp_pos.n++;
140         }
141     }
142
143     if (mode & (TARGET_KILL)) {
144         ang_sort(creature_ptr, tmp_pos.x, tmp_pos.y, tmp_pos.n, ang_sort_comp_distance, ang_sort_swap_distance);
145     } else {
146         ang_sort(creature_ptr, tmp_pos.x, tmp_pos.y, tmp_pos.n, ang_sort_comp_importance, ang_sort_swap_distance);
147     }
148
149     if (creature_ptr->riding == 0 || !target_pet || (tmp_pos.n <= 1) || !(mode & (TARGET_KILL)))
150         return;
151
152     POSITION tmp = tmp_pos.y[0];
153     tmp_pos.y[0] = tmp_pos.y[1];
154     tmp_pos.y[1] = tmp;
155     tmp = tmp_pos.x[0];
156     tmp_pos.x[0] = tmp_pos.x[1];
157     tmp_pos.x[1] = tmp;
158 }