OSDN Git Service

Merge remote-tracking branch 'remotes/origin/For2.2.2-Fix-Hourier' into For2.2.2...
[hengbandforosx/hengbandosx.git] / src / target / target-preparation.c
1 #include "target/target-preparation.h"
2 #include "floor/cave.h"
3 #include "floor/floor.h"
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  * Determine if a given location is "interesting"
55  */
56 static bool target_set_accept(player_type *creature_ptr, POSITION y, POSITION x)
57 {
58     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
59     if (!(in_bounds(floor_ptr, y, x)))
60         return FALSE;
61
62     if (player_bold(creature_ptr, y, x))
63         return TRUE;
64
65     if (creature_ptr->image)
66         return FALSE;
67
68     grid_type *g_ptr;
69     g_ptr = &floor_ptr->grid_array[y][x];
70     if (g_ptr->m_idx) {
71         monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
72         if (m_ptr->ml)
73             return TRUE;
74     }
75
76     OBJECT_IDX next_o_idx = 0;
77     for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
78         object_type *o_ptr;
79         o_ptr = &floor_ptr->o_list[this_o_idx];
80         next_o_idx = o_ptr->next_o_idx;
81         if (o_ptr->marked & OM_FOUND)
82             return TRUE;
83     }
84
85     if (g_ptr->info & (CAVE_MARK)) {
86         if (g_ptr->info & CAVE_OBJECT)
87             return TRUE;
88
89         if (have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_NOTICE))
90             return TRUE;
91     }
92
93     return FALSE;
94 }
95
96 /*
97  * Prepare the "temp" array for "target_set"
98  *
99  * Return the number of target_able monsters in the set.
100  */
101 void target_set_prepare(player_type *creature_ptr, BIT_FLAGS mode)
102 {
103     POSITION min_hgt, max_hgt, min_wid, max_wid;
104     if (mode & TARGET_KILL) {
105         min_hgt = MAX((creature_ptr->y - get_max_range(creature_ptr)), 0);
106         max_hgt = MIN((creature_ptr->y + get_max_range(creature_ptr)), creature_ptr->current_floor_ptr->height - 1);
107         min_wid = MAX((creature_ptr->x - get_max_range(creature_ptr)), 0);
108         max_wid = MIN((creature_ptr->x + get_max_range(creature_ptr)), creature_ptr->current_floor_ptr->width - 1);
109     } else {
110         min_hgt = panel_row_min;
111         max_hgt = panel_row_max;
112         min_wid = panel_col_min;
113         max_wid = panel_col_max;
114     }
115
116     tmp_pos.n = 0;
117     for (POSITION y = min_hgt; y <= max_hgt; y++) {
118         for (POSITION x = min_wid; x <= max_wid; x++) {
119             grid_type *g_ptr;
120             if (!target_set_accept(creature_ptr, y, x))
121                 continue;
122
123             g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
124             if ((mode & (TARGET_KILL)) && !target_able(creature_ptr, g_ptr->m_idx))
125                 continue;
126
127             if ((mode & (TARGET_KILL)) && !target_pet && is_pet(&creature_ptr->current_floor_ptr->m_list[g_ptr->m_idx]))
128                 continue;
129
130             tmp_pos.x[tmp_pos.n] = x;
131             tmp_pos.y[tmp_pos.n] = y;
132             tmp_pos.n++;
133         }
134     }
135
136     if (mode & (TARGET_KILL)) {
137         ang_sort(creature_ptr, tmp_pos.x, tmp_pos.y, tmp_pos.n, ang_sort_comp_distance, ang_sort_swap_distance);
138     } else {
139         ang_sort(creature_ptr, tmp_pos.x, tmp_pos.y, tmp_pos.n, ang_sort_comp_importance, ang_sort_swap_distance);
140     }
141
142     if (creature_ptr->riding == 0 || !target_pet || (tmp_pos.n <= 1) || !(mode & (TARGET_KILL)))
143         return;
144
145     POSITION tmp = tmp_pos.y[0];
146     tmp_pos.y[0] = tmp_pos.y[1];
147     tmp_pos.y[1] = tmp;
148     tmp = tmp_pos.x[0];
149     tmp_pos.x[0] = tmp_pos.x[1];
150     tmp_pos.x[1] = tmp;
151 }