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/floor.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/target-checker.h"
17 #include "target/target-describer.h"
18 #include "target/target-preparation.h"
19 #include "target/target-types.h"
20 #include "term/screen-processor.h"
21 #include "util/int-char-converter.h"
22 #include "window/main-window-util.h"
25 typedef struct ts_type {
43 static ts_type *initialize_target_set_type(player_type *creature_ptr, ts_type *ts_ptr, target_type mode)
46 ts_ptr->y = creature_ptr->y;
47 ts_ptr->x = creature_ptr->x;
50 get_screen_size(&ts_ptr->wid, &ts_ptr->hgt);
56 * @brief フォーカスを当てるべきマップ描画の基準座標を指定する
57 * @param creature_ptr プレーヤーへの参照ポインタ
61 * Handle a request to change the current panel
62 * Return TRUE if the panel was changed.
63 * Also used in do_cmd_locate
64 * @return 実際に再描画が必要だった場合TRUEを返す
66 static bool change_panel_xy(player_type *creature_ptr, POSITION y, POSITION x)
68 POSITION dy = 0, dx = 0;
70 get_screen_size(&wid, &hgt);
71 if (y < panel_row_min)
74 if (y > panel_row_max)
77 if (x < panel_col_min)
80 if (x > panel_col_max)
86 return change_panel(creature_ptr, dy, dx);
90 * Help "select" a location (see below)
92 static POSITION_IDX target_pick(POSITION y1, POSITION x1, POSITION dy, POSITION dx)
94 POSITION_IDX b_i = -1, b_v = 9999;
95 for (POSITION_IDX i = 0; i < tmp_pos.n; i++) {
96 POSITION x2 = tmp_pos.x[i];
97 POSITION y2 = tmp_pos.y[i];
98 POSITION x3 = (x2 - x1);
99 POSITION y3 = (y2 - y1);
100 if (dx && (x3 * dx <= 0))
103 if (dy && (y3 * dy <= 0))
106 POSITION x4 = ABS(x3);
107 POSITION y4 = ABS(y3);
108 if (dy && !dx && (x4 > y4))
111 if (dx && !dy && (y4 > x4))
114 POSITION_IDX v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
115 if ((b_i >= 0) && (v >= b_v))
125 static void describe_projectablity(player_type *creature_ptr, ts_type *ts_ptr)
127 ts_ptr->y = tmp_pos.y[ts_ptr->m];
128 ts_ptr->x = tmp_pos.x[ts_ptr->m];
129 change_panel_xy(creature_ptr, ts_ptr->y, ts_ptr->x);
130 if ((ts_ptr->mode & TARGET_LOOK) == 0)
131 print_path(creature_ptr, ts_ptr->y, ts_ptr->x);
133 ts_ptr->g_ptr = &creature_ptr->current_floor_ptr->grid_array[ts_ptr->y][ts_ptr->x];
134 if (target_able(creature_ptr, ts_ptr->g_ptr->m_idx))
135 strcpy(ts_ptr->info, _("q止 t決 p自 o現 +次 -前", "q,t,p,o,+,-,<dir>"));
137 strcpy(ts_ptr->info, _("q止 p自 o現 +次 -前", "q,p,o,+,-,<dir>"));
143 sprintf(cheatinfo, " LOS:%d, PROJECTABLE:%d", los(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x),
144 projectable(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x));
145 strcat(ts_ptr->info, cheatinfo);
148 static void menu_target(ts_type *ts_ptr)
153 if (ts_ptr->query == '\r')
157 static void switch_target_input(player_type *creature_ptr, ts_type *ts_ptr)
159 ts_ptr->distance = 0;
160 switch (ts_ptr->query) {
169 if (!target_able(creature_ptr, ts_ptr->g_ptr->m_idx)) {
174 health_track(creature_ptr, ts_ptr->g_ptr->m_idx);
175 target_who = ts_ptr->g_ptr->m_idx;
176 target_row = ts_ptr->y;
177 target_col = ts_ptr->x;
183 if (++ts_ptr->m != tmp_pos.n)
192 if (ts_ptr->m-- != 0)
195 ts_ptr->m = tmp_pos.n - 1;
201 verify_panel(creature_ptr);
202 creature_ptr->update |= PU_MONSTERS;
203 creature_ptr->redraw |= PR_MAP;
204 creature_ptr->window |= PW_OVERHEAD;
205 handle_stuff(creature_ptr);
206 target_set_prepare(creature_ptr, ts_ptr->mode);
207 ts_ptr->y = creature_ptr->y;
208 ts_ptr->x = creature_ptr->x;
212 ts_ptr->flag = FALSE;
217 const char queried_command = rogue_like_commands ? 'x' : 'l';
218 if (ts_ptr->query != queried_command) {
219 ts_ptr->distance = get_keymap_dir(ts_ptr->query);
220 if (ts_ptr->distance == 0)
226 if (++ts_ptr->m != tmp_pos.n)
238 static bool check_panel_changed(player_type *creature_ptr, ts_type *ts_ptr)
240 if (!change_panel(creature_ptr, ddy[ts_ptr->distance], ddx[ts_ptr->distance]))
243 int v = tmp_pos.y[ts_ptr->m];
244 int u = tmp_pos.x[ts_ptr->m];
245 target_set_prepare(creature_ptr, ts_ptr->mode);
247 ts_ptr->target_num = target_pick(v, u, ddy[ts_ptr->distance], ddx[ts_ptr->distance]);
248 if (ts_ptr->target_num >= 0)
249 ts_ptr->m = ts_ptr->target_num;
254 static void sweep_targets(player_type *creature_ptr, ts_type *ts_ptr)
256 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
257 while (ts_ptr->flag && (ts_ptr->target_num < 0)) {
258 if (check_panel_changed(creature_ptr, ts_ptr))
261 POSITION dx = ddx[ts_ptr->distance];
262 POSITION dy = ddy[ts_ptr->distance];
263 panel_row_min = ts_ptr->y2;
264 panel_col_min = ts_ptr->x2;
265 panel_bounds_center();
266 creature_ptr->update |= PU_MONSTERS;
267 creature_ptr->redraw |= PR_MAP;
268 creature_ptr->window |= PW_OVERHEAD;
269 handle_stuff(creature_ptr);
270 target_set_prepare(creature_ptr, ts_ptr->mode);
271 ts_ptr->flag = FALSE;
274 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)))
277 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)))
280 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)
281 || (ts_ptr->x < panel_col_min)) {
282 if (change_panel(creature_ptr, dy, dx))
283 target_set_prepare(creature_ptr, ts_ptr->mode);
286 if (ts_ptr->x >= floor_ptr->width - 1)
287 ts_ptr->x = floor_ptr->width - 2;
288 else if (ts_ptr->x <= 0)
291 if (ts_ptr->y >= floor_ptr->height - 1)
292 ts_ptr->y = floor_ptr->height - 2;
293 else if (ts_ptr->y <= 0)
298 static bool set_target_grid(player_type *creature_ptr, ts_type *ts_ptr)
300 if (!ts_ptr->flag || (tmp_pos.n == 0))
303 describe_projectablity(creature_ptr, ts_ptr);
305 ts_ptr->query = examine_grid(creature_ptr, ts_ptr->y, ts_ptr->x, ts_ptr->mode, ts_ptr->info);
311 switch_target_input(creature_ptr, ts_ptr);
312 if (ts_ptr->distance == 0)
315 ts_ptr->y2 = panel_row_min;
316 ts_ptr->x2 = panel_col_min;
317 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]);
318 sweep_targets(creature_ptr, ts_ptr);
319 ts_ptr->m = ts_ptr->target_num;
323 static void describe_grid_wizard(player_type *creature_ptr, ts_type *ts_ptr)
329 sprintf(cheatinfo, " LOS:%d, PROJECTABLE:%d, SPECIAL:%d", los(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x),
330 projectable(creature_ptr, creature_ptr->y, creature_ptr->x, ts_ptr->y, ts_ptr->x), ts_ptr->g_ptr->special);
331 strcat(ts_ptr->info, cheatinfo);
334 static void switch_next_grid_command(player_type *creature_ptr, ts_type *ts_ptr)
336 switch (ts_ptr->query) {
346 target_row = ts_ptr->y;
347 target_col = ts_ptr->x;
351 verify_panel(creature_ptr);
352 creature_ptr->update |= PU_MONSTERS;
353 creature_ptr->redraw |= PR_MAP;
354 creature_ptr->window |= PW_OVERHEAD;
355 handle_stuff(creature_ptr);
356 target_set_prepare(creature_ptr, ts_ptr->mode);
357 ts_ptr->y = creature_ptr->y;
358 ts_ptr->x = creature_ptr->x;
360 // todo ↑元からbreakしていないがFall Throughを付けてよいか不明なので保留
370 for (int i = 0; i < tmp_pos.n; i++) {
371 int t = distance(ts_ptr->y, ts_ptr->x, tmp_pos.y[i], tmp_pos.x[i]);
379 ts_ptr->flag = FALSE;
384 ts_ptr->distance = get_keymap_dir(ts_ptr->query);
385 if (isupper(ts_ptr->query))
386 ts_ptr->move_fast = TRUE;
388 if (!ts_ptr->distance)
395 static void decide_change_panel(player_type *creature_ptr, ts_type *ts_ptr)
397 if (ts_ptr->distance == 0)
400 POSITION dx = ddx[ts_ptr->distance];
401 POSITION dy = ddy[ts_ptr->distance];
402 if (ts_ptr->move_fast) {
403 int mag = MIN(ts_ptr->wid / 2, ts_ptr->hgt / 2);
404 ts_ptr->x += dx * mag;
405 ts_ptr->y += dy * mag;
411 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)))
414 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)))
417 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)
418 || (ts_ptr->x < panel_col_min)) {
419 if (change_panel(creature_ptr, dy, dx))
420 target_set_prepare(creature_ptr, ts_ptr->mode);
423 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
424 if (ts_ptr->x >= floor_ptr->width - 1)
425 ts_ptr->x = floor_ptr->width - 2;
426 else if (ts_ptr->x <= 0)
429 if (ts_ptr->y >= floor_ptr->height - 1)
430 ts_ptr->y = floor_ptr->height - 2;
431 else if (ts_ptr->y <= 0)
435 static void sweep_target_grids(player_type *creature_ptr, ts_type *ts_ptr)
437 while (!ts_ptr->done) {
438 if (set_target_grid(creature_ptr, ts_ptr))
441 ts_ptr->move_fast = FALSE;
442 if ((ts_ptr->mode & TARGET_LOOK) == 0)
443 print_path(creature_ptr, ts_ptr->y, ts_ptr->x);
445 ts_ptr->g_ptr = &creature_ptr->current_floor_ptr->grid_array[ts_ptr->y][ts_ptr->x];
446 strcpy(ts_ptr->info, _("q止 t決 p自 m近 +次 -前", "q,t,p,m,+,-,<dir>"));
447 describe_grid_wizard(creature_ptr, ts_ptr);
449 /* Describe and Prompt (enable "TARGET_LOOK") */
450 while ((ts_ptr->query = examine_grid(creature_ptr, ts_ptr->y, ts_ptr->x, ts_ptr->mode | TARGET_LOOK, ts_ptr->info)) == 0)
453 ts_ptr->distance = 0;
454 if (use_menu && (ts_ptr->query == '\r'))
457 switch_next_grid_command(creature_ptr, ts_ptr);
458 decide_change_panel(creature_ptr, ts_ptr);
463 * Handle "target" and "look".
465 bool target_set(player_type *creature_ptr, target_type mode)
468 ts_type *ts_ptr = initialize_target_set_type(creature_ptr, &tmp_ts, mode);
470 target_set_prepare(creature_ptr, mode);
471 sweep_target_grids(creature_ptr, ts_ptr);
474 verify_panel(creature_ptr);
475 creature_ptr->update |= (PU_MONSTERS);
476 creature_ptr->redraw |= (PR_MAP);
477 creature_ptr->window |= (PW_OVERHEAD);
478 handle_stuff(creature_ptr);
479 return target_who != 0;