Freeciv-3.3
Loading...
Searching...
No Matches
goto.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <string.h>
19
20/* utility */
21#include "log.h"
22#include "mem.h"
23
24/* common */
25#include "game.h"
26#include "map.h"
27#include "movement.h"
28#include "packets.h"
29#include "pf_tools.h"
30#include "road.h"
31#include "unit.h"
32#include "unitlist.h"
33
34/* client/include */
35#include "client_main.h"
36#include "control.h"
37#include "mapview_g.h"
38
39/* client */
40#include "goto.h"
41#include "mapctrl_common.h"
42
43#define LOG_GOTO_PATH LOG_DEBUG
44#define log_goto_path log_debug
45#define log_goto_packet log_debug
46
47/*
48 * The whole path is separated by waypoints into parts. Each part has its
49 * own starting position and requires its own map. When the unit is unable
50 * to move, end_tile equals start_tile and path is nullptr.
51 */
52struct part {
55 struct pf_path *path;
56 struct pf_map *map;
57};
58
59struct goto_map {
60 struct unit *focus;
61 struct part *parts;
63 union {
64 struct {
66 } connect;
67 struct {
69 } patrol;
70 };
72};
73
74/* Get 'struct goto_map_list' and related functions: */
75#define SPECLIST_TAG goto_map
76#define SPECLIST_TYPE struct goto_map
77#include "speclist.h"
78#define goto_map_list_iterate(gotolist, pgoto) \
79 TYPED_LIST_ITERATE(struct goto_map, gotolist, pgoto)
80#define goto_map_list_iterate_end \
81 LIST_ITERATE_END
82
83/* Iterate over goto maps, assumes no dead units. */
84#define goto_map_unit_iterate(gotolist, pgoto, punit) \
85 goto_map_list_iterate(gotolist, pgoto) { \
86 struct unit *punit = goto_map_unit(pgoto);
87
88#define goto_map_unit_iterate_end \
89 } goto_map_list_iterate_end;
90
91static struct goto_map_list *goto_maps = nullptr;
92static bool goto_warned = FALSE;
93
94static void reset_last_part(struct goto_map *goto_map);
95static void remove_last_part(struct goto_map *goto_map);
96static void fill_parameter_part(struct pf_parameter *param,
97 const struct goto_map *goto_map,
98 const struct part *p);
99
100/****************************************************************************
101 Various stuff for the goto routes
102****************************************************************************/
103static struct tile *goto_destination = nullptr;
104
105/************************************************************************/
108static struct goto_map *goto_map_new(struct unit *punit)
109{
110 struct goto_map *goto_map = fc_malloc(sizeof(*goto_map));
111
113 goto_map->parts = nullptr;
114 goto_map->num_parts = 0;
115
116 return goto_map;
117}
118
119/************************************************************************/
122static void goto_map_free(struct goto_map *goto_map)
123{
124 if (goto_map->parts != nullptr) {
125 while (goto_map->num_parts > 0) {
127 }
129 }
132 }
133 free(goto_map);
134}
135
136/************************************************************************/
139static struct unit *goto_map_unit(const struct goto_map *goto_map)
140{
141 struct unit *punit = goto_map->focus;
142
143 fc_assert(punit != nullptr);
146
147 return punit;
148}
149
150/************************************************************************/
154{
156
158}
159
160/************************************************************************/
164{
165 if (goto_maps != nullptr) {
170 goto_maps = nullptr;
171 }
172
173 goto_destination = nullptr;
175}
176
177/************************************************************************/
180bool is_valid_goto_destination(const struct tile *ptile)
181{
182 return (goto_destination != nullptr && ptile == goto_destination);
183}
184
185/************************************************************************/
188static void goto_path_redraw(const struct pf_path *new_path,
189 const struct pf_path *old_path)
190{
191 int start_index = 0;
192 int i;
193
194 fc_assert_ret(new_path != nullptr);
195
196 if (old_path != nullptr) {
197 /* We had a path drawn already. Determine how much of it we can reuse
198 * in drawing the new path. */
199 for (i = 0; i < new_path->length - 1 && i < old_path->length - 1; i++) {
200 struct pf_position *old_pos = old_path->positions + i;
201 struct pf_position *new_pos = new_path->positions + i;
202
203 if (old_pos->dir_to_next_pos != new_pos->dir_to_next_pos
204 || old_pos->tile != new_pos->tile) {
205 break;
206 }
207 }
208 start_index = i;
209
210 /* Erase everything we cannot reuse. */
211 for (; i < old_path->length - 1; i++) {
212 struct pf_position *pos = old_path->positions + i;
213
214 if (is_valid_dir(pos->dir_to_next_pos)) {
215 mapdeco_remove_gotoline(pos->tile, pos->dir_to_next_pos);
216 } else {
217 fc_assert(pos->tile == (pos + 1)->tile);
218 }
219 }
220 }
221
222 /* Draw the new path. */
223 for (i = start_index; i < new_path->length - 1; i++) {
224 struct pf_position *pos = new_path->positions + i;
225
226 if (is_valid_dir(pos->dir_to_next_pos)) {
227 mapdeco_add_gotoline(pos->tile, pos->dir_to_next_pos);
228 } else {
229 fc_assert(pos->tile == (pos + 1)->tile);
230 }
231 }
232}
233
234/************************************************************************/
237static void goto_path_undraw(const struct pf_path *path)
238{
239 int i;
240
241 fc_assert_ret(path != nullptr);
242
243 for (i = 0; i < path->length - 1; i++) {
244 struct pf_position *pos = path->positions + i;
245
246 if (is_valid_dir(pos->dir_to_next_pos)) {
247 mapdeco_remove_gotoline(pos->tile, pos->dir_to_next_pos);
248 } else {
249 fc_assert(pos->tile == (pos + 1)->tile);
250 }
251 }
252}
253
254/************************************************************************/
260 struct tile *ptile)
261{
262 struct pf_path *old_path, *new_path;
263 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
264
265 old_path = p->path;
266 if (old_path != nullptr && pf_path_last_position(old_path)->tile == ptile) {
267 /* Nothing to update. */
268 return TRUE;
269 }
270
271 log_debug("update_last_part(%d,%d) old (%d,%d)-(%d,%d)",
272 TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
273 new_path = pf_map_path(p->map, ptile);
274
275 if (!new_path) {
276 log_goto_path(" no path found");
277
278 if (p->start_tile == ptile) {
279 /* This mean we cannot reach the start point. It is probably,
280 * a path-finding bug, but don't make infinite recursion. */
281
282 if (!goto_warned) {
283 log_error("No path found to reach the start point.");
285 }
286
287 if (old_path != nullptr) {
290 p->path = nullptr;
291 }
293 && goto_map->patrol.return_path != nullptr) {
296 goto_map->patrol.return_path = nullptr;
297 }
298 return FALSE;
299 }
300
302 return FALSE;
303 }
304
305 log_goto_path(" path found:");
307
308 p->path = new_path;
309 p->end_tile = ptile;
312
313 if (hover_state == HOVER_PATROL) {
314 struct pf_parameter parameter;
315 struct pf_map *pfm;
316 struct pf_path *return_path;
317
318 fill_parameter_part(&parameter, goto_map, p);
319 pfm = pf_map_new(&parameter);
320 return_path = pf_map_path(pfm, goto_map->parts[0].start_tile);
322
323 if (return_path == nullptr) {
324 log_goto_path(" no return path found");
325
326 if (p->start_tile == ptile) {
327 /* This mean we cannot reach the start point. It is probably,
328 * a path-finding bug, but don't make infinite recursion. */
329
330 if (!goto_warned) {
331 log_error("No path found to reach the start point.");
333 }
334
335 if (old_path != nullptr) {
338 }
340 p->path = nullptr;
341 if (goto_map->patrol.return_path != nullptr) {
344 goto_map->patrol.return_path = nullptr;
345 }
346 return FALSE;
347 }
348
349 p->path = old_path;
350
351 if (p->path != nullptr) {
353
354 p->end_tile = pos->tile;
355 p->end_moves_left = pos->moves_left;
356 p->end_fuel_left = pos->fuel_left;
357 }
358
361
362 return FALSE;
363 }
364
365 log_goto_path(" returned path found:");
366 pf_path_print(return_path, LOG_GOTO_PATH);
367
368 if (goto_map->patrol.return_path != nullptr) {
369 /* We cannot reuse old path because:
370 * 1- the start tile isn't the same.
371 * 2- the turn number neither (impossible to do in backward mode). */
374 }
375 goto_path_redraw(return_path, nullptr);
376 goto_map->patrol.return_path = return_path;
377 }
378
381
382 log_goto_path("To (%d,%d) part %d: total_MC: %d",
383 TILE_XY(ptile), goto_map->num_parts,
386 : new_path)->total_MC);
387
388 return TRUE;
389}
390
391/************************************************************************/
396{
397 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
398
399 if (p->path != nullptr) {
400 /* Otherwise no need to update */
402 }
403}
404
405/************************************************************************/
408static void fill_parameter_part(struct pf_parameter *param,
409 const struct goto_map *goto_map,
410 const struct part *p)
411{
412 *param = goto_map->template;
413
414 if (p->start_tile == p->end_tile) {
415 /* Copy is enough, we didn't move last part. */
416 fc_assert(p->path->length == 1);
417 return;
418 }
419
420 param->start_tile = p->end_tile;
423 if (can_exist_at_tile(&(wld.map), param->utype, param->start_tile)) {
424 param->transported_by_initially = nullptr;
425 } else {
426 const struct unit *transporter =
428
429 param->transported_by_initially = (transporter != nullptr
430 ? unit_type_get(transporter) : nullptr);
431 }
432}
433
434/************************************************************************/
439static void add_part(struct goto_map *goto_map)
440{
441 struct part *p;
442 struct pf_parameter parameter;
443 struct unit *punit = goto_map_unit(goto_map);
444
446 goto_map->parts =
448 goto_map->num_parts * sizeof(*goto_map->parts));
449 p = &goto_map->parts[goto_map->num_parts - 1];
450
451 if (goto_map->num_parts == 1) {
452 /* First part */
454 parameter = goto_map->template;
455 } else {
456 struct part *prev = &goto_map->parts[goto_map->num_parts - 2];
457
458 p->start_tile = prev->end_tile;
459 fill_parameter_part(&parameter, goto_map, prev);
460 }
461
462 p->path = nullptr;
463 p->end_tile = p->start_tile;
464 parameter.start_tile = p->start_tile;
465 p->map = pf_map_new(&parameter);
466}
467
468/************************************************************************/
472{
473 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
474
476
478 if (p->path) {
479 /* We do not always have a path */
481 }
484}
485
486/************************************************************************/
490{
491 bool duplicate_of_last = TRUE;
492
494
495 if (goto_destination == nullptr) {
496 /* Not a valid position. */
497 return FALSE;
498 }
499
501 const struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
502
503 if (last_part->path == nullptr) {
504 /* The current part has zero length. */
505 return FALSE;
506 }
507 if (last_part->start_tile != last_part->end_tile) {
509 }
511 if (duplicate_of_last) {
512 return FALSE;
513 }
514
518
520
521 return TRUE;
522}
523
524/************************************************************************/
529{
530 bool popped = FALSE;
531
533
535 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
536 struct tile *end_tile = p->end_tile;
537
538 if (goto_map->num_parts == 1) {
539 /* We don't have any waypoint but the start pos. */
540 continue;
541 }
542 popped = TRUE;
543
545
546 /*
547 * Set the end position of the previous part (now the last) to the
548 * end position of the last part (now gone). I.e. redraw a line to
549 * the mouse position.
550 */
551 update_last_part(goto_map, end_tile);
553
554 return popped;
555}
556
557/************************************************************************/
561static unsigned get_EC(const struct tile *ptile, enum known_type known,
562 const struct pf_parameter *param)
563{
564 return 1;
565}
566
567/************************************************************************/
571static enum tile_behavior get_TB_aggr(const struct tile *ptile,
572 enum known_type known,
573 const struct pf_parameter *param)
574{
575 if (known == TILE_UNKNOWN) {
577 return TB_IGNORE;
578 }
579 } else if (is_non_allied_unit_tile(ptile, param->owner,
581 || is_non_allied_city_tile(ptile, param->owner)) {
582 /* Can attack but can't count on going through */
583 return TB_DONT_LEAVE;
584 }
585
586 return TB_NORMAL;
587}
588
589/************************************************************************/
593static enum tile_behavior get_TB_caravan(const struct tile *ptile,
594 enum known_type known,
595 const struct pf_parameter *param)
596{
597 if (known == TILE_UNKNOWN) {
599 return TB_IGNORE;
600 }
601 } else if (is_non_allied_city_tile(ptile, param->owner)) {
602 /* Units that can establish a trade route, enter a market place or
603 * establish an embassy can travel to, but not through, enemy cities.
604 * FIXME: ACTION_HELP_WONDER units cannot. */
605 return TB_DONT_LEAVE;
606 } else if (is_non_allied_unit_tile(ptile, param->owner,
608 /* Note this must be below the city check. */
609 return TB_IGNORE;
610 }
611
612 /* Includes empty, allied, or allied-city tiles. */
613 return TB_NORMAL;
614}
615
616/************************************************************************/
620static int get_activity_time(const struct tile *ptile,
621 const struct player *pplayer)
622{
623 struct terrain *pterrain = tile_terrain(ptile);
624 int activity_mc = 0;
625
627
628 switch (connect_activity) {
630 if (pterrain->irrigation_time == 0) {
631 return -1;
632 }
633 extra_type_iterate(pextra) {
635 && tile_has_extra(ptile, pextra)) {
636 /* Don't replace old extras. */
637 return -1;
638 }
640
641 if (tile_has_extra(ptile, connect_tgt)) {
642 break;
643 }
644
645 activity_mc = pterrain->irrigation_time;
646 break;
649
650 if (!tile_has_extra(ptile, connect_tgt)) {
651 struct tile *vtile;
652 int single_mc;
653
654 vtile = tile_virtual_new(ptile);
656 nullptr, pplayer, 0);
658
659 if (single_mc < 0) {
660 return -1;
661 }
662
664 }
665 break;
666 default:
667 log_error("Invalid connect activity: %d.", connect_activity);
668 }
669
670 return activity_mc;
671}
672
673/************************************************************************/
677static bool is_non_allied_city_adjacent(const struct player *pplayer,
678 const struct tile *ptile)
679{
680 adjc_iterate(&(wld.map), ptile, tile1) {
681 if (is_non_allied_city_tile(tile1, pplayer)) {
682 return TRUE;
683 }
685
686 return FALSE;
687}
688
689/************************************************************************/
698static int get_connect_road(const struct tile *src_tile, enum direction8 dir,
699 const struct tile *dest_tile,
700 int src_cost, int src_extra,
701 unsigned *dest_cost, unsigned *dest_extra,
702 const struct pf_parameter *param)
703{
704 int activity_time, move_cost, moves_left;
705 int total_cost, total_extra;
706 struct road_type *proad;
707
708 if (tile_get_known(dest_tile, param->owner) == TILE_UNKNOWN) {
709 return -1;
710 }
711
712 activity_time = get_activity_time(dest_tile, param->owner);
713 if (activity_time < 0) {
714 return -1;
715 }
716
717 move_cost = param->get_MC(src_tile, PF_MS_NATIVE, dest_tile, PF_MS_NATIVE,
718 param);
720 return -1;
721 }
722
723 if (is_non_allied_city_adjacent(param->owner, dest_tile)) {
724 /* We don't want to build roads to enemies plus get ZoC problems */
725 return -1;
726 }
727
729
731
732 if (proad == nullptr) {
733 /* No suitable road type available */
734 return -1;
735 }
736
737 /* Ok, the move is possible. What are the costs? */
738
739 /* Extra cost here is the final length of the road */
741
742 /* Special cases: get_MC function doesn't know that we would have built
743 * a road (railroad) on src tile by that time.
744 * We assume that settler building the road can also travel it. */
745 if (tile_has_road(dest_tile, proad)) {
746 move_cost = proad->move_cost;
747 }
748
749 move_cost = MIN(move_cost, param->move_rate);
750 total_cost = src_cost;
751 moves_left = param->move_rate - (src_cost % param->move_rate);
752 if (moves_left < move_cost) {
753 total_cost += moves_left;
754 } else {
755 total_cost += move_cost;
756 }
757
758 /* Now need to include the activity cost. If we have moves left, they
759 * will count as a full turn towards the activity time */
760 moves_left = param->move_rate - (total_cost % param->move_rate);
761 if (activity_time > 0) {
762 int speed = FC_PTR_TO_INT(param->data);
763
765 + (speed - 1)) / speed;
767 total_cost += moves_left;
768 }
769 total_cost += activity_time * param->move_rate;
770
771 /* Now we determine if we have found a better path. When building
772 * road type with positive move_cost, we care most about the length
773 * of the result. When building road type with move_cost 0, we
774 * care most about construction time. */
775
776 /* *dest_cost == -1 means we haven't reached dest until now */
777
778 if (*dest_cost != -1) {
779 if (proad->move_cost > 0) {
781 || (total_extra == *dest_extra && total_cost >= *dest_cost)) {
782 /* No, this path is worse than what we already have */
783 return -1;
784 }
785 } else {
786 if (total_cost > *dest_cost
787 || (total_cost == *dest_cost && total_extra >= *dest_extra)) {
788 return -1;
789 }
790 }
791 }
792
793 /* Ok, we found a better path! */
794 *dest_cost = total_cost;
796
797 return (proad->move_cost > 0 ?
798 total_extra * PF_TURN_FACTOR + total_cost :
799 total_cost * PF_TURN_FACTOR + total_extra);
800}
801
802/************************************************************************/
808static int get_connect_irrig(const struct tile *src_tile,
809 enum direction8 dir,
810 const struct tile *dest_tile,
811 int src_cost, int src_extra,
812 unsigned *dest_cost, unsigned *dest_extra,
813 const struct pf_parameter *param)
814{
815 int activity_time, move_cost, moves_left, total_cost;
816
817 if (tile_get_known(dest_tile, param->owner) == TILE_UNKNOWN) {
818 return -1;
819 }
820
821 activity_time = get_activity_time(dest_tile, param->owner);
822 if (activity_time < 0) {
823 return -1;
824 }
825
826 if (!is_cardinal_dir(dir)) {
827 return -1;
828 }
829
830 move_cost = param->get_MC(src_tile, PF_MS_NATIVE, dest_tile, PF_MS_NATIVE,
831 param);
833 return -1;
834 }
835
836 if (is_non_allied_city_adjacent(param->owner, dest_tile)) {
837 /* We don't want to build irrigation for enemies plus get ZoC problems */
838 return -1;
839 }
840
841 /* Ok, the move is possible. What are the costs? */
842
843 move_cost = MIN(move_cost, param->move_rate);
844 total_cost = src_cost;
845 moves_left = param->move_rate - (src_cost % param->move_rate);
846 if (moves_left < move_cost) {
847 total_cost += moves_left;
848 } else {
849 total_cost += move_cost;
850 }
851
852 /* Now need to include the activity cost. If we have moves left, they
853 * will count as a full turn towards the activity time */
854 moves_left = param->move_rate - (total_cost % param->move_rate);
855 if (activity_time > 0) {
856 int speed = FC_PTR_TO_INT(param->data);
857
859 + (speed - 1)) / speed;
861 total_cost += moves_left;
862 }
863 total_cost += activity_time * param->move_rate;
864
865 /* *dest_cost == -1 means we haven't reached dest until now */
866 if (*dest_cost != -1 && total_cost > *dest_cost) {
867 return -1;
868 }
869
870 /* Ok, we found a better path! */
871 *dest_cost = total_cost;
872 *dest_extra = 0;
873
874 return total_cost;
875}
876
877/************************************************************************/
881static enum tile_behavior
882no_fights_or_unknown_goto(const struct tile *ptile,
883 enum known_type known,
884 const struct pf_parameter *p)
885{
887 /* Special case allowing goto into the unknown. */
888 return TB_NORMAL;
889 }
890
891 return no_fights_or_unknown(ptile, known, p);
892}
893
894/************************************************************************/
898static void goto_fill_parameter_base(struct pf_parameter *parameter,
899 const struct unit *punit)
900{
901 pft_fill_unit_parameter(parameter, &(wld.map), punit);
902
903 fc_assert(parameter->get_EC == nullptr);
904 fc_assert(parameter->get_TB == nullptr);
905 fc_assert(parameter->get_MC != nullptr);
906 fc_assert(parameter->start_tile == unit_tile(punit));
907 fc_assert(!parameter->omniscience);
908
909 parameter->get_EC = get_EC;
911 parameter->get_TB = get_TB_aggr;
914 parameter->get_TB = get_TB_caravan;
915 } else {
917 }
918}
919
920/************************************************************************/
932 const struct unit *punit)
933{
934 struct pf_parameter *parameter = &goto_map->template;
935
937
939
940 switch (hover_state) {
941 case HOVER_CONNECT:
942 {
944 int speed;
945
947 parameter->get_costs = get_connect_irrig;
948 } else {
949 parameter->get_costs = get_connect_road;
950 }
951 parameter->get_moves_left_req = nullptr;
952
954 parameter->data = FC_INT_TO_PTR(speed);
955
956 /* Take into account the activity time at the origin */
959
960 if (activity_initial > 0) {
961 /* First action is activity */
962 parameter->moves_left_initially = parameter->move_rate;
963 /* Number of turns, rounding up */
966 if (punit->moves_left == 0) {
968 }
969 } else {
971 }
972 }
973 break;
974 case HOVER_GOTO:
975 case HOVER_PATROL:
978 /* TODO: consider doing the same for other actor consuming actions. */
979 /* We only want targets reachable immediately... */
980 parameter->move_rate = 0;
981 /* ...then we don't need to deal with dangers or refuel points. */
982 parameter->is_pos_dangerous = nullptr;
983 parameter->get_moves_left_req = nullptr;
984 } else {
985 goto_map->patrol.return_path = nullptr;
986 }
987 break;
990 "Path finding during target selection");
991 break;
992 case HOVER_TELEPORT:
993 fc_assert_msg(hover_state != HOVER_TELEPORT, "Goto with HOVER_TELEPORT?");
994 break;
995 case HOVER_NONE:
996 case HOVER_PARADROP:
998 fc_assert_msg(hover_state != HOVER_NONE, "Goto with HOVER_NONE?");
1000 "Goto with HOVER_PARADROP?");
1002 "Goto with HOVER_ACT_SEL_TGT?");
1003 break;
1004 };
1005}
1006
1007/************************************************************************/
1011void enter_goto_state(struct unit_list *punits)
1012{
1014
1015 /* Can't have selection rectangle and goto going on at the same time. */
1017
1020
1022
1026
1028}
1029
1030/************************************************************************/
1034{
1035 if (!goto_is_active()) {
1036 return;
1037 }
1038
1043
1044 goto_destination = nullptr;
1046}
1047
1048/************************************************************************/
1052{
1053 if (!goto_is_active()) {
1054 return;
1055 }
1056
1058 if (ptest == punit) {
1061 /* Stop now, links are gone! */
1062 break;
1063 }
1065}
1066
1067/************************************************************************/
1071{
1072 return (goto_maps != nullptr && 0 != goto_map_list_size(goto_maps));
1073}
1074
1075/************************************************************************/
1079bool goto_get_turns(int *min, int *max)
1080{
1081 fc_assert_ret_val(min != nullptr, FALSE);
1082 fc_assert_ret_val(max != nullptr, FALSE);
1083
1084 *min = FC_INFINITY;
1085 *max = -1;
1086
1087 if (!goto_is_active()) {
1088 return FALSE;
1089 }
1090
1091 if (goto_destination == nullptr) {
1092 /* Not a valid position. */
1093 return FALSE;
1094 }
1095
1096 if (hover_state == HOVER_CONNECT) {
1097 /* In connect mode, we want to know the turn number the activity will
1098 * be finished. */
1100
1102 bool moved = FALSE;
1103 int turns = goto_map->connect.initial_turns;
1104 int i;
1105
1106 for (i = 0; i < goto_map->num_parts; i++) {
1107 const struct pf_path *path = goto_map->parts[i].path;
1108
1110 if (!moved && path->length > 1) {
1111 moved = TRUE;
1112 }
1113 }
1114
1115 if (moved && activity_time > 0) {
1116 turns++;
1117 }
1118
1119 if (turns < *min) {
1120 *min = turns;
1121 }
1122 if (turns > *max) {
1123 *max = turns;
1124 }
1126 } else {
1127 /* In other modes, we want to know the turn number to reach the tile. */
1129 int turns = 0;
1130 int i;
1131
1132 for (i = 0; i < goto_map->num_parts; i++) {
1134 }
1136 && goto_map->patrol.return_path != nullptr) {
1138 }
1139
1140 if (turns < *min) {
1141 *min = turns;
1142 }
1143 if (turns > *max) {
1144 *max = turns;
1145 }
1147 }
1148
1149 return TRUE;
1150}
1151
1152/************************************************************************/
1156bool goto_tile_state(const struct tile *ptile, enum goto_tile_state *state,
1157 int *turns, bool *waypoint)
1158{
1159 fc_assert_ret_val(ptile != nullptr, FALSE);
1160 fc_assert_ret_val(turns != nullptr, FALSE);
1161 fc_assert_ret_val(waypoint != nullptr, FALSE);
1162
1163 if (!goto_is_active()) {
1164 return FALSE;
1165 }
1166
1167 *state = -1;
1168 *turns = -1;
1169 *waypoint = FALSE;
1170
1171 if (hover_state == HOVER_CONNECT) {
1172 /* In connect mode, we want to know the turn number the activity will
1173 * be finished. */
1174 int activity_time;
1175
1176 if (tile_get_known(ptile, client_player()) == TILE_UNKNOWN) {
1177 return FALSE; /* We never connect on unknown tiles. */
1178 }
1179
1181
1183 const struct pf_path *path;
1184 const struct pf_position *pos = nullptr; /* Keep compiler happy! */
1186 int turns_for_map = -2;
1187 bool moved = FALSE;
1188 int i, j;
1189
1190 for (i = 0; i < goto_map->num_parts; i++) {
1191 if (i > 0 && goto_map->parts[i].start_tile == ptile) {
1192 *waypoint = TRUE;
1193 }
1194
1195 path = goto_map->parts[i].path;
1196 if (path == nullptr || path->length == 0) {
1197 continue;
1198 }
1199
1200 for (j = 0; j < path->length; j++) {
1201 pos = path->positions + j;
1202 if (!moved && j > 0) {
1203 moved = TRUE;
1204 }
1205 if (pos->tile != ptile) {
1206 continue;
1207 }
1208 if (activity_time > 0) {
1209 if (map_turns + pos->turn + moved > turns_for_map) {
1210 turns_for_map = map_turns + pos->turn + moved;
1211 }
1212 } else if (pos->moves_left == 0) {
1213 if (map_turns + pos->turn > turns_for_map) {
1214 turns_for_map = map_turns + pos->turn + moved;
1215 }
1216 }
1217 }
1218 map_turns += pos->turn;
1219 }
1220
1221 if (ptile == goto_destination) {
1222 int ml = (pos != nullptr ? pos->moves_left : 0);
1223
1224 if (moved && activity_time > 0) {
1225 map_turns++;
1226 }
1227 if (map_turns > *turns) {
1228 *state = (activity_time > 0 || ml == 0
1230 *turns = map_turns;
1231 } else if (map_turns == *turns
1232 && *state == GTS_MP_LEFT
1233 && (activity_time > 0 || ml == 0)) {
1234 *state = GTS_EXHAUSTED_MP;
1235 }
1236 } else {
1237 if (activity_time > 0) {
1238 if (turns_for_map > *turns) {
1239 *state = GTS_TURN_STEP;
1240 *turns = turns_for_map;
1241 }
1242 } else {
1243 if (turns_for_map + 1 > *turns) {
1244 *state = GTS_TURN_STEP;
1245 *turns = turns_for_map + 1;
1246 }
1247 }
1248 }
1250 } else {
1251 bool mark_on_map = FALSE;
1252
1253 /* In other modes, we want to know the turn number to reach the tile. */
1255 const struct tile *destination;
1256 const struct pf_path *path;
1257 const struct pf_position *pos = nullptr; /* Keep compiler happy! */
1258 const struct pf_position *last_pos = nullptr;
1259 int map_turns = 0;
1260 int turns_for_map = -2;
1261 int i, j;
1262
1263 for (i = 0; i < goto_map->num_parts; i++) {
1264 if (i > 0 && goto_map->parts[i].start_tile == ptile) {
1265 mark_on_map = *waypoint = TRUE;
1266 }
1267
1268 path = goto_map->parts[i].path;
1269 if (path == nullptr || path->length == 0) {
1270 continue;
1271 }
1272 last_pos = path->positions;
1273 for (j = 0; j < path->length; j++) {
1274 pos = path->positions + j;
1275 /* turn to reach was increased in that step */
1276 if (pos->turn != last_pos->turn
1277 && pos->tile == ptile) {
1278 mark_on_map = TRUE;
1279 }
1280 if (pos->moves_left == 0 && last_pos->moves_left != 0
1281 && pos->tile == ptile) {
1282 mark_on_map = TRUE;
1283 }
1284 if (pos->tile == ptile
1285 /* End turn case. */
1286 && (pos->moves_left == 0
1287 /* Waiting case. */
1288 || (j < path->length - 1 && (pos + 1)->tile == ptile))
1289 && map_turns + pos->turn > turns_for_map) {
1290 turns_for_map = map_turns + pos->turn;
1291 }
1292 last_pos = pos;
1293 }
1294 map_turns += pos->turn;
1295 }
1296
1298 && goto_map->patrol.return_path != nullptr
1299 && goto_map->patrol.return_path->length > 0) {
1300 path = goto_map->patrol.return_path;
1301
1302 for (j = 0; j < path->length; j++) {
1303 pos = path->positions + j;
1304 if (pos->tile == ptile
1305 /* End turn case. */
1306 && (pos->moves_left == 0
1307 /* Waiting case. */
1308 || (j < path->length - 1 && (pos + 1)->tile == ptile))
1309 && map_turns + pos->turn > turns_for_map) {
1310 turns_for_map = map_turns + pos->turn;
1311 }
1312 }
1313 map_turns += pos->turn;
1314 destination = pos->tile;
1315 } else {
1317 }
1318
1319 if (ptile == destination) {
1320 int ml = (pos != nullptr ? pos->moves_left : 0);
1321
1322 if (map_turns > *turns) {
1323 mark_on_map = TRUE;
1324 *state = (ml == 0 ? GTS_EXHAUSTED_MP : GTS_MP_LEFT);
1325 *turns = map_turns;
1326 } else if (map_turns == *turns
1327 && *state == GTS_MP_LEFT
1328 && ml == 0) {
1329 *state = GTS_EXHAUSTED_MP;
1330 }
1331 } else {
1332 if (turns_for_map > *turns) {
1333 *state = GTS_TURN_STEP;
1334 *turns = turns_for_map;
1335 }
1336 }
1338
1339 return mark_on_map;
1340 }
1341
1342 return (*turns != -1 || *waypoint);
1343}
1344
1345/************************************************************************/
1350bool is_valid_goto_draw_line(struct tile *dest_tile)
1351{
1353
1354 if (dest_tile == nullptr) {
1355 return FALSE;
1356 }
1357
1358 /* Assume valid destination */
1359 goto_destination = dest_tile;
1360
1362 if (!update_last_part(goto_map, dest_tile)) {
1363 goto_destination = nullptr;
1364 }
1366
1367 /* Update goto data in info label. */
1369
1370 return (goto_destination != nullptr);
1371}
1372
1373/************************************************************************/
1378{
1379 struct packet_unit_orders p;
1380
1381 if (!can_client_issue_orders()) {
1382 return;
1383 }
1384
1385 /* Clear the orders by sending an empty orders path. */
1386 log_goto_packet("Clearing orders for unit %d.", punit->id);
1387 p.unit_id = punit->id;
1389 p.repeat = p.vigilant = FALSE;
1390 p.length = 0;
1394}
1395
1396/************************************************************************/
1399static void make_path_orders(struct unit *punit, struct pf_path *path,
1400 enum unit_orders orders,
1401 struct unit_order *final_order,
1402 struct unit_order *order_list,
1403 int *length, int *dest_tile)
1404{
1405 int i;
1406 struct tile *old_tile;
1407
1408 fc_assert_ret(path != nullptr);
1410 "Unit %d has moved without goto cancellation.",
1411 punit->id);
1412 fc_assert_ret(length != nullptr);
1413
1414 /* We skip the start position. */
1415 *length = path->length - 1;
1416 fc_assert(*length < MAX_LEN_ROUTE);
1417 old_tile = path->positions[0].tile;
1418
1419 /* If the path has n positions it takes n-1 steps. */
1420 for (i = 0; i < path->length - 1; i++) {
1421 struct tile *new_tile = path->positions[i + 1].tile;
1422
1423 if (same_pos(new_tile, old_tile)) {
1424 order_list[i].order = ORDER_FULL_MP;
1425 order_list[i].dir = DIR8_ORIGIN;
1426 order_list[i].activity = ACTIVITY_LAST;
1427 order_list[i].target = NO_TARGET;
1428 order_list[i].sub_target = NO_TARGET;
1429 order_list[i].action = ACTION_NONE;
1430 log_goto_packet(" packet[%d] = wait: %d,%d", i, TILE_XY(old_tile));
1431 } else {
1432 order_list[i].order = orders;
1434 order_list[i].activity = ACTIVITY_LAST;
1435 order_list[i].target = NO_TARGET;
1436 order_list[i].sub_target = NO_TARGET;
1437 order_list[i].action = ACTION_NONE;
1438 log_goto_packet(" packet[%d] = move %s: %d,%d => %d,%d",
1439 i, dir_get_name(order_list[i].dir),
1441 }
1443 }
1444
1445 if (i > 0
1446 && order_list[i - 1].order == ORDER_MOVE) {
1447 struct player *cplayer = client_player();
1448
1452 /* Won't be able to perform a regular move to the target tile... */
1453 if (!final_order) {
1454 /* ...and no final order exists. Choose what to do when the unit gets
1455 * there. */
1456 order_list[i - 1].order = ORDER_ACTION_MOVE;
1457 } else {
1458 /* ...and a final order exist. Can't assume an action move. Did the
1459 * caller hope that the situation would change before the unit got
1460 * there? */
1461
1462 /* It's currently illegal to walk into tiles with non-allied units or
1463 * cities. Some actions causes the actor to enter the target tile but
1464 * that is a part of the action it self, not a regular pre action
1465 * move. */
1466 log_verbose("unit or city blocks the path of your %s",
1468 }
1469 }
1470 }
1471
1472 if (final_order) {
1473 /* Append the final order after moving to the target tile. */
1474 order_list[i].order = final_order->order;
1475 order_list[i].dir = final_order->dir;
1476 order_list[i].activity = (final_order->order == ORDER_ACTIVITY)
1477 ? final_order->activity : ACTIVITY_LAST;
1478 order_list[i].target = final_order->target;
1479 order_list[i].sub_target = final_order->sub_target;
1480 order_list[i].action = final_order->action;
1481 (*length)++;
1482 }
1483
1484 if (dest_tile) {
1485 *dest_tile = tile_index(old_tile);
1486 }
1487}
1488
1489/************************************************************************/
1492static void send_path_orders(struct unit *punit, struct pf_path *path,
1493 bool repeat, bool vigilant,
1494 enum unit_orders orders,
1495 struct unit_order *final_order)
1496{
1497 struct packet_unit_orders p;
1498
1499 if (path->length == 1 && final_order == nullptr) {
1500 return; /* No path at all, no need to spam the server. */
1501 }
1502
1503 memset(&p, 0, sizeof(p));
1504 p.unit_id = punit->id;
1506 p.repeat = repeat;
1507 p.vigilant = vigilant;
1508
1509 log_goto_packet("Orders for unit %d:", punit->id);
1510 log_goto_packet(" Repeat: %d. Vigilant: %d.",
1511 p.repeat, p.vigilant);
1512
1514 p.orders, &p.length, &p.dest_tile);
1515
1518}
1519
1520/************************************************************************/
1523static void send_rally_path_orders(struct city *pcity, struct unit *punit,
1524 struct pf_path *path, bool vigilant,
1525 bool persistent,
1526 enum unit_orders orders,
1527 struct unit_order *final_order)
1528{
1529 struct packet_city_rally_point p;
1530
1531 memset(&p, 0, sizeof(p));
1532 p.id = pcity->id;
1533 p.vigilant = vigilant;
1535
1536 log_goto_packet("Rally orders for city %d:", pcity->id);
1537 log_goto_packet(" Vigilant: %d.", p.vigilant);
1538
1540 p.orders, &p.length, nullptr);
1541
1543}
1544
1545/************************************************************************/
1548void send_goto_path(struct unit *punit, struct pf_path *path,
1549 struct unit_order *final_order)
1550{
1552}
1553
1554/************************************************************************/
1557static void send_rally_path(struct city *pcity, struct unit *punit,
1558 bool persistent, struct pf_path *path,
1559 struct unit_order *final_order)
1560{
1563}
1564
1565/************************************************************************/
1569bool send_goto_tile(struct unit *punit, struct tile *ptile)
1570{
1571 struct pf_parameter parameter;
1572 struct pf_map *pfm;
1573 struct pf_path *path;
1574
1575 goto_fill_parameter_base(&parameter, punit);
1576 pfm = pf_map_new(&parameter);
1577 path = pf_map_path(pfm, ptile);
1579
1580 if (path != nullptr) {
1581 send_goto_path(punit, path, nullptr);
1582 pf_path_destroy(path);
1583 return TRUE;
1584 } else {
1585 return FALSE;
1586 }
1587}
1588
1589/************************************************************************/
1593bool send_rally_tile(struct city *pcity, struct tile *ptile, bool persistent)
1594{
1595 const struct unit_type *putype;
1596 struct unit *punit;
1597 struct pf_parameter parameter;
1598 struct pf_map *pfm;
1599 struct pf_path *path;
1600
1601 fc_assert_ret_val(pcity != nullptr, FALSE);
1602 fc_assert_ret_val(ptile != nullptr, FALSE);
1603
1604 /* Create a virtual unit of the type being produced by the city. */
1605 if (pcity->production.kind != VUT_UTYPE) {
1606 /* Can only give orders to units. */
1607 return FALSE;
1608 }
1609
1610 putype = pcity->production.value.utype;
1613 putype));
1614
1615 /* Use the unit to find a path to the destination tile. */
1616 goto_fill_parameter_base(&parameter, punit);
1617 pfm = pf_map_new(&parameter);
1618 path = pf_map_path(pfm, ptile);
1620
1621 if (path != nullptr) {
1622 /* Send orders to server. */
1623 send_rally_path(pcity, punit, persistent, path, nullptr);
1625 pf_path_destroy(path);
1626
1627 return TRUE;
1628 } else {
1630
1631 return FALSE;
1632 }
1633}
1634
1635/************************************************************************/
1639bool send_attack_tile(struct unit *punit, struct tile *ptile)
1640{
1641 struct pf_parameter parameter;
1642 struct pf_map *pfm;
1643 struct pf_path *path;
1644
1645 goto_fill_parameter_base(&parameter, punit);
1646 parameter.move_rate = 0;
1647 parameter.is_pos_dangerous = nullptr;
1648 parameter.get_moves_left_req = nullptr;
1649 pfm = pf_map_new(&parameter);
1650 path = pf_map_path(pfm, ptile);
1652
1653 if (path != nullptr) {
1655 pf_path_destroy(path);
1656 return TRUE;
1657 }
1658
1659 return FALSE;
1660}
1661
1662/************************************************************************/
1667{
1669
1671 int i;
1672 struct pf_path *path = nullptr;
1673 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1674
1675 if (last_part->path == nullptr) {
1676 /* Cannot move there */
1677 continue;
1678 }
1679
1680 for (i = 0; i < goto_map->num_parts; i++) {
1682 }
1684
1686
1689}
1690
1691/************************************************************************/
1694static bool order_recursive_roads(struct tile *ptile, struct extra_type *pextra,
1695 struct packet_unit_orders *p, int rec)
1696{
1697 if (rec > MAX_EXTRA_TYPES) {
1698 return FALSE;
1699 }
1700
1701 if (!is_extra_caused_by(pextra, EC_ROAD)) {
1702 return FALSE;
1703 }
1704
1705 if (tile_has_extra(ptile, pextra)) {
1706 /* No need to build what is already there. */
1707 return TRUE;
1708 }
1709
1710 extra_deps_iterate(&(pextra->reqs), pdep) {
1711 if (!tile_has_extra(ptile, pdep)) {
1712 if (!order_recursive_roads(ptile, pdep, p, rec + 1)) {
1713 return FALSE;
1714 }
1715 }
1717
1719 p->orders[p->length].dir = DIR8_ORIGIN;
1721 p->orders[p->length].target = ptile->index;
1722 p->orders[p->length].sub_target = extra_index(pextra);
1724 p->length++;
1725
1726 return TRUE;
1727}
1728
1729/************************************************************************/
1734 struct extra_type *tgt)
1735{
1737
1739 int i;
1740 struct packet_unit_orders p;
1741 struct tile *old_tile;
1742 struct pf_path *path = nullptr;
1743 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1744
1745 if (last_part->path == nullptr) {
1746 /* Cannot move there */
1747 continue;
1748 }
1749
1750 memset(&p, 0, sizeof(p));
1751
1752 i = 0;
1753 do {
1755 i++;
1756 } while (i < goto_map->num_parts);
1757
1758 p.unit_id = punit->id;
1760 p.repeat = FALSE;
1761 p.vigilant = FALSE; /* Should be TRUE? */
1762
1763 p.length = 0;
1765
1766 for (i = 0; i < path->length; i++) {
1767 switch (activity) {
1768 case ACTIVITY_IRRIGATE:
1769 if (!tile_has_extra(old_tile, tgt)) {
1770 /* Assume the unit can irrigate or we wouldn't be here. */
1774 p.orders[p.length].target = old_tile->index;
1775 p.orders[p.length].sub_target = extra_index(tgt);
1777 p.length++;
1778 }
1779 break;
1780 case ACTIVITY_GEN_ROAD:
1781 order_recursive_roads(old_tile, tgt, &p, 0);
1782 break;
1783 default:
1784 log_error("Invalid connect activity: %d.", activity);
1785 break;
1786 }
1787
1788 if (i != path->length - 1) {
1789 struct tile *new_tile = path->positions[i + 1].tile;
1790
1792
1800 p.length++;
1801
1803 }
1804 }
1805
1807
1811}
1812
1813/************************************************************************/
1820static bool order_wants_direction(enum unit_orders order, action_id act_id,
1821 struct tile *tgt_tile, struct unit *punit)
1822{
1823 struct player *cplayer;
1824
1825 switch (order) {
1826 case ORDER_MOVE:
1827 case ORDER_ACTION_MOVE:
1828 /* Not only is it legal. It is mandatory. A move is always done in a
1829 * direction. */
1830 return TRUE;
1832 if (!action_id_distance_accepted(act_id, 0)) {
1833 /* Always illegal to do to a target on the actor's own tile. */
1834 return TRUE;
1835 }
1836
1837 if (!action_id_distance_accepted(act_id, 1)) {
1838 /* Always illegal to perform to a target on a neighbor tile. */
1839 return FALSE;
1840 }
1841
1846 /* Won't be able to move to the target tile to perform the action on
1847 * top of it. */
1848 /* TODO: Detect situations where it also would be illegal to perform
1849 * the action from the neighbor tile. */
1850 return TRUE;
1851 }
1852
1854 /* Prefer efficiency over safety among allies. */
1856 return TRUE;
1857 }
1858
1859 return FALSE;
1860 default:
1861 return FALSE;
1862 }
1863}
1864
1865/************************************************************************/
1869static bool order_demands_direction(enum unit_orders order, action_id act_id)
1870{
1871 switch (order) {
1872 case ORDER_MOVE:
1873 case ORDER_ACTION_MOVE:
1874 /* A move is always done in a direction. */
1875 return TRUE;
1877 if (!action_id_distance_accepted(act_id, 0)) {
1878 /* Always illegal to do to a target on the actor's own tile. */
1879 return TRUE;
1880 }
1881
1882 return FALSE;
1883 default:
1884 return FALSE;
1885 }
1886}
1887
1888/************************************************************************/
1895{
1898 int i;
1899 struct tile *tgt_tile;
1900 struct pf_path *path = nullptr;
1901 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1902
1903 if (last_part->path == nullptr) {
1904 /* Cannot move there */
1905 continue;
1906 }
1907
1908 i = 0;
1909 do {
1911 i++;
1912 } while (i < goto_map->num_parts);
1913
1915
1917
1918 /* Make the last move in a plain goto try to pop up the action
1919 * selection dialog rather than moving to the last tile if it contains
1920 * a domestic, allied or team mate city, unit or unit stack. This can,
1921 * in cases where the action requires movement left, save a turn. */
1927 ACTION_ANY,
1929 FALSE)
1931 ACTION_ANY,
1933 TRUE)
1935 ACTION_ANY,
1936 DS_TEAM,
1937 TRUE)))) {
1938 /* Try to pop up the action selection dialog before moving to the
1939 * target tile. */
1941 }
1942
1943 /* Handle single-step goto like single-step move. */
1944 if (goto_last_order == ORDER_LAST && path->length == 2
1947 }
1948
1949 if (goto_last_order == ORDER_LAST) {
1950 send_goto_path(punit, path, nullptr);
1951 } else if (path->length > 1
1954 struct unit_order order;
1955 int last_order_dir;
1956 struct tile *on_tile;
1958
1959 if (path->length > 1 && goto_last_tgt == NO_TARGET
1960 && ((on_tile = path->positions[path->length - 2].tile))
1962 tgt_tile, punit)
1963 && !same_pos(on_tile, tgt_tile)) {
1964 /* The last order prefers to handle the last direction it self.
1965 * There exists a tile before the target tile to do it from. */
1966
1967 /* Give the last path direction to the final order. */
1969
1970 /* The last path direction is now spent. */
1972 } else {
1976
1977 /* Target the tile the actor is standing on or goto_last_tgt. */
1979 }
1980
1983 ? tgt_tile->index : goto_last_tgt);
1985 }
1986
1987 order.order = goto_last_order;
1988 order.dir = last_order_dir;
1989 order.activity = ACTIVITY_LAST;
1990 order.target = last_order_target;
1992 order.action = goto_last_action;
1993
1994 /* ORDER_ACTIVITY would require real activity */
1996
1997 send_goto_path(punit, path, &order);
1998 }
1999 pf_path_destroy(path);
2001}
2002
2003/************************************************************************/
2008{
2009 struct pf_parameter parameter;
2010 struct pf_map *pfm;
2011 struct pf_path *path = nullptr;
2012
2014 /* We're already on a city - don't go anywhere. */
2015 return nullptr;
2016 }
2017
2018 goto_fill_parameter_base(&parameter, punit);
2019 pfm = pf_map_new(&parameter);
2020
2021 pf_map_tiles_iterate(pfm, ptile, FALSE) {
2022 if (is_allied_city_tile(ptile, unit_owner(punit))) {
2023 path = pf_map_path(pfm, ptile);
2024 break;
2025 }
2027
2029
2030 return path;
2031}
2032
2033/************************************************************************/
2036struct tile *tile_before_end_path(struct unit *punit, struct tile *ptile)
2037{
2038 struct pf_parameter parameter;
2039 struct pf_map *pfm;
2040 struct tile *dtile;
2041 struct pf_path *path;
2042
2043 goto_fill_parameter_base(&parameter, punit);
2044 parameter.move_rate = 0;
2045 parameter.is_pos_dangerous = nullptr;
2046 parameter.get_moves_left_req = nullptr;
2047 pfm = pf_map_new(&parameter);
2048 path = pf_map_path(pfm, ptile);
2049
2050 if (path == nullptr) {
2051 return nullptr;
2052 }
2053
2054 if (path->length < 2) {
2055 dtile = nullptr;
2056 } else {
2057 dtile = path->positions[path->length - 2].tile;
2058 }
2060
2061 return dtile;
2062}
bool action_id_exists(const action_id act_id)
Definition actions.c:1068
#define action_id_distance_accepted(act_id, distance)
Definition actions.h:445
#define ACTION_ANY
Definition actions.h:52
#define action_id_has_result_safe(act_id, result)
Definition actions.h:426
#define ACTION_NONE
Definition actions.h:55
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
int city_production_unit_veteran_level(struct city *pcity, const struct unit_type *punittype)
Definition city.c:804
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:767
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:743
struct civclient client
bool can_client_issue_orders(void)
#define client_player()
char * incite_cost
Definition comments.c:76
#define MAX_LEN_ROUTE
Definition conn_types.h:38
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:388
enum unit_orders goto_last_order
Definition control.c:96
int check_recursive_road_connect(struct tile *ptile, const struct extra_type *pextra, const struct unit *punit, const struct player *pplayer, int rec)
Definition control.c:1337
int goto_last_tgt
Definition control.c:94
struct extra_type * connect_tgt
Definition control.c:91
struct unit_list * get_units_in_focus(void)
Definition control.c:177
void request_unit_ssa_set(const struct unit *punit, enum server_side_agent agent)
Definition control.c:2128
enum unit_activity connect_activity
Definition control.c:90
enum cursor_hover_state hover_state
Definition control.c:89
void clear_unit_orders(struct unit *punit)
Definition control.c:481
int goto_last_sub_tgt
Definition control.c:95
action_id goto_last_action
Definition control.c:93
@ HOVER_GOTO
Definition control.h:27
@ HOVER_PARADROP
Definition control.h:29
@ HOVER_TELEPORT
Definition control.h:28
@ HOVER_ACT_SEL_TGT
Definition control.h:32
@ HOVER_NONE
Definition control.h:26
@ HOVER_CONNECT
Definition control.h:30
@ HOVER_PATROL
Definition control.h:31
@ HOVER_GOTO_SEL_TGT
Definition control.h:33
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_deps_iterate(_reqs, _dep)
Definition extras.h:371
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define extra_deps_iterate_end
Definition extras.h:379
#define extra_road_get(_e_)
Definition extras.h:191
#define NO_TARGET
Definition fc_types.h:213
#define DIR8_ORIGIN
Definition fc_types.h:314
int action_id
Definition fc_types.h:248
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
struct world wld
Definition game.c:62
static bool goto_warned
Definition goto.c:92
static bool is_non_allied_city_adjacent(const struct player *pplayer, const struct tile *ptile)
Definition goto.c:677
static int get_connect_irrig(const struct tile *src_tile, enum direction8 dir, const struct tile *dest_tile, int src_cost, int src_extra, unsigned *dest_cost, unsigned *dest_extra, const struct pf_parameter *param)
Definition goto.c:808
static void fill_parameter_part(struct pf_parameter *param, const struct goto_map *goto_map, const struct part *p)
Definition goto.c:408
#define LOG_GOTO_PATH
Definition goto.c:43
#define goto_map_list_iterate_end
Definition goto.c:80
static int get_connect_road(const struct tile *src_tile, enum direction8 dir, const struct tile *dest_tile, int src_cost, int src_extra, unsigned *dest_cost, unsigned *dest_extra, const struct pf_parameter *param)
Definition goto.c:698
static void make_path_orders(struct unit *punit, struct pf_path *path, enum unit_orders orders, struct unit_order *final_order, struct unit_order *order_list, int *length, int *dest_tile)
Definition goto.c:1399
static void goto_path_undraw(const struct pf_path *path)
Definition goto.c:237
static enum tile_behavior no_fights_or_unknown_goto(const struct tile *ptile, enum known_type known, const struct pf_parameter *p)
Definition goto.c:882
static bool order_recursive_roads(struct tile *ptile, struct extra_type *pextra, struct packet_unit_orders *p, int rec)
Definition goto.c:1694
static void goto_fill_parameter_full(struct goto_map *goto_map, const struct unit *punit)
Definition goto.c:931
static struct tile * goto_destination
Definition goto.c:103
static unsigned get_EC(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition goto.c:561
static enum tile_behavior get_TB_caravan(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition goto.c:593
void exit_goto_state(void)
Definition goto.c:1033
struct tile * tile_before_end_path(struct unit *punit, struct tile *ptile)
Definition goto.c:2036
bool goto_is_active(void)
Definition goto.c:1070
bool send_attack_tile(struct unit *punit, struct tile *ptile)
Definition goto.c:1639
struct pf_path * path_to_nearest_allied_city(struct unit *punit)
Definition goto.c:2007
static struct goto_map_list * goto_maps
Definition goto.c:91
static void goto_fill_parameter_base(struct pf_parameter *parameter, const struct unit *punit)
Definition goto.c:898
void init_client_goto(void)
Definition goto.c:153
#define goto_map_unit_iterate_end
Definition goto.c:88
void send_patrol_route(void)
Definition goto.c:1666
bool send_rally_tile(struct city *pcity, struct tile *ptile, bool persistent)
Definition goto.c:1593
static void remove_last_part(struct goto_map *goto_map)
Definition goto.c:471
static void send_rally_path_orders(struct city *pcity, struct unit *punit, struct pf_path *path, bool vigilant, bool persistent, enum unit_orders orders, struct unit_order *final_order)
Definition goto.c:1523
bool is_valid_goto_draw_line(struct tile *dest_tile)
Definition goto.c:1350
static void send_path_orders(struct unit *punit, struct pf_path *path, bool repeat, bool vigilant, enum unit_orders orders, struct unit_order *final_order)
Definition goto.c:1492
static bool order_wants_direction(enum unit_orders order, action_id act_id, struct tile *tgt_tile, struct unit *punit)
Definition goto.c:1820
static struct goto_map * goto_map_new(struct unit *punit)
Definition goto.c:108
static bool update_last_part(struct goto_map *goto_map, struct tile *ptile)
Definition goto.c:259
static enum tile_behavior get_TB_aggr(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition goto.c:571
#define goto_map_list_iterate(gotolist, pgoto)
Definition goto.c:78
static void reset_last_part(struct goto_map *goto_map)
Definition goto.c:395
#define log_goto_path
Definition goto.c:44
#define goto_map_unit_iterate(gotolist, pgoto, punit)
Definition goto.c:84
bool goto_add_waypoint(void)
Definition goto.c:489
bool send_goto_tile(struct unit *punit, struct tile *ptile)
Definition goto.c:1569
static struct unit * goto_map_unit(const struct goto_map *goto_map)
Definition goto.c:139
bool goto_pop_waypoint(void)
Definition goto.c:528
#define log_goto_packet
Definition goto.c:45
void send_connect_route(enum unit_activity activity, struct extra_type *tgt)
Definition goto.c:1733
void goto_unit_killed(struct unit *punit)
Definition goto.c:1051
void free_client_goto(void)
Definition goto.c:163
void enter_goto_state(struct unit_list *punits)
Definition goto.c:1011
void send_goto_route(void)
Definition goto.c:1894
bool is_valid_goto_destination(const struct tile *ptile)
Definition goto.c:180
static void goto_path_redraw(const struct pf_path *new_path, const struct pf_path *old_path)
Definition goto.c:188
bool goto_get_turns(int *min, int *max)
Definition goto.c:1079
static int get_activity_time(const struct tile *ptile, const struct player *pplayer)
Definition goto.c:620
static void goto_map_free(struct goto_map *goto_map)
Definition goto.c:122
void request_orders_cleared(struct unit *punit)
Definition goto.c:1377
static void send_rally_path(struct city *pcity, struct unit *punit, bool persistent, struct pf_path *path, struct unit_order *final_order)
Definition goto.c:1557
static bool order_demands_direction(enum unit_orders order, action_id act_id)
Definition goto.c:1869
void send_goto_path(struct unit *punit, struct pf_path *path, struct unit_order *final_order)
Definition goto.c:1548
static void add_part(struct goto_map *goto_map)
Definition goto.c:439
goto_tile_state
Definition goto.h:25
@ GTS_EXHAUSTED_MP
Definition goto.h:28
@ GTS_MP_LEFT
Definition goto.h:27
@ GTS_TURN_STEP
Definition goto.h:26
static struct tile * pos
Definition finddlg.c:53
void update_unit_info_label(struct unit_list *punits)
Definition mapview.c:275
static GtkWidget * persistent
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_msg(condition, message,...)
Definition log.h:206
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
int get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1488
const char * dir_get_name(enum direction8 dir)
Definition map.c:1287
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1457
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
bool is_valid_dir(enum direction8 dir)
Definition map.c:1401
#define adjc_iterate_end
Definition map.h:430
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
void cancel_selection_rectangle(void)
void mapdeco_add_gotoline(const struct tile *ptile, enum direction8 dir)
void refresh_tile_mapcanvas(struct tile *ptile, bool full_refresh, bool write_to_screen)
void mapdeco_remove_gotoline(const struct tile *ptile, enum direction8 dir)
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:289
struct client_options gui_options
Definition options.c:71
int send_packet_city_rally_point(struct connection *pc, const struct packet_city_rally_point *packet, bool force_to_send)
int send_packet_unit_orders(struct connection *pc, const struct packet_unit_orders *packet)
struct pf_path * pf_path_concat(struct pf_path *dest_path, const struct pf_path *src_path)
const struct pf_position * pf_path_last_position(const struct pf_path *path)
void pf_path_destroy(struct pf_path *path)
bool pf_path_backtrack(struct pf_path *path, struct tile *ptile)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
void pf_map_destroy(struct pf_map *pfm)
#define pf_path_print(path, level)
#define PF_IMPOSSIBLE_MC
@ PF_MS_NATIVE
#define PF_TURN_FACTOR
#define pf_map_tiles_iterate(ARG_pfm, NAME_tile, COND_from_start)
tile_behavior
@ TB_NORMAL
@ TB_DONT_LEAVE
@ TB_IGNORE
#define pf_map_tiles_iterate_end
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:843
enum tile_behavior no_fights_or_unknown(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:493
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
#define MIN(x, y)
Definition shared.h:55
#define FC_INFINITY
Definition shared.h:36
#define FC_PTR_TO_INT(p)
Definition shared.h:95
#define FC_INT_TO_PTR(i)
Definition shared.h:94
Definition city.h:317
struct connection conn
Definition client_main.h:96
bool goto_into_unknown
Definition options.h:161
bool popup_last_move_to_allied
Definition options.h:171
bv_extras conflicts
Definition extras.h:133
struct requirement_vector reqs
Definition extras.h:106
int num_parts
Definition goto.c:62
struct pf_path * return_path
Definition goto.c:68
struct goto_map::@138::@141 patrol
struct unit * focus
Definition goto.c:60
struct part * parts
Definition goto.c:61
struct pf_parameter template
Definition goto.c:71
struct goto_map::@138::@140 connect
int initial_turns
Definition goto.c:65
struct unit_order orders[MAX_LEN_ROUTE]
struct unit_order orders[MAX_LEN_ROUTE]
Definition goto.c:52
int end_moves_left
Definition goto.c:54
struct pf_map * map
Definition goto.c:56
struct tile * start_tile
Definition goto.c:53
struct pf_path * path
Definition goto.c:55
int end_fuel_left
Definition goto.c:54
struct tile * end_tile
Definition goto.c:53
int fuel_left_initially
const struct unit_type * transported_by_initially
enum tile_behavior(* get_TB)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
const struct player * owner
bool(* is_pos_dangerous)(const struct tile *ptile, enum known_type, const struct pf_parameter *param)
int(* get_moves_left_req)(const struct tile *ptile, enum known_type, const struct pf_parameter *param)
int moves_left_initially
unsigned(* get_MC)(const struct tile *from_tile, enum pf_move_scope src_move_scope, const struct tile *to_tile, enum pf_move_scope dst_move_scope, const struct pf_parameter *param)
int(* get_costs)(const struct tile *from_tile, enum direction8 dir, const struct tile *to_tile, int from_cost, int from_extra, unsigned *to_cost, unsigned *to_extra, const struct pf_parameter *param)
unsigned(* get_EC)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
const struct unit_type * utype
struct tile * start_tile
unsigned length
struct pf_position * positions
unsigned total_MC
struct tile * tile
int move_cost
Definition road.h:74
int irrigation_time
Definition terrain.h:115
Definition tile.h:50
int index
Definition tile.h:51
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
Definition unit.h:140
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
struct unit * transporter
Definition unit.h:186
const struct unit_type * utype
Definition unit.h:141
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1035
bool tile_has_road(const struct tile *ptile, const struct road_type *proad)
Definition tile.c:844
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:981
enum known_type tile_get_known(const struct tile *ptile, const struct player *pplayer)
Definition tile.c:392
#define tile_index(_pt_)
Definition tile.h:89
known_type
Definition tile.h:35
@ TILE_UNKNOWN
Definition tile.h:36
#define ACTIVITY_FACTOR
Definition tile.h:166
#define tile_terrain(_tile)
Definition tile.h:111
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
struct unit * transporter_for_unit_at(const struct unit *pcargo, const struct tile *ptile)
Definition unit.c:1959
int get_activity_rate(const struct unit *punit)
Definition unit.c:519
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1661
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1766
#define unit_tile(_pu)
Definition unit.h:404
unit_orders
Definition unit.h:38
@ ORDER_ACTION_MOVE
Definition unit.h:46
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_FULL_MP
Definition unit.h:44
@ ORDER_MOVE
Definition unit.h:40
@ ORDER_LAST
Definition unit.h:50
@ ORDER_PERFORM_ACTION
Definition unit.h:48
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:415
#define unit_owner(_pu)
Definition unit.h:403
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:440
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1593
bool utype_may_act_at_all(const struct unit_type *putype)
Definition unittype.c:365
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:196
bool utype_acts_hostile(const struct unit_type *putype)
Definition unittype.c:449
bool can_utype_do_act_if_tgt_diplrel(const struct unit_type *punit_type, const action_id act_id, const int prop, const bool is_there)
Definition unittype.c:1023
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624