1 #include "target/target-setter.h"
2 #include "core/player-redraw-types.h"
3 #include "core/player-update-types.h"
4 #include "core/stuff-handler.h"
5 #include "core/window-redrawer.h"
6 #include "floor/line-of-sight.h"
7 #include "game-option/cheat-options.h"
8 #include "game-option/game-play-options.h"
9 #include "game-option/input-options.h"
10 #include "grid/grid.h"
11 #include "io/cursor.h"
12 #include "io/input-key-requester.h"
13 #include "io/screen-util.h"
14 #include "main/sound-of-music.h"
15 #include "system/floor-type-definition.h"
16 #include "target/projection-path-calculator.h"
17 #include "target/target-checker.h"
18 #include "target/target-describer.h"
19 #include "target/target-preparation.h"
20 #include "target/target-types.h"
21 #include "term/screen-processor.h"
22 #include "util/int-char-converter.h"
23 #include "window/main-window-util.h"
26 typedef struct ts_type {
44 static ts_type *initialize_target_set_type(player_type *creature_ptr, ts_type *ts_ptr, target_type mode)
47 ts_ptr->y = creature_ptr->y;
48 ts_ptr->x = creature_ptr->x;
51 get_screen_size(&ts_ptr->wid, &ts_ptr->hgt);
57 * @brief フォーカスを当てるべきマップ描画の基準座標を指定する
58 * @param creature_ptr プレーヤーへの参照ポインタ
62 * Handle a request to change the current panel
63 * Return TRUE if the panel was changed.
64 * Also used in do_cmd_locate
65 * @return 実際に再描画が必要だった場合TRUEを返す
67 static bool change_panel_xy(player_type *creature_ptr, POSITION y, POSITION x)
69 POSITION dy = 0, dx = 0;
71 get_screen_size(&wid, &hgt);
72 if (y < panel_row_min)
75 if (y > panel_row_max)
78 if (x < panel_col_min)
81 if (x > panel_col_max)
87 return change_panel(creature_ptr, dy, dx);
91 * Help "select" a location (see below)
93 static POSITION_IDX target_pick(POSITION y1, POSITION x1, POSITION dy, POSITION dx)
95 POSITION_IDX b_i = -1, b_v = 9999;
96 for (POSITION_IDX i = 0; i < tmp_pos.n; i++) {
97 POSITION x2 = tmp_pos.x[i];
98 POSITION y2 = tmp_pos.y[i];
99 POSITION x3 = (x2 - x1);
100 POSITION y3 = (y2 - y1);
101 if (dx && (x3 * dx <= 0))
104 if (dy && (y3 * dy <= 0))
107 POSITION x4 = ABS(x3);
108 POSITION y4 = ABS(y3);
109 if (dy && !dx && (x4 > y4))
112 if (dx && !dy && (y4 > x4))
115 POSITION_IDX v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
116 if ((b_i >= 0) && (v >= b_v))
126 static void describe_projectablity(player_type *creature_ptr, ts_type *ts_ptr)
128 ts_ptr->y = tmp_pos.y[ts_ptr->m];
129 ts_ptr->x = tmp_pos.x[ts_ptr->m];
130 change_panel_xy(creature_ptr, ts_ptr->y, ts_ptr->x);
131 if ((ts_ptr->mode & TARGET_LOOK) == 0)
132 print_path(creature_ptr, ts_ptr->y, ts_ptr->x);
134 ts_ptr->g_ptr = &creature_ptr->current_floor_ptr->grid_array[ts_ptr->y][ts_ptr->x];
135 if (target_able(creature_ptr, ts_ptr->g_ptr->m_idx))
136 strcpy(ts_ptr->info, _("q止 t決 p自 o現 +次 -前", "q,t,p,o,+,-,<dir>"));
138 strcpy(ts_ptr->info, _("q止 p自 o現 +次 -前", "q,p,o,+,-,<dir>"));
144 sprintf(cheatinfo, " LOS:%d, PROJECTABLE:%d", los(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x),
145 projectable(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x));
146 strcat(ts_ptr->info, cheatinfo);
149 static void menu_target(ts_type *ts_ptr)
154 if (ts_ptr->query == '\r')
158 static void switch_target_input(player_type *creature_ptr, ts_type *ts_ptr)
160 ts_ptr->distance = 0;
161 switch (ts_ptr->query) {
170 if (!target_able(creature_ptr, ts_ptr->g_ptr->m_idx)) {
175 health_track(creature_ptr, ts_ptr->g_ptr->m_idx);
176 target_who = ts_ptr->g_ptr->m_idx;
177 target_row = ts_ptr->y;
178 target_col = ts_ptr->x;
184 if (++ts_ptr->m != tmp_pos.n)
193 if (ts_ptr->m-- != 0)
196 ts_ptr->m = tmp_pos.n - 1;
202 verify_panel(creature_ptr);
203 creature_ptr->update |= PU_MONSTERS;
204 creature_ptr->redraw |= PR_MAP;
205 creature_ptr->window_flags |= PW_OVERHEAD;
206 handle_stuff(creature_ptr);
207 target_set_prepare(creature_ptr, ts_ptr->mode);
208 ts_ptr->y = creature_ptr->y;
209 ts_ptr->x = creature_ptr->x;
213 ts_ptr->flag = FALSE;
218 const char queried_command = rogue_like_commands ? 'x' : 'l';
219 if (ts_ptr->query != queried_command) {
220 ts_ptr->distance = get_keymap_dir(ts_ptr->query);
221 if (ts_ptr->distance == 0)
227 if (++ts_ptr->m != tmp_pos.n)
239 static bool check_panel_changed(player_type *creature_ptr, ts_type *ts_ptr)
241 if (!change_panel(creature_ptr, ddy[ts_ptr->distance], ddx[ts_ptr->distance]))
244 int v = tmp_pos.y[ts_ptr->m];
245 int u = tmp_pos.x[ts_ptr->m];
246 target_set_prepare(creature_ptr, ts_ptr->mode);
248 ts_ptr->target_num = target_pick(v, u, ddy[ts_ptr->distance], ddx[ts_ptr->distance]);
249 if (ts_ptr->target_num >= 0)
250 ts_ptr->m = ts_ptr->target_num;
255 static void sweep_targets(player_type *creature_ptr, ts_type *ts_ptr)
257 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
258 while (ts_ptr->flag && (ts_ptr->target_num < 0)) {
259 if (check_panel_changed(creature_ptr, ts_ptr))
262 POSITION dx = ddx[ts_ptr->distance];
263 POSITION dy = ddy[ts_ptr->distance];
264 panel_row_min = ts_ptr->y2;
265 panel_col_min = ts_ptr->x2;
266 panel_bounds_center();
267 creature_ptr->update |= PU_MONSTERS;
268 creature_ptr->redraw |= PR_MAP;
269 creature_ptr->window_flags |= PW_OVERHEAD;
270 handle_stuff(creature_ptr);
271 target_set_prepare(creature_ptr, ts_ptr->mode);
272 ts_ptr->flag = FALSE;
275 if (((ts_ptr->x < panel_col_min + ts_ptr->wid / 2) && (dx > 0)) || ((ts_ptr->x > panel_col_min + ts_ptr->wid / 2) && (dx < 0)))
278 if (((ts_ptr->y < panel_row_min + ts_ptr->hgt / 2) && (dy > 0)) || ((ts_ptr->y > panel_row_min + ts_ptr->hgt / 2) && (dy < 0)))
281 if ((ts_ptr->y >= panel_row_min + ts_ptr->hgt) || (ts_ptr->y < panel_row_min) || (ts_ptr->x >= panel_col_min + ts_ptr->wid)
282 || (ts_ptr->x < panel_col_min)) {
283 if (change_panel(creature_ptr, dy, dx))
284 target_set_prepare(creature_ptr, ts_ptr->mode);
287 if (ts_ptr->x >= floor_ptr->width - 1)
288 ts_ptr->x = floor_ptr->width - 2;
289 else if (ts_ptr->x <= 0)
292 if (ts_ptr->y >= floor_ptr->height - 1)
293 ts_ptr->y = floor_ptr->height - 2;
294 else if (ts_ptr->y <= 0)
299 static bool set_target_grid(player_type *creature_ptr, ts_type *ts_ptr)
301 if (!ts_ptr->flag || (tmp_pos.n == 0))
304 describe_projectablity(creature_ptr, ts_ptr);
306 ts_ptr->query = examine_grid(creature_ptr, ts_ptr->y, ts_ptr->x, ts_ptr->mode, ts_ptr->info);
312 switch_target_input(creature_ptr, ts_ptr);
313 if (ts_ptr->distance == 0)
316 ts_ptr->y2 = panel_row_min;
317 ts_ptr->x2 = panel_col_min;
318 ts_ptr->target_num = target_pick(tmp_pos.y[ts_ptr->m], tmp_pos.x[ts_ptr->m], ddy[ts_ptr->distance], ddx[ts_ptr->distance]);
319 sweep_targets(creature_ptr, ts_ptr);
320 ts_ptr->m = ts_ptr->target_num;
324 static void describe_grid_wizard(player_type *creature_ptr, ts_type *ts_ptr)
330 sprintf(cheatinfo, " LOS:%d, PROJECTABLE:%d, SPECIAL:%d", los(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x),
331 projectable(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x), ts_ptr->g_ptr->special);
332 strcat(ts_ptr->info, cheatinfo);
335 static void switch_next_grid_command(player_type *creature_ptr, ts_type *ts_ptr)
337 switch (ts_ptr->query) {
347 target_row = ts_ptr->y;
348 target_col = ts_ptr->x;
352 verify_panel(creature_ptr);
353 creature_ptr->update |= PU_MONSTERS;
354 creature_ptr->redraw |= PR_MAP;
355 creature_ptr->window_flags |= PW_OVERHEAD;
356 handle_stuff(creature_ptr);
357 target_set_prepare(creature_ptr, ts_ptr->mode);
358 ts_ptr->y = creature_ptr->y;
359 ts_ptr->x = creature_ptr->x;
361 // todo ↑元からbreakしていないがFall Throughを付けてよいか不明なので保留
371 for (int i = 0; i < tmp_pos.n; i++) {
372 int t = distance(ts_ptr->y, ts_ptr->x, tmp_pos.y[i], tmp_pos.x[i]);
380 ts_ptr->flag = FALSE;
385 ts_ptr->distance = get_keymap_dir(ts_ptr->query);
386 if (isupper(ts_ptr->query))
387 ts_ptr->move_fast = TRUE;
389 if (!ts_ptr->distance)
396 static void decide_change_panel(player_type *creature_ptr, ts_type *ts_ptr)
398 if (ts_ptr->distance == 0)
401 POSITION dx = ddx[ts_ptr->distance];
402 POSITION dy = ddy[ts_ptr->distance];
403 if (ts_ptr->move_fast) {
404 int mag = MIN(ts_ptr->wid / 2, ts_ptr->hgt / 2);
405 ts_ptr->x += dx * mag;
406 ts_ptr->y += dy * mag;
412 if (((ts_ptr->x < panel_col_min + ts_ptr->wid / 2) && (dx > 0)) || ((ts_ptr->x > panel_col_min + ts_ptr->wid / 2) && (dx < 0)))
415 if (((ts_ptr->y < panel_row_min + ts_ptr->hgt / 2) && (dy > 0)) || ((ts_ptr->y > panel_row_min + ts_ptr->hgt / 2) && (dy < 0)))
418 if ((ts_ptr->y >= panel_row_min + ts_ptr->hgt) || (ts_ptr->y < panel_row_min) || (ts_ptr->x >= panel_col_min + ts_ptr->wid)
419 || (ts_ptr->x < panel_col_min)) {
420 if (change_panel(creature_ptr, dy, dx))
421 target_set_prepare(creature_ptr, ts_ptr->mode);
424 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
425 if (ts_ptr->x >= floor_ptr->width - 1)
426 ts_ptr->x = floor_ptr->width - 2;
427 else if (ts_ptr->x <= 0)
430 if (ts_ptr->y >= floor_ptr->height - 1)
431 ts_ptr->y = floor_ptr->height - 2;
432 else if (ts_ptr->y <= 0)
436 static void sweep_target_grids(player_type *creature_ptr, ts_type *ts_ptr)
438 while (!ts_ptr->done) {
439 if (set_target_grid(creature_ptr, ts_ptr))
442 ts_ptr->move_fast = FALSE;
443 if ((ts_ptr->mode & TARGET_LOOK) == 0)
444 print_path(creature_ptr, ts_ptr->y, ts_ptr->x);
446 ts_ptr->g_ptr = &creature_ptr->current_floor_ptr->grid_array[ts_ptr->y][ts_ptr->x];
447 strcpy(ts_ptr->info, _("q止 t決 p自 m近 +次 -前", "q,t,p,m,+,-,<dir>"));
448 describe_grid_wizard(creature_ptr, ts_ptr);
450 /* Describe and Prompt (enable "TARGET_LOOK") */
451 while ((ts_ptr->query = examine_grid(creature_ptr, ts_ptr->y, ts_ptr->x, ts_ptr->mode | TARGET_LOOK, ts_ptr->info)) == 0)
454 ts_ptr->distance = 0;
455 if (use_menu && (ts_ptr->query == '\r'))
458 switch_next_grid_command(creature_ptr, ts_ptr);
459 decide_change_panel(creature_ptr, ts_ptr);
464 * Handle "target" and "look".
466 bool target_set(player_type *creature_ptr, target_type mode)
469 ts_type *ts_ptr = initialize_target_set_type(creature_ptr, &tmp_ts, mode);
471 target_set_prepare(creature_ptr, mode);
472 sweep_target_grids(creature_ptr, ts_ptr);
475 verify_panel(creature_ptr);
476 creature_ptr->update |= (PU_MONSTERS);
477 creature_ptr->redraw |= (PR_MAP);
478 creature_ptr->window_flags |= (PW_OVERHEAD);
479 handle_stuff(creature_ptr);
480 return target_who != 0;