Freeciv-3.1
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 NULL.
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 = NULL;
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 = NULL;
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 = NULL;
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 (NULL != goto_map->parts) {
125 while (goto_map->num_parts > 0) {
127 }
128 free(goto_map->parts);
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 != NULL);
146 return punit;
147}
148
149/************************************************************************/
153{
155
156 goto_maps = goto_map_list_new();
157}
158
159/************************************************************************/
163{
164 if (NULL != goto_maps) {
168 goto_map_list_destroy(goto_maps);
169 goto_maps = NULL;
170 }
171
172 goto_destination = NULL;
174}
175
176/************************************************************************/
179bool is_valid_goto_destination(const struct tile *ptile)
180{
181 return (NULL != goto_destination && ptile == goto_destination);
182}
183
184/************************************************************************/
187static void goto_path_redraw(const struct pf_path *new_path,
188 const struct pf_path *old_path)
189{
190 int start_index = 0;
191 int i;
192
193 fc_assert_ret(new_path != NULL);
194
195 if (old_path != NULL) {
196 /* We had a path drawn already. Determine how much of it we can reuse
197 * in drawing the new path. */
198 for (i = 0; i < new_path->length - 1 && i < old_path->length - 1; i++) {
199 struct pf_position *old_pos = old_path->positions + i;
200 struct pf_position *new_pos = new_path->positions + i;
201
202 if (old_pos->dir_to_next_pos != new_pos->dir_to_next_pos
203 || old_pos->tile != new_pos->tile) {
204 break;
205 }
206 }
207 start_index = i;
208
209 /* Erase everything we cannot reuse. */
210 for (; i < old_path->length - 1; i++) {
211 struct pf_position *pos = old_path->positions + i;
212
213 if (is_valid_dir(pos->dir_to_next_pos)) {
214 mapdeco_remove_gotoline(pos->tile, pos->dir_to_next_pos);
215 } else {
216 fc_assert(pos->tile == (pos + 1)->tile);
217 }
218 }
219 }
220
221 /* Draw the new path. */
222 for (i = start_index; i < new_path->length - 1; i++) {
223 struct pf_position *pos = new_path->positions + i;
224
225 if (is_valid_dir(pos->dir_to_next_pos)) {
226 mapdeco_add_gotoline(pos->tile, pos->dir_to_next_pos);
227 } else {
228 fc_assert(pos->tile == (pos + 1)->tile);
229 }
230 }
231}
232
233/************************************************************************/
236static void goto_path_undraw(const struct pf_path *path)
237{
238 int i;
239
240 fc_assert_ret(path != NULL);
241
242 for (i = 0; i < path->length - 1; i++) {
243 struct pf_position *pos = path->positions + i;
244
245 if (is_valid_dir(pos->dir_to_next_pos)) {
246 mapdeco_remove_gotoline(pos->tile, pos->dir_to_next_pos);
247 } else {
248 fc_assert(pos->tile == (pos + 1)->tile);
249 }
250 }
251}
252
253/************************************************************************/
259 struct tile *ptile)
260{
261 struct pf_path *old_path, *new_path;
262 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
263
264 old_path = p->path;
265 if (old_path != NULL && pf_path_last_position(old_path)->tile == ptile) {
266 /* Nothing to update. */
267 return TRUE;
268 }
269
270 log_debug("update_last_part(%d,%d) old (%d,%d)-(%d,%d)",
271 TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
272 new_path = pf_map_path(p->map, ptile);
273
274 if (!new_path) {
275 log_goto_path(" no path found");
276
277 if (p->start_tile == ptile) {
278 /* This mean we cannot reach the start point. It is probably,
279 * a path-finding bug, but don't make infinite recursion. */
280
281 if (!goto_warned) {
282 log_error("No path found to reach the start point.");
284 }
285
286 if (old_path != NULL) {
287 goto_path_undraw(old_path);
288 pf_path_destroy(old_path);
289 p->path = NULL;
290 }
292 && goto_map->patrol.return_path != NULL) {
296 }
297 return FALSE;
298 }
299
301 return FALSE;
302 }
303
304 log_goto_path(" path found:");
305 pf_path_print(new_path, LOG_GOTO_PATH);
306
307 p->path = new_path;
308 p->end_tile = ptile;
311
312 if (hover_state == HOVER_PATROL) {
313 struct pf_parameter parameter;
314 struct pf_map *pfm;
315 struct pf_path *return_path;
316
317 fill_parameter_part(&parameter, goto_map, p);
318 pfm = pf_map_new(&parameter);
319 return_path = pf_map_path(pfm, goto_map->parts[0].start_tile);
320 pf_map_destroy(pfm);
321
322 if (return_path == NULL) {
323 log_goto_path(" no return path found");
324
325 if (p->start_tile == ptile) {
326 /* This mean we cannot reach the start point. It is probably,
327 * a path-finding bug, but don't make infinite recursion. */
328
329 if (!goto_warned) {
330 log_error("No path found to reach the start point.");
332 }
333
334 if (old_path != NULL) {
335 goto_path_undraw(old_path);
336 pf_path_destroy(old_path);
337 }
338 pf_path_destroy(new_path);
339 p->path = NULL;
340 if (goto_map->patrol.return_path != NULL) {
344 }
345 return FALSE;
346 }
347
348 p->path = old_path;
349
350 if (p->path != NULL) {
351 const struct pf_position *pos = pf_path_last_position(old_path);
352
353 p->end_tile = pos->tile;
354 p->end_moves_left = pos->moves_left;
355 p->end_fuel_left = pos->fuel_left;
356 }
357
358 pf_path_destroy(new_path);
360
361 return FALSE;
362 }
363
364 log_goto_path(" returned path found:");
365 pf_path_print(return_path, LOG_GOTO_PATH);
366
367 if (goto_map->patrol.return_path != NULL) {
368 /* We cannot reuse old path because:
369 * 1- the start tile isn't the same.
370 * 2- the turn number neither (impossible to do in backward mode). */
373 }
374 goto_path_redraw(return_path, NULL);
375 goto_map->patrol.return_path = return_path;
376 }
377
378 goto_path_redraw(new_path, old_path);
379 pf_path_destroy(old_path);
380
381 log_goto_path("To (%d,%d) part %d: total_MC: %d",
382 TILE_XY(ptile), goto_map->num_parts,
385 : new_path)->total_MC);
386
387 return TRUE;
388}
389
390/************************************************************************/
395{
396 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
397
398 if (NULL != p->path) {
399 /* Otherwise no need to update */
401 }
402}
403
404/************************************************************************/
407static void fill_parameter_part(struct pf_parameter *param,
408 const struct goto_map *goto_map,
409 const struct part *p)
410{
411 *param = goto_map->template;
412
413 if (p->start_tile == p->end_tile) {
414 /* Copy is enough, we didn't move last part. */
415 fc_assert(p->path->length == 1);
416 return;
417 }
418
419 param->start_tile = p->end_tile;
422 if (can_exist_at_tile(&(wld.map), param->utype, param->start_tile)) {
423 param->transported_by_initially = NULL;
424 } else {
425 const struct unit *transporter =
427
428 param->transported_by_initially = (transporter != NULL
429 ? unit_type_get(transporter) : NULL);
430 }
431}
432
433/************************************************************************/
438static void add_part(struct goto_map *goto_map)
439{
440 struct part *p;
441 struct pf_parameter parameter;
442 struct unit *punit = goto_map_unit(goto_map);
443
445 goto_map->parts =
447 goto_map->num_parts * sizeof(*goto_map->parts));
448 p = &goto_map->parts[goto_map->num_parts - 1];
449
450 if (goto_map->num_parts == 1) {
451 /* first part */
453 parameter = goto_map->template;
454 } else {
455 struct part *prev = &goto_map->parts[goto_map->num_parts - 2];
456
457 p->start_tile = prev->end_tile;
458 fill_parameter_part(&parameter, goto_map, prev);
459 }
460 p->path = NULL;
461 p->end_tile = p->start_tile;
462 parameter.start_tile = p->start_tile;
463 p->map = pf_map_new(&parameter);
464}
465
466/************************************************************************/
470{
471 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
472
474
476 if (p->path) {
477 /* We do not always have a path */
479 }
482}
483
484/************************************************************************/
488{
489 bool duplicate_of_last = TRUE;
490
492 if (NULL == goto_destination) {
493 /* Not a valid position. */
494 return FALSE;
495 }
496
498 const struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
499
500 if (last_part->path == NULL) {
501 /* The current part has zero length. */
502 return FALSE;
503 }
504 if (last_part->start_tile != last_part->end_tile) {
505 duplicate_of_last = FALSE;
506 }
508 if (duplicate_of_last) {
509 return FALSE;
510 }
511
515
517 return TRUE;
518}
519
520/************************************************************************/
525{
526 bool popped = FALSE;
527
530 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
531 struct tile *end_tile = p->end_tile;
532
533 if (goto_map->num_parts == 1) {
534 /* we don't have any waypoint but the start pos. */
535 continue;
536 }
537 popped = TRUE;
538
540
541 /*
542 * Set the end position of the previous part (now the last) to the
543 * end position of the last part (now gone). I.e. redraw a line to
544 * the mouse position.
545 */
546 update_last_part(goto_map, end_tile);
548 return popped;
549}
550
551/************************************************************************/
555static unsigned get_EC(const struct tile *ptile, enum known_type known,
556 const struct pf_parameter *param)
557{
558 return 1;
559}
560
561/************************************************************************/
565static enum tile_behavior get_TB_aggr(const struct tile *ptile,
566 enum known_type known,
567 const struct pf_parameter *param)
568{
569 if (known == TILE_UNKNOWN) {
571 return TB_IGNORE;
572 }
573 } else if (is_non_allied_unit_tile(ptile, param->owner)
574 || is_non_allied_city_tile(ptile, param->owner)) {
575 /* Can attack but can't count on going through */
576 return TB_DONT_LEAVE;
577 }
578 return TB_NORMAL;
579}
580
581/************************************************************************/
585static enum tile_behavior get_TB_caravan(const struct tile *ptile,
586 enum known_type known,
587 const struct pf_parameter *param)
588{
589 if (known == TILE_UNKNOWN) {
591 return TB_IGNORE;
592 }
593 } else if (is_non_allied_city_tile(ptile, param->owner)) {
594 /* Units that can establish a trade route, enter a market place or
595 * establish an embassy can travel to, but not through, enemy cities.
596 * FIXME: ACTION_HELP_WONDER units cannot. */
597 return TB_DONT_LEAVE;
598 } else if (is_non_allied_unit_tile(ptile, param->owner)) {
599 /* Note this must be below the city check. */
600 return TB_IGNORE;
601 }
602
603 /* Includes empty, allied, or allied-city tiles. */
604 return TB_NORMAL;
605}
606
607/************************************************************************/
611static int get_activity_time(const struct tile *ptile,
612 const struct player *pplayer)
613{
614 struct terrain *pterrain = tile_terrain(ptile);
615 int activity_mc = 0;
616
618
619 switch (connect_activity) {
620 case ACTIVITY_IRRIGATE:
621 if (pterrain->irrigation_time == 0) {
622 return -1;
623 }
624 extra_type_iterate(pextra) {
626 && tile_has_extra(ptile, pextra)) {
627 /* Don't replace old extras. */
628 return -1;
629 }
631
632 if (tile_has_extra(ptile, connect_tgt)) {
633 break;
634 }
635
636 activity_mc = pterrain->irrigation_time;
637 break;
638 case ACTIVITY_GEN_ROAD:
640
641 if (!tile_has_extra(ptile, connect_tgt)) {
642 struct tile *vtile;
643 int single_mc;
644
645 vtile = tile_virtual_new(ptile);
646 single_mc = check_recursive_road_connect(vtile, connect_tgt, NULL, pplayer, 0);
648
649 if (single_mc < 0) {
650 return -1;
651 }
652
653 activity_mc += single_mc;
654 }
655 break;
656 default:
657 log_error("Invalid connect activity: %d.", connect_activity);
658 }
659
660 return activity_mc;
661}
662
663/************************************************************************/
667static bool is_non_allied_city_adjacent(const struct player *pplayer,
668 const struct tile *ptile)
669{
670 adjc_iterate(&(wld.map), ptile, tile1) {
671 if (is_non_allied_city_tile(tile1, pplayer)) {
672 return TRUE;
673 }
675
676 return FALSE;
677}
678
679/************************************************************************/
688static int get_connect_road(const struct tile *src_tile, enum direction8 dir,
689 const struct tile *dest_tile,
690 int src_cost, int src_extra,
691 unsigned *dest_cost, unsigned *dest_extra,
692 const struct pf_parameter *param)
693{
694 int activity_time, move_cost, moves_left;
695 int total_cost, total_extra;
696 struct road_type *proad;
697
698 if (tile_get_known(dest_tile, param->owner) == TILE_UNKNOWN) {
699 return -1;
700 }
701
702 activity_time = get_activity_time(dest_tile, param->owner);
703 if (activity_time < 0) {
704 return -1;
705 }
706
707 move_cost = param->get_MC(src_tile, PF_MS_NATIVE, dest_tile, PF_MS_NATIVE,
708 param);
710 return -1;
711 }
712
713 if (is_non_allied_city_adjacent(param->owner, dest_tile)) {
714 /* We don't want to build roads to enemies plus get ZoC problems */
715 return -1;
716 }
717
718 fc_assert(connect_activity == ACTIVITY_GEN_ROAD);
719
721
722 if (proad == NULL) {
723 /* No suitable road type available */
724 return -1;
725 }
726
727 /* Ok, the move is possible. What are the costs? */
728
729 /* Extra cost here is the final length of the road */
730 total_extra = src_extra + 1;
731
732 /* Special cases: get_MC function doesn't know that we would have built
733 * a road (railroad) on src tile by that time.
734 * We assume that settler building the road can also travel it. */
735 if (tile_has_road(dest_tile, proad)) {
736 move_cost = proad->move_cost;
737 }
738
739 move_cost = MIN(move_cost, param->move_rate);
740 total_cost = src_cost;
741 moves_left = param->move_rate - (src_cost % param->move_rate);
742 if (moves_left < move_cost) {
743 total_cost += moves_left;
744 } else {
745 total_cost += move_cost;
746 }
747
748 /* Now need to include the activity cost. If we have moves left, they
749 * will count as a full turn towards the activity time */
750 moves_left = param->move_rate - (total_cost % param->move_rate);
751 if (activity_time > 0) {
752 int speed = FC_PTR_TO_INT(param->data);
753
754 activity_time = ((activity_time * ACTIVITY_FACTOR)
755 + (speed - 1)) / speed;
756 activity_time--;
757 total_cost += moves_left;
758 }
759 total_cost += activity_time * param->move_rate;
760
761 /* Now we determine if we have found a better path. When building
762 * road type with positive move_cost, we care most about the length
763 * of the result. When building road type with move_cost 0, we
764 * care most about construction time. */
765
766 /* *dest_cost == -1 means we haven't reached dest until now */
767
768 if (*dest_cost != -1) {
769 if (proad->move_cost > 0) {
770 if (total_extra > *dest_extra
771 || (total_extra == *dest_extra && total_cost >= *dest_cost)) {
772 /* No, this path is worse than what we already have */
773 return -1;
774 }
775 } else {
776 if (total_cost > *dest_cost
777 || (total_cost == *dest_cost && total_extra >= *dest_extra)) {
778 return -1;
779 }
780 }
781 }
782
783 /* Ok, we found a better path! */
784 *dest_cost = total_cost;
785 *dest_extra = total_extra;
786
787 return (proad->move_cost > 0 ?
788 total_extra * PF_TURN_FACTOR + total_cost :
789 total_cost * PF_TURN_FACTOR + total_extra);
790}
791
792/************************************************************************/
798static int get_connect_irrig(const struct tile *src_tile,
799 enum direction8 dir,
800 const struct tile *dest_tile,
801 int src_cost, int src_extra,
802 unsigned *dest_cost, unsigned *dest_extra,
803 const struct pf_parameter *param)
804{
805 int activity_time, move_cost, moves_left, total_cost;
806
807 if (tile_get_known(dest_tile, param->owner) == TILE_UNKNOWN) {
808 return -1;
809 }
810
811 activity_time = get_activity_time(dest_tile, param->owner);
812 if (activity_time < 0) {
813 return -1;
814 }
815
816 if (!is_cardinal_dir(dir)) {
817 return -1;
818 }
819
820 move_cost = param->get_MC(src_tile, PF_MS_NATIVE, dest_tile, PF_MS_NATIVE,
821 param);
823 return -1;
824 }
825
826 if (is_non_allied_city_adjacent(param->owner, dest_tile)) {
827 /* We don't want to build irrigation for enemies plus get ZoC problems */
828 return -1;
829 }
830
831 /* Ok, the move is possible. What are the costs? */
832
833 move_cost = MIN(move_cost, param->move_rate);
834 total_cost = src_cost;
835 moves_left = param->move_rate - (src_cost % param->move_rate);
836 if (moves_left < move_cost) {
837 total_cost += moves_left;
838 } else {
839 total_cost += move_cost;
840 }
841
842 /* Now need to include the activity cost. If we have moves left, they
843 * will count as a full turn towards the activity time */
844 moves_left = param->move_rate - (total_cost % param->move_rate);
845 if (activity_time > 0) {
846 int speed = FC_PTR_TO_INT(param->data);
847
848 activity_time = ((activity_time * ACTIVITY_FACTOR)
849 + (speed - 1)) / speed;
850 activity_time--;
851 total_cost += moves_left;
852 }
853 total_cost += activity_time * param->move_rate;
854
855 /* *dest_cost == -1 means we haven't reached dest until now */
856 if (*dest_cost != -1 && total_cost > *dest_cost) {
857 return -1;
858 }
859
860 /* Ok, we found a better path! */
861 *dest_cost = total_cost;
862 *dest_extra = 0;
863
864 return total_cost;
865}
866
867/************************************************************************/
871static enum tile_behavior
872no_fights_or_unknown_goto(const struct tile *ptile,
873 enum known_type known,
874 const struct pf_parameter *p)
875{
877 /* Special case allowing goto into the unknown. */
878 return TB_NORMAL;
879 }
880
881 return no_fights_or_unknown(ptile, known, p);
882}
883
884/************************************************************************/
888static void goto_fill_parameter_base(struct pf_parameter *parameter,
889 const struct unit *punit)
890{
891 pft_fill_unit_parameter(parameter, &(wld.map), punit);
892
893 fc_assert(parameter->get_EC == NULL);
894 fc_assert(parameter->get_TB == NULL);
895 fc_assert(parameter->get_MC != NULL);
896 fc_assert(parameter->start_tile == unit_tile(punit));
897 fc_assert(!parameter->omniscience);
898
899 parameter->get_EC = get_EC;
901 parameter->get_TB = get_TB_aggr;
904 parameter->get_TB = get_TB_caravan;
905 } else {
907 }
908}
909
910/************************************************************************/
922 const struct unit *punit)
923{
924 struct pf_parameter *parameter = &goto_map->template;
925
927
929
930 switch (hover_state) {
931 case HOVER_CONNECT:
932 {
933 int activity_initial;
934 int speed;
935
936 if (connect_activity == ACTIVITY_IRRIGATE) {
937 parameter->get_costs = get_connect_irrig;
938 } else {
939 parameter->get_costs = get_connect_road;
940 }
941 parameter->get_moves_left_req = NULL;
942
943 speed = get_activity_rate(punit);
944 parameter->data = FC_INT_TO_PTR(speed);
945
946 /* Take into account the activity time at the origin */
947 activity_initial = get_activity_time(unit_tile(punit),
949
950 if (activity_initial > 0) {
951 /* First action is activity */
952 parameter->moves_left_initially = parameter->move_rate;
953 /* Number of turns, rounding up */
955 ((activity_initial * ACTIVITY_FACTOR + (speed - 1)) / speed);
956 if (punit->moves_left == 0) {
958 }
959 } else {
961 }
962 }
963 break;
964 case HOVER_GOTO:
965 case HOVER_PATROL:
966 if (action_id_has_result_safe(goto_last_action, ACTRES_NUKE_UNITS)
968 /* TODO: consider doing the same for other actor consuming actions. */
969 /* We only want targets reachable immediately... */
970 parameter->move_rate = 0;
971 /* ...then we don't need to deal with dangers or refuel points. */
972 parameter->is_pos_dangerous = NULL;
973 parameter->get_moves_left_req = NULL;
974 } else {
976 }
977 break;
980 "Path finding during target selection");
981 break;
982 case HOVER_NONE:
983 case HOVER_PARADROP:
985 fc_assert_msg(hover_state != HOVER_NONE, "Goto with HOVER_NONE?");
987 "Goto with HOVER_PARADROP?");
989 "Goto with HOVER_ACT_SEL_TGT?");
990 break;
991 };
992}
993
994/************************************************************************/
998void enter_goto_state(struct unit_list *punits)
999{
1001
1002 /* Can't have selection rectangle and goto going on at the same time. */
1004
1005 unit_list_iterate(punits, punit) {
1007
1008 goto_map_list_append(goto_maps, goto_map);
1009
1014}
1015
1016/************************************************************************/
1020{
1021 if (!goto_is_active()) {
1022 return;
1023 }
1024
1028 goto_map_list_clear(goto_maps);
1029
1030 goto_destination = NULL;
1032}
1033
1034/************************************************************************/
1038{
1039 if (!goto_is_active()) {
1040 return;
1041 }
1042
1044 if (ptest == punit) {
1045 goto_map_list_remove(goto_maps, goto_map);
1047 /* Stop now, links are gone! */
1048 break;
1049 }
1051}
1052
1053/************************************************************************/
1057{
1058 return (NULL != goto_maps && 0 != goto_map_list_size(goto_maps));
1059}
1060
1061/************************************************************************/
1065bool goto_get_turns(int *min, int *max)
1066{
1067 fc_assert_ret_val(min != NULL, FALSE);
1068 fc_assert_ret_val(max != NULL, FALSE);
1069
1070 *min = FC_INFINITY;
1071 *max = -1;
1072
1073 if (!goto_is_active()) {
1074 return FALSE;
1075 }
1076 if (NULL == goto_destination) {
1077 /* Not a valid position. */
1078 return FALSE;
1079 }
1080
1081 if (hover_state == HOVER_CONNECT) {
1082 /* In connect mode, we want to know the turn number the activity will
1083 * be finished. */
1084 int activity_time = get_activity_time(goto_destination, client_player());
1085
1087 bool moved = FALSE;
1088 int turns = goto_map->connect.initial_turns;
1089 int i;
1090
1091 for (i = 0; i < goto_map->num_parts; i++) {
1092 const struct pf_path *path = goto_map->parts[i].path;
1093
1095 if (!moved && path->length > 1) {
1096 moved = TRUE;
1097 }
1098 }
1099
1100 if (moved && activity_time > 0) {
1101 turns++;
1102 }
1103
1104 if (turns < *min) {
1105 *min = turns;
1106 }
1107 if (turns > *max) {
1108 *max = turns;
1109 }
1111 } else {
1112 /* In other modes, we want to know the turn number to reach the tile. */
1114 int turns = 0;
1115 int i;
1116
1117 for (i = 0; i < goto_map->num_parts; i++) {
1119 }
1121 && goto_map->patrol.return_path != NULL) {
1123 }
1124
1125 if (turns < *min) {
1126 *min = turns;
1127 }
1128 if (turns > *max) {
1129 *max = turns;
1130 }
1132 }
1133
1134 return TRUE;
1135}
1136
1137/************************************************************************/
1141bool goto_tile_state(const struct tile *ptile, enum goto_tile_state *state,
1142 int *turns, bool *waypoint)
1143{
1144 fc_assert_ret_val(ptile != NULL, FALSE);
1145 fc_assert_ret_val(turns != NULL, FALSE);
1146 fc_assert_ret_val(waypoint != NULL, FALSE);
1147
1148 if (!goto_is_active()) {
1149 return FALSE;
1150 }
1151
1152 *state = -1;
1153 *turns = -1;
1154 *waypoint = FALSE;
1155
1156 if (hover_state == HOVER_CONNECT) {
1157 /* In connect mode, we want to know the turn number the activity will
1158 * be finished. */
1159 int activity_time;
1160
1161 if (tile_get_known(ptile, client_player()) == TILE_UNKNOWN) {
1162 return FALSE; /* We never connect on unknown tiles. */
1163 }
1164
1165 activity_time = get_activity_time(ptile, client_player());
1166
1168 const struct pf_path *path;
1169 const struct pf_position *pos = NULL; /* Keep compiler happy! */
1170 int map_turns = goto_map->connect.initial_turns;
1171 int turns_for_map = -2;
1172 bool moved = FALSE;
1173 int i, j;
1174
1175 for (i = 0; i < goto_map->num_parts; i++) {
1176 if (i > 0 && goto_map->parts[i].start_tile == ptile) {
1177 *waypoint = TRUE;
1178 }
1179
1180 path = goto_map->parts[i].path;
1181 if (path == NULL || path->length == 0) {
1182 continue;
1183 }
1184
1185 for (j = 0; j < path->length; j++) {
1186 pos = path->positions + j;
1187 if (!moved && j > 0) {
1188 moved = TRUE;
1189 }
1190 if (pos->tile != ptile) {
1191 continue;
1192 }
1193 if (activity_time > 0) {
1194 if (map_turns + pos->turn + moved > turns_for_map) {
1195 turns_for_map = map_turns + pos->turn + moved;
1196 }
1197 } else if (pos->moves_left == 0) {
1198 if (map_turns + pos->turn > turns_for_map) {
1199 turns_for_map = map_turns + pos->turn + moved;
1200 }
1201 }
1202 }
1203 map_turns += pos->turn;
1204 }
1205
1206 if (ptile == goto_destination) {
1207 int ml = (pos != NULL ? pos->moves_left : 0);
1208
1209 if (moved && activity_time > 0) {
1210 map_turns++;
1211 }
1212 if (map_turns > *turns) {
1213 *state = (activity_time > 0 || ml == 0
1215 *turns = map_turns;
1216 } else if (map_turns == *turns
1217 && *state == GTS_MP_LEFT
1218 && (activity_time > 0 || ml == 0)) {
1219 *state = GTS_EXHAUSTED_MP;
1220 }
1221 } else {
1222 if (activity_time > 0) {
1223 if (turns_for_map > *turns) {
1224 *state = GTS_TURN_STEP;
1225 *turns = turns_for_map;
1226 }
1227 } else {
1228 if (turns_for_map + 1 > *turns) {
1229 *state = GTS_TURN_STEP;
1230 *turns = turns_for_map + 1;
1231 }
1232 }
1233 }
1235 } else {
1236 bool mark_on_map = FALSE;
1237
1238 /* In other modes, we want to know the turn number to reach the tile. */
1240 const struct tile *destination;
1241 const struct pf_path *path;
1242 const struct pf_position *pos = NULL; /* Keep compiler happy! */
1243 const struct pf_position *last_pos = NULL;
1244 int map_turns = 0;
1245 int turns_for_map = -2;
1246 int i, j;
1247
1248 for (i = 0; i < goto_map->num_parts; i++) {
1249 if (i > 0 && goto_map->parts[i].start_tile == ptile) {
1250 mark_on_map = *waypoint = TRUE;
1251 }
1252
1253 path = goto_map->parts[i].path;
1254 if (path == NULL || path->length == 0) {
1255 continue;
1256 }
1257 last_pos = path->positions;
1258 for (j = 0; j < path->length; j++) {
1259 pos = path->positions + j;
1260 /* turn to reach was increased in that step */
1261 if (pos->turn != last_pos->turn
1262 && pos->tile == ptile) {
1263 mark_on_map = TRUE;
1264 }
1265 if (pos->moves_left == 0 && last_pos->moves_left != 0
1266 && pos->tile == ptile) {
1267 mark_on_map = TRUE;
1268 }
1269 if (pos->tile == ptile
1270 /* End turn case. */
1271 && (pos->moves_left == 0
1272 /* Waiting case. */
1273 || (j < path->length - 1 && (pos + 1)->tile == ptile))
1274 && map_turns + pos->turn > turns_for_map) {
1275 turns_for_map = map_turns + pos->turn;
1276 }
1277 last_pos = pos;
1278 }
1279 map_turns += pos->turn;
1280 }
1281
1283 && goto_map->patrol.return_path != NULL
1284 && goto_map->patrol.return_path->length > 0) {
1285 path = goto_map->patrol.return_path;
1286
1287 for (j = 0; j < path->length; j++) {
1288 pos = path->positions + j;
1289 if (pos->tile == ptile
1290 /* End turn case. */
1291 && (pos->moves_left == 0
1292 /* Waiting case. */
1293 || (j < path->length - 1 && (pos + 1)->tile == ptile))
1294 && map_turns + pos->turn > turns_for_map) {
1295 turns_for_map = map_turns + pos->turn;
1296 }
1297 }
1298 map_turns += pos->turn;
1299 destination = pos->tile;
1300 } else {
1301 destination = goto_destination;
1302 }
1303
1304 if (ptile == destination) {
1305 int ml = (pos != NULL ? pos->moves_left : 0);
1306
1307 if (map_turns > *turns) {
1308 mark_on_map = TRUE;
1309 *state = (ml == 0 ? GTS_EXHAUSTED_MP : GTS_MP_LEFT);
1310 *turns = map_turns;
1311 } else if (map_turns == *turns
1312 && *state == GTS_MP_LEFT
1313 && ml == 0) {
1314 *state = GTS_EXHAUSTED_MP;
1315 }
1316 } else {
1317 if (turns_for_map > *turns) {
1318 *state = GTS_TURN_STEP;
1319 *turns = turns_for_map;
1320 }
1321 }
1323
1324 return mark_on_map;
1325 }
1326
1327 return (*turns != -1 || *waypoint);
1328}
1329
1330/************************************************************************/
1335bool is_valid_goto_draw_line(struct tile *dest_tile)
1336{
1338 if (NULL == dest_tile) {
1339 return FALSE;
1340 }
1341
1342 /* assume valid destination */
1343 goto_destination = dest_tile;
1344
1346 if (!update_last_part(goto_map, dest_tile)) {
1347 goto_destination = NULL;
1348 }
1350
1351 /* Update goto data in info label. */
1353 return (NULL != goto_destination);
1354}
1355
1356/************************************************************************/
1361{
1362 struct packet_unit_orders p;
1363
1364 if (!can_client_issue_orders()) {
1365 return;
1366 }
1367
1368 /* Clear the orders by sending an empty orders path. */
1369 log_goto_packet("Clearing orders for unit %d.", punit->id);
1370 p.unit_id32 = punit->id;
1371 p.unit_id16 = p.unit_id32;
1373 p.repeat = p.vigilant = FALSE;
1374 p.length = 0;
1376 request_unit_ssa_set(punit, SSA_NONE);
1378}
1379
1380/************************************************************************/
1383static void make_path_orders(struct unit *punit, struct pf_path *path,
1384 enum unit_orders orders,
1385 struct unit_order *final_order,
1386 struct unit_order *order_list,
1387 int *length, int *dest_tile)
1388{
1389 int i;
1390 struct tile *old_tile;
1391
1392 fc_assert_ret(path != NULL);
1394 "Unit %d has moved without goto cancellation.",
1395 punit->id);
1396 fc_assert_ret(length != NULL);
1397
1398 /* We skip the start position. */
1399 *length = path->length - 1;
1400 fc_assert(*length < MAX_LEN_ROUTE);
1401 old_tile = path->positions[0].tile;
1402
1403 /* If the path has n positions it takes n-1 steps. */
1404 for (i = 0; i < path->length - 1; i++) {
1405 struct tile *new_tile = path->positions[i + 1].tile;
1406
1407 if (same_pos(new_tile, old_tile)) {
1408 order_list[i].order = ORDER_FULL_MP;
1409 order_list[i].dir = DIR8_ORIGIN;
1410 order_list[i].activity = ACTIVITY_LAST;
1411 order_list[i].target = NO_TARGET;
1412 order_list[i].sub_target = NO_TARGET;
1413 order_list[i].action = ACTION_NONE;
1414 log_goto_packet(" packet[%d] = wait: %d,%d", i, TILE_XY(old_tile));
1415 } else {
1416 order_list[i].order = orders;
1417 order_list[i].dir = get_direction_for_step(&(wld.map), old_tile, new_tile);
1418 order_list[i].activity = ACTIVITY_LAST;
1419 order_list[i].target = NO_TARGET;
1420 order_list[i].sub_target = NO_TARGET;
1421 order_list[i].action = ACTION_NONE;
1422 log_goto_packet(" packet[%d] = move %s: %d,%d => %d,%d",
1423 i, dir_get_name(order_list[i].dir),
1424 TILE_XY(old_tile), TILE_XY(new_tile));
1425 }
1426 old_tile = new_tile;
1427 }
1428
1429 if (i > 0
1430 && order_list[i - 1].order == ORDER_MOVE
1431 && (is_non_allied_city_tile(old_tile, client_player())
1432 || is_non_allied_unit_tile(old_tile, client_player()))) {
1433 /* Won't be able to perform a regular move to the target tile... */
1434 if (!final_order) {
1435 /* ...and no final order exists. Choose what to do when the unit gets
1436 * there. */
1437 order_list[i - 1].order = ORDER_ACTION_MOVE;
1438 } else {
1439 /* ...and a final order exist. Can't assume an action move. Did the
1440 * caller hope that the situation would change before the unit got
1441 * there? */
1442
1443 /* It's currently illegal to walk into tiles with non-allied units or
1444 * cities. Some actions causes the actor to enter the target tile but
1445 * that is a part of the action it self, not a regular pre action
1446 * move. */
1447 log_verbose("unit or city blocks the path of your %s",
1449 }
1450 }
1451
1452 if (final_order) {
1453 /* Append the final order after moving to the target tile. */
1454 order_list[i].order = final_order->order;
1455 order_list[i].dir = final_order->dir;
1456 order_list[i].activity = (final_order->order == ORDER_ACTIVITY)
1457 ? final_order->activity : ACTIVITY_LAST;
1458 order_list[i].target = final_order->target;
1459 order_list[i].sub_target = final_order->sub_target;
1460 order_list[i].action = final_order->action;
1461 (*length)++;
1462 }
1463
1464 if (dest_tile) {
1465 *dest_tile = tile_index(old_tile);
1466 }
1467}
1468
1469/************************************************************************/
1472static void send_path_orders(struct unit *punit, struct pf_path *path,
1473 bool repeat, bool vigilant,
1474 enum unit_orders orders,
1475 struct unit_order *final_order)
1476{
1477 struct packet_unit_orders p;
1478
1479 if (path->length == 1 && final_order == NULL) {
1480 return; /* No path at all, no need to spam the server. */
1481 }
1482
1483 memset(&p, 0, sizeof(p));
1484 p.unit_id32 = punit->id;
1485 p.unit_id16 = p.unit_id32;
1487 p.repeat = repeat;
1488 p.vigilant = vigilant;
1489
1490 log_goto_packet("Orders for unit %d:", punit->id);
1491 log_goto_packet(" Repeat: %d. Vigilant: %d.",
1492 p.repeat, p.vigilant);
1493
1494 make_path_orders(punit, path, orders, final_order,
1495 p.orders, &p.length, &p.dest_tile);
1496
1497 request_unit_ssa_set(punit, SSA_NONE);
1499}
1500
1501/************************************************************************/
1504static void send_rally_path_orders(struct city *pcity, struct unit *punit,
1505 struct pf_path *path, bool vigilant,
1506 bool persistent,
1507 enum unit_orders orders,
1508 struct unit_order *final_order)
1509{
1510 struct packet_city_rally_point p;
1511
1512 memset(&p, 0, sizeof(p));
1513 p.city_id32 = pcity->id;
1514 p.city_id16 = p.city_id32;
1515 p.vigilant = vigilant;
1517
1518 log_goto_packet("Rally orders for city %d:", pcity->id);
1519 log_goto_packet(" Vigilant: %d.", p.vigilant);
1520
1521 make_path_orders(punit, path, orders, final_order,
1522 p.orders, &p.length, NULL);
1523
1525}
1526
1527/************************************************************************/
1530void send_goto_path(struct unit *punit, struct pf_path *path,
1531 struct unit_order *final_order)
1532{
1533 send_path_orders(punit, path, FALSE, FALSE, ORDER_MOVE, final_order);
1534}
1535
1536/************************************************************************/
1539static void send_rally_path(struct city *pcity, struct unit *punit,
1540 bool persistent, struct pf_path *path,
1541 struct unit_order *final_order)
1542{
1544 ORDER_MOVE, final_order);
1545}
1546
1547/************************************************************************/
1551bool send_goto_tile(struct unit *punit, struct tile *ptile)
1552{
1553 struct pf_parameter parameter;
1554 struct pf_map *pfm;
1555 struct pf_path *path;
1556
1557 goto_fill_parameter_base(&parameter, punit);
1558 pfm = pf_map_new(&parameter);
1559 path = pf_map_path(pfm, ptile);
1560 pf_map_destroy(pfm);
1561
1562 if (path) {
1563 send_goto_path(punit, path, NULL);
1564 pf_path_destroy(path);
1565 return TRUE;
1566 } else {
1567 return FALSE;
1568 }
1569}
1570
1571/************************************************************************/
1575bool send_rally_tile(struct city *pcity, struct tile *ptile, bool persistent)
1576{
1577 const struct unit_type *putype;
1578 struct unit *punit;
1579 struct pf_parameter parameter;
1580 struct pf_map *pfm;
1581 struct pf_path *path;
1582
1583 fc_assert_ret_val(pcity != NULL, FALSE);
1584 fc_assert_ret_val(ptile != NULL, FALSE);
1585
1586 /* Create a virtual unit of the type being produced by the city. */
1587 if (pcity->production.kind != VUT_UTYPE) {
1588 /* Can only give orders to units. */
1589 return FALSE;
1590 }
1591
1592 putype = pcity->production.value.utype;
1593 punit = unit_virtual_create(client_player(), pcity, putype,
1595 putype));
1596
1597 /* Use the unit to find a path to the destination tile. */
1598 goto_fill_parameter_base(&parameter, punit);
1599 pfm = pf_map_new(&parameter);
1600 path = pf_map_path(pfm, ptile);
1601 pf_map_destroy(pfm);
1602
1603 if (path) {
1604 /* Send orders to server. */
1605 send_rally_path(pcity, punit, persistent, path, NULL);
1607 pf_path_destroy(path);
1608
1609 return TRUE;
1610 } else {
1612
1613 return FALSE;
1614 }
1615}
1616
1617/************************************************************************/
1621bool send_attack_tile(struct unit *punit, struct tile *ptile)
1622{
1623 struct pf_parameter parameter;
1624 struct pf_map *pfm;
1625 struct pf_path *path;
1626
1627 goto_fill_parameter_base(&parameter, punit);
1628 parameter.move_rate = 0;
1629 parameter.is_pos_dangerous = NULL;
1630 parameter.get_moves_left_req = NULL;
1631 pfm = pf_map_new(&parameter);
1632 path = pf_map_path(pfm, ptile);
1633 pf_map_destroy(pfm);
1634
1635 if (path) {
1636 send_path_orders(punit, path, false, false, ORDER_ACTION_MOVE, NULL);
1637 pf_path_destroy(path);
1638 return TRUE;
1639 }
1640 return FALSE;
1641}
1642
1643/************************************************************************/
1648{
1651 int i;
1652 struct pf_path *path = NULL;
1653 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1654
1655 if (NULL == last_part->path) {
1656 /* Cannot move there */
1657 continue;
1658 }
1659
1660 for (i = 0; i < goto_map->num_parts; i++) {
1662 }
1664
1666
1669}
1670
1671/************************************************************************/
1674static bool order_recursive_roads(struct tile *ptile, struct extra_type *pextra,
1675 struct packet_unit_orders *p, int rec)
1676{
1677 if (rec > MAX_EXTRA_TYPES) {
1678 return FALSE;
1679 }
1680
1681 if (!is_extra_caused_by(pextra, EC_ROAD)) {
1682 return FALSE;
1683 }
1684
1685 if (tile_has_extra(ptile, pextra)) {
1686 /* No need to build what is already there. */
1687 return TRUE;
1688 }
1689
1690 extra_deps_iterate(&(pextra->reqs), pdep) {
1691 if (!tile_has_extra(ptile, pdep)) {
1692 if (!order_recursive_roads(ptile, pdep, p, rec + 1)) {
1693 return FALSE;
1694 }
1695 }
1697
1699 p->orders[p->length].dir = DIR8_ORIGIN;
1700 p->orders[p->length].activity = ACTIVITY_LAST;
1701 p->orders[p->length].target = ptile->index;
1702 p->orders[p->length].sub_target = extra_index(pextra);
1703 p->orders[p->length].action = ACTION_ROAD;
1704 p->length++;
1705
1706 return TRUE;
1707}
1708
1709/************************************************************************/
1713void send_connect_route(enum unit_activity activity,
1714 struct extra_type *tgt)
1715{
1718 int i;
1719 struct packet_unit_orders p;
1720 struct tile *old_tile;
1721 struct pf_path *path = NULL;
1722 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1723
1724 if (NULL == last_part->path) {
1725 /* Cannot move there */
1726 continue;
1727 }
1728
1729 memset(&p, 0, sizeof(p));
1730
1731 i = 0;
1732 do {
1734 i++;
1735 } while (i < goto_map->num_parts);
1736
1737 p.unit_id32 = punit->id;
1738 p.unit_id16 = p.unit_id32;
1740 p.repeat = FALSE;
1741 p.vigilant = FALSE; /* Should be TRUE? */
1742
1743 p.length = 0;
1744 old_tile = path->positions[0].tile;
1745
1746 for (i = 0; i < path->length; i++) {
1747 switch (activity) {
1748 case ACTIVITY_IRRIGATE:
1749 if (!tile_has_extra(old_tile, tgt)) {
1750 /* Assume the unit can irrigate or we wouldn't be here. */
1753 p.orders[p.length].activity = ACTIVITY_LAST;
1754 p.orders[p.length].target = old_tile->index;
1755 p.orders[p.length].sub_target = extra_index(tgt);
1756 p.orders[p.length].action = ACTION_IRRIGATE;
1757 p.length++;
1758 }
1759 break;
1760 case ACTIVITY_GEN_ROAD:
1761 order_recursive_roads(old_tile, tgt, &p, 0);
1762 break;
1763 default:
1764 log_error("Invalid connect activity: %d.", activity);
1765 break;
1766 }
1767
1768 if (i != path->length - 1) {
1769 struct tile *new_tile = path->positions[i + 1].tile;
1770
1771 fc_assert(!same_pos(new_tile, old_tile));
1772
1775 old_tile, new_tile);
1776 p.orders[p.length].activity = ACTIVITY_LAST;
1780 p.length++;
1781
1782 old_tile = new_tile;
1783 }
1784 }
1785
1786 p.dest_tile = tile_index(old_tile);
1787
1788 request_unit_ssa_set(punit, SSA_NONE);
1791}
1792
1793/************************************************************************/
1800static bool order_wants_direction(enum unit_orders order, action_id act_id,
1801 struct tile *tgt_tile)
1802{
1803 switch (order) {
1804 case ORDER_MOVE:
1805 case ORDER_ACTION_MOVE:
1806 /* Not only is it legal. It is mandatory. A move is always done in a
1807 * direction. */
1808 return TRUE;
1810 if (!action_id_distance_accepted(act_id, 0)) {
1811 /* Always illegal to do to a target on the actor's own tile. */
1812 return TRUE;
1813 }
1814
1815 if (!action_id_distance_accepted(act_id, 1)) {
1816 /* Always illegal to perform to a target on a neighbor tile. */
1817 return FALSE;
1818 }
1819
1820 if (is_non_allied_city_tile(tgt_tile, client_player())
1821 || is_non_allied_unit_tile(tgt_tile, client_player())) {
1822 /* Won't be able to move to the target tile to perform the action on
1823 * top of it. */
1824 /* TODO: Detect situations where it also would be illegal to perform
1825 * the action from the neighbor tile. */
1826 return TRUE;
1827 }
1828
1830 /* Prefer efficiency over safety among allies. */
1832 return TRUE;
1833 }
1834
1835 return FALSE;
1836 default:
1837 return FALSE;
1838 }
1839}
1840
1841/************************************************************************/
1845static bool order_demands_direction(enum unit_orders order, action_id act_id)
1846{
1847 switch (order) {
1848 case ORDER_MOVE:
1849 case ORDER_ACTION_MOVE:
1850 /* A move is always done in a direction. */
1851 return TRUE;
1853 if (!action_id_distance_accepted(act_id, 0)) {
1854 /* Always illegal to do to a target on the actor's own tile. */
1855 return TRUE;
1856 }
1857
1858 return FALSE;
1859 default:
1860 return FALSE;
1861 }
1862}
1863
1864/************************************************************************/
1871{
1874 int i;
1875 struct tile *tgt_tile;
1876 struct pf_path *path = NULL;
1877 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1878
1879 if (NULL == last_part->path) {
1880 /* Cannot move there */
1881 continue;
1882 }
1883
1884 i = 0;
1885 do {
1887 i++;
1888 } while (i < goto_map->num_parts);
1889
1891
1892 tgt_tile = pf_path_last_position(path)->tile;
1893
1894 /* Make the last move in a plain goto try to pop up the action
1895 * selection dialog rather than moving to the last tile if it contains
1896 * a domestic, allied or team mate city, unit or unit stack. This can,
1897 * in cases where the action requires movement left, save a turn. */
1900 && ((is_allied_city_tile(tgt_tile, client_player())
1901 || is_allied_unit_tile(tgt_tile, client_player()))
1903 ACTION_ANY,
1904 DRO_FOREIGN,
1905 FALSE)
1907 ACTION_ANY,
1908 DS_ALLIANCE,
1909 TRUE)
1911 ACTION_ANY,
1912 DS_TEAM,
1913 TRUE)))) {
1914 /* Try to pop up the action selection dialog before moving to the
1915 * target tile. */
1917 }
1918
1919 /* Handle single-step goto like single-step move. */
1920 if (goto_last_order == ORDER_LAST && path->length == 2
1923 }
1924
1925 if (goto_last_order == ORDER_LAST) {
1926 send_goto_path(punit, path, NULL);
1927 } else if (path->length > 1
1930 struct unit_order order;
1931 int last_order_dir;
1932 struct tile *on_tile;
1933 int last_order_target = NO_TARGET;
1934
1935 if (path->length > 1 && goto_last_tgt == NO_TARGET
1936 && ((on_tile = path->positions[path->length - 2].tile))
1938 tgt_tile)
1939 && !same_pos(on_tile, tgt_tile)) {
1940 /* The last order prefers to handle the last direction it self.
1941 * There exists a tile before the target tile to do it from. */
1942
1943 /* Give the last path direction to the final order. */
1944 last_order_dir = get_direction_for_step(&(wld.map), on_tile, tgt_tile);
1945
1946 /* The last path direction is now spent. */
1947 pf_path_backtrack(path, on_tile);
1948 } else {
1952
1953 /* Target the tile the actor is standing on or goto_last_tgt. */
1954 last_order_dir = DIR8_ORIGIN;
1955 }
1956
1958 last_order_target = (goto_last_tgt == NO_TARGET
1959 ? tgt_tile->index : goto_last_tgt);
1960 last_order_dir = DIR8_ORIGIN;
1961 }
1962
1963 order.order = goto_last_order;
1964 order.dir = last_order_dir;
1965 order.activity = ACTIVITY_LAST;
1966 order.target = last_order_target;
1968 order.action = goto_last_action;
1969
1970 /* ORDER_ACTIVITY would require real activity */
1972
1973 send_goto_path(punit, path, &order);
1974 }
1975 pf_path_destroy(path);
1977}
1978
1979/************************************************************************/
1984{
1985 struct pf_parameter parameter;
1986 struct pf_map *pfm;
1987 struct pf_path *path = NULL;
1988
1990 /* We're already on a city - don't go anywhere. */
1991 return NULL;
1992 }
1993
1994 goto_fill_parameter_base(&parameter, punit);
1995 pfm = pf_map_new(&parameter);
1996
1997 pf_map_tiles_iterate(pfm, ptile, FALSE) {
1998 if (is_allied_city_tile(ptile, unit_owner(punit))) {
1999 path = pf_map_path(pfm, ptile);
2000 break;
2001 }
2003
2004 pf_map_destroy(pfm);
2005
2006 return path;
2007}
2008
2009/************************************************************************/
2012struct tile *tile_before_end_path(struct unit *punit, struct tile *ptile)
2013{
2014 struct pf_parameter parameter;
2015 struct pf_map *pfm;
2016 struct tile *dtile;
2017 struct pf_path *path;
2018
2019 goto_fill_parameter_base(&parameter, punit);
2020 parameter.move_rate = 0;
2021 parameter.is_pos_dangerous = NULL;
2022 parameter.get_moves_left_req = NULL;
2023 pfm = pf_map_new(&parameter);
2024 path = pf_map_path(pfm, ptile);
2025 if (path == NULL) {
2026 return NULL;
2027 }
2028 if (path->length < 2) {
2029 dtile = NULL;
2030 } else {
2031 dtile = path->positions[path->length - 2].tile;
2032 }
2033 pf_map_destroy(pfm);
2034
2035 return dtile;
2036}
bool action_id_exists(const action_id act_id)
Definition actions.c:1697
#define action_id_distance_accepted(act_id, distance)
Definition actions.h:698
#define ACTION_ANY
Definition actions.h:292
#define action_id_has_result_safe(act_id, result)
Definition actions.h:670
#define ACTION_NONE
Definition actions.h:295
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
int city_production_unit_veteran_level(struct city *pcity, const struct unit_type *punittype)
Definition city.c:789
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:748
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:724
struct civclient client
bool can_client_issue_orders(void)
#define client_player()
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:389
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:1332
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:2055
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:482
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:28
@ HOVER_ACT_SEL_TGT
Definition control.h:31
@ HOVER_NONE
Definition control.h:26
@ HOVER_CONNECT
Definition control.h:29
@ HOVER_PATROL
Definition control.h:30
@ HOVER_GOTO_SEL_TGT
Definition control.h:32
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:73
#define extra_type_iterate(_p)
Definition extras.h:291
#define extra_deps_iterate(_reqs, _dep)
Definition extras.h:338
#define extra_type_iterate_end
Definition extras.h:297
#define is_extra_caused_by(e, c)
Definition extras.h:196
#define extra_index(_e_)
Definition extras.h:177
#define extra_deps_iterate_end
Definition extras.h:346
#define extra_road_get(_e_)
Definition extras.h:185
#define NO_TARGET
Definition fc_types.h:324
#define DIR8_ORIGIN
Definition fc_types.h:427
int action_id
Definition fc_types.h:359
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
struct world wld
Definition game.c:58
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:667
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:798
static void fill_parameter_part(struct pf_parameter *param, const struct goto_map *goto_map, const struct part *p)
Definition goto.c:407
#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:688
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:1383
static void goto_path_undraw(const struct pf_path *path)
Definition goto.c:236
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:872
static bool order_recursive_roads(struct tile *ptile, struct extra_type *pextra, struct packet_unit_orders *p, int rec)
Definition goto.c:1674
static void goto_fill_parameter_full(struct goto_map *goto_map, const struct unit *punit)
Definition goto.c:921
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:555
static enum tile_behavior get_TB_caravan(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition goto.c:585
void exit_goto_state(void)
Definition goto.c:1019
struct tile * tile_before_end_path(struct unit *punit, struct tile *ptile)
Definition goto.c:2012
bool goto_is_active(void)
Definition goto.c:1056
bool send_attack_tile(struct unit *punit, struct tile *ptile)
Definition goto.c:1621
struct pf_path * path_to_nearest_allied_city(struct unit *punit)
Definition goto.c:1983
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:888
void init_client_goto(void)
Definition goto.c:152
#define goto_map_unit_iterate_end
Definition goto.c:88
void send_patrol_route(void)
Definition goto.c:1647
bool send_rally_tile(struct city *pcity, struct tile *ptile, bool persistent)
Definition goto.c:1575
static bool order_wants_direction(enum unit_orders order, action_id act_id, struct tile *tgt_tile)
Definition goto.c:1800
static void remove_last_part(struct goto_map *goto_map)
Definition goto.c:469
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:1504
bool is_valid_goto_draw_line(struct tile *dest_tile)
Definition goto.c:1335
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:1472
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:258
static enum tile_behavior get_TB_aggr(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition goto.c:565
#define goto_map_list_iterate(gotolist, pgoto)
Definition goto.c:78
static void reset_last_part(struct goto_map *goto_map)
Definition goto.c:394
#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:487
bool send_goto_tile(struct unit *punit, struct tile *ptile)
Definition goto.c:1551
static struct unit * goto_map_unit(const struct goto_map *goto_map)
Definition goto.c:139
bool goto_pop_waypoint(void)
Definition goto.c:524
#define log_goto_packet
Definition goto.c:45
void send_connect_route(enum unit_activity activity, struct extra_type *tgt)
Definition goto.c:1713
void goto_unit_killed(struct unit *punit)
Definition goto.c:1037
void free_client_goto(void)
Definition goto.c:162
void enter_goto_state(struct unit_list *punits)
Definition goto.c:998
void send_goto_route(void)
Definition goto.c:1870
bool is_valid_goto_destination(const struct tile *ptile)
Definition goto.c:179
static void goto_path_redraw(const struct pf_path *new_path, const struct pf_path *old_path)
Definition goto.c:187
bool goto_get_turns(int *min, int *max)
Definition goto.c:1065
static int get_activity_time(const struct tile *ptile, const struct player *pplayer)
Definition goto.c:611
static void goto_map_free(struct goto_map *goto_map)
Definition goto.c:122
void request_orders_cleared(struct unit *punit)
Definition goto.c:1360
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:1539
static bool order_demands_direction(enum unit_orders order, action_id act_id)
Definition goto.c:1845
void send_goto_path(struct unit *punit, struct pf_path *path, struct unit_order *final_order)
Definition goto.c:1530
static void add_part(struct goto_map *goto_map)
Definition goto.c:438
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:258
static GtkWidget * persistent
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_msg(condition, message,...)
Definition log.h:205
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
int get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1345
const char * dir_get_name(enum direction8 dir)
Definition map.c:1144
bool is_cardinal_dir(enum direction8 dir)
Definition map.c:1314
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
bool is_valid_dir(enum direction8 dir)
Definition map.c:1258
#define adjc_iterate_end
Definition map.h:427
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
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:264
struct client_options gui_options
Definition options.c:71
#define MAX_LEN_ROUTE
Definition packets.h:44
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:840
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:1205
#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:309
int id
Definition city.h:315
struct universal production
Definition city.h:382
struct connection conn
Definition client_main.h:96
bool goto_into_unknown
Definition options.h:153
bool popup_last_move_to_allied
Definition options.h:163
bv_extras conflicts
Definition extras.h:129
struct requirement_vector reqs
Definition extras.h:102
struct goto_map::@132::@135 patrol
int num_parts
Definition goto.c:62
struct pf_path * return_path
Definition goto.c:68
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::@132::@134 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
enum direction8 dir_to_next_pos
struct tile * tile
int move_cost
Definition road.h:78
int irrigation_time
Definition terrain.h:210
Definition tile.h:49
int index
Definition tile.h:50
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:138
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
struct unit * transporter
Definition unit.h:183
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
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:1018
bool tile_has_road(const struct tile *ptile, const struct road_type *proad)
Definition tile.c:829
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:966
enum known_type tile_get_known(const struct tile *ptile, const struct player *pplayer)
Definition tile.c:386
#define tile_index(_pt_)
Definition tile.h:87
known_type
Definition tile.h:34
@ TILE_UNKNOWN
Definition tile.h:35
#define ACTIVITY_FACTOR
Definition tile.h:168
#define tile_terrain(_tile)
Definition tile.h:113
#define TILE_XY(ptile)
Definition tile.h:42
#define tile_has_extra(ptile, pextra)
Definition tile.h:150
const struct unit_type * utype
Definition fc_types.h:604
struct unit * transporter_for_unit_at(const struct unit *pcargo, const struct tile *ptile)
Definition unit.c:1914
int get_activity_rate(const struct unit *punit)
Definition unit.c:482
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1625
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1721
#define unit_tile(_pu)
Definition unit.h:395
unit_orders
Definition unit.h:37
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:406
#define unit_owner(_pu)
Definition unit.h:394
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:430
#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:1639
bool utype_may_act_at_all(const struct unit_type *putype)
Definition unittype.c:431
bool utype_acts_hostile(const struct unit_type *putype)
Definition unittype.c:515
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:1069