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)
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 ***********************************************************************/
15 #include <fc_config.h>
35 #include "client_main.h"
37 #include "mapview_g.h"
41 #include "mapctrl_common.h"
43 #define LOG_GOTO_PATH LOG_DEBUG
44 #define log_goto_path log_debug
45 #define log_goto_packet log_debug
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.
53 struct tile
*start_tile
, *end_tile
;
54 int end_moves_left
, end_fuel_left
;
68 struct pf_path
*return_path
;
71 struct pf_parameter
template;
74 /* get 'struct goto_map_list' and related functions: */
75 #define SPECLIST_TAG goto_map
76 #define SPECLIST_TYPE struct goto_map
78 #define goto_map_list_iterate(gotolist, pgoto) \
79 TYPED_LIST_ITERATE(struct goto_map, gotolist, pgoto)
80 #define goto_map_list_iterate_end \
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);
88 #define goto_map_unit_iterate_end \
89 } goto_map_list_iterate_end;
91 static struct goto_map_list
*goto_maps
= NULL
;
92 static bool goto_warned
= FALSE
;
94 static void reset_last_part(struct goto_map
*goto_map
);
95 static void remove_last_part(struct goto_map
*goto_map
);
96 static void fill_parameter_part(struct pf_parameter
*param
,
97 const struct goto_map
*goto_map
,
98 const struct part
*p
);
100 /**************************************************************************
101 Various stuff for the goto routes
102 **************************************************************************/
103 static struct tile
*goto_destination
= NULL
;
105 /****************************************************************************
106 Create a new goto map.
107 ****************************************************************************/
108 static struct goto_map
*goto_map_new(struct unit
*punit
)
110 struct goto_map
*goto_map
= fc_malloc(sizeof(*goto_map
));
112 goto_map
->focus
= punit
;
113 goto_map
->parts
= NULL
;
114 goto_map
->num_parts
= 0;
119 /****************************************************************************
120 Free an existing goto map.
121 ****************************************************************************/
122 static void goto_map_free(struct goto_map
*goto_map
)
124 if (NULL
!= goto_map
->parts
) {
125 while (goto_map
->num_parts
> 0) {
126 remove_last_part(goto_map
);
128 free(goto_map
->parts
);
130 if (hover_state
== HOVER_PATROL
&& goto_map
->patrol
.return_path
) {
131 pf_path_destroy(goto_map
->patrol
.return_path
);
136 /****************************************************************************
137 Returns the unit associated with the goto map.
138 ****************************************************************************/
139 static struct unit
*goto_map_unit(const struct goto_map
*goto_map
)
141 struct unit
*punit
= goto_map
->focus
;
143 fc_assert(punit
!= NULL
);
144 fc_assert(unit_is_in_focus(punit
));
145 fc_assert(punit
== player_unit_by_number(client_player(), punit
->id
));
149 /**********************************************************************
150 Called only by handle_map_info() in client/packhand.c.
151 ***********************************************************************/
152 void init_client_goto(void)
156 goto_maps
= goto_map_list_new();
159 /**********************************************************************
160 Called above, and by control_done() in client/control.c.
161 ***********************************************************************/
162 void free_client_goto(void)
164 if (NULL
!= goto_maps
) {
165 goto_map_list_iterate(goto_maps
, goto_map
) {
166 goto_map_free(goto_map
);
167 } goto_map_list_iterate_end
;
168 goto_map_list_destroy(goto_maps
);
172 goto_destination
= NULL
;
176 /**********************************************************************
177 Determines if a goto to the destination tile is allowed.
178 ***********************************************************************/
179 bool is_valid_goto_destination(const struct tile
*ptile
)
181 return (NULL
!= goto_destination
&& ptile
== goto_destination
);
184 /****************************************************************************
186 ****************************************************************************/
187 static void goto_path_redraw(const struct pf_path
*new_path
,
188 const struct pf_path
*old_path
)
193 fc_assert_ret(new_path
!= NULL
);
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
;
202 if (old_pos
->dir_to_next_pos
!= new_pos
->dir_to_next_pos
203 || old_pos
->tile
!= new_pos
->tile
) {
209 /* Erase everything we cannot reuse. */
210 for (; i
< old_path
->length
- 1; i
++) {
211 struct pf_position
*pos
= old_path
->positions
+ i
;
213 if (is_valid_dir(pos
->dir_to_next_pos
)) {
214 mapdeco_remove_gotoline(pos
->tile
, pos
->dir_to_next_pos
);
216 fc_assert(pos
->tile
== (pos
+ 1)->tile
);
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
;
225 if (is_valid_dir(pos
->dir_to_next_pos
)) {
226 mapdeco_add_gotoline(pos
->tile
, pos
->dir_to_next_pos
);
228 fc_assert(pos
->tile
== (pos
+ 1)->tile
);
233 /****************************************************************************
235 ****************************************************************************/
236 static void goto_path_undraw(const struct pf_path
*path
)
240 fc_assert_ret(path
!= NULL
);
242 for (i
= 0; i
< path
->length
- 1; i
++) {
243 struct pf_position
*pos
= path
->positions
+ i
;
245 if (is_valid_dir(pos
->dir_to_next_pos
)) {
246 mapdeco_remove_gotoline(pos
->tile
, pos
->dir_to_next_pos
);
248 fc_assert(pos
->tile
== (pos
+ 1)->tile
);
253 /**********************************************************************
254 Change the destination of the last part to the given location.
255 If a path cannot be found, the destination is set to the start.
256 Return TRUE when the new path is valid.
257 ***********************************************************************/
258 static bool update_last_part(struct goto_map
*goto_map
,
261 struct pf_path
*old_path
, *new_path
;
262 struct part
*p
= &goto_map
->parts
[goto_map
->num_parts
- 1];
265 if (old_path
!= NULL
&& pf_path_last_position(old_path
)->tile
== ptile
) {
266 /* Nothing to update. */
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
);
275 log_goto_path(" no path found");
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. */
282 log_error("No path found to reach the start point.");
286 if (old_path
!= NULL
) {
287 goto_path_undraw(old_path
);
288 pf_path_destroy(old_path
);
291 if (hover_state
== HOVER_PATROL
292 && goto_map
->patrol
.return_path
!= NULL
) {
293 goto_path_undraw(goto_map
->patrol
.return_path
);
294 pf_path_destroy(goto_map
->patrol
.return_path
);
295 goto_map
->patrol
.return_path
= NULL
;
300 reset_last_part(goto_map
);
304 log_goto_path(" path found:");
305 pf_path_print(new_path
, LOG_GOTO_PATH
);
309 p
->end_moves_left
= pf_path_last_position(new_path
)->moves_left
;
310 p
->end_fuel_left
= pf_path_last_position(new_path
)->fuel_left
;
312 if (hover_state
== HOVER_PATROL
) {
313 struct pf_parameter parameter
;
315 struct pf_path
*return_path
;
317 fill_parameter_part(¶meter
, goto_map
, p
);
318 pfm
= pf_map_new(¶meter
);
319 return_path
= pf_map_path(pfm
, goto_map
->parts
[0].start_tile
);
322 if (return_path
== NULL
) {
323 log_goto_path(" no return path found");
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. */
330 log_error("No path found to reach the start point.");
334 if (old_path
!= NULL
) {
335 goto_path_undraw(old_path
);
336 pf_path_destroy(old_path
);
338 pf_path_destroy(new_path
);
340 if (goto_map
->patrol
.return_path
!= NULL
) {
341 goto_path_undraw(goto_map
->patrol
.return_path
);
342 pf_path_destroy(goto_map
->patrol
.return_path
);
343 goto_map
->patrol
.return_path
= NULL
;
349 p
->end_tile
= pf_path_last_position(old_path
)->tile
;
350 p
->end_moves_left
= pf_path_last_position(old_path
)->moves_left
;
351 p
->end_fuel_left
= pf_path_last_position(old_path
)->fuel_left
;
352 pf_path_destroy(new_path
);
353 reset_last_part(goto_map
);
357 log_goto_path(" returned path found:");
358 pf_path_print(return_path
, LOG_GOTO_PATH
);
360 if (goto_map
->patrol
.return_path
!= NULL
) {
361 /* We cannot re-use old path because:
362 * 1- the start tile isn't the same.
363 * 2- the turn number neither (impossible to do in backward mode). */
364 goto_path_undraw(goto_map
->patrol
.return_path
);
365 pf_path_destroy(goto_map
->patrol
.return_path
);
367 goto_path_redraw(return_path
, NULL
);
368 goto_map
->patrol
.return_path
= return_path
;
371 goto_path_redraw(new_path
, old_path
);
372 pf_path_destroy(old_path
);
374 log_goto_path("To (%d,%d) part %d: total_MC: %d",
375 TILE_XY(ptile
), goto_map
->num_parts
,
376 pf_path_last_position(hover_state
== HOVER_PATROL
377 ? goto_map
->patrol
.return_path
378 : new_path
)->total_MC
);
383 /**********************************************************************
384 Change the drawn path to a size of 0 steps by setting it to the
386 ***********************************************************************/
387 static void reset_last_part(struct goto_map
*goto_map
)
389 struct part
*p
= &goto_map
->parts
[goto_map
->num_parts
- 1];
391 if (NULL
!= p
->path
) {
392 /* Otherwise no need to update */
393 update_last_part(goto_map
, p
->start_tile
);
397 /****************************************************************************
398 Fill pathfinding parameter for adding a new part.
399 ****************************************************************************/
400 static void fill_parameter_part(struct pf_parameter
*param
,
401 const struct goto_map
*goto_map
,
402 const struct part
*p
)
404 *param
= goto_map
->template;
406 if (p
->start_tile
== p
->end_tile
) {
407 /* Copy is enough, we didn't move last part. */
408 fc_assert(p
->path
->length
== 1);
412 param
->start_tile
= p
->end_tile
;
413 param
->moves_left_initially
= p
->end_moves_left
;
414 param
->fuel_left_initially
= p
->end_fuel_left
;
415 if (can_exist_at_tile(&(wld
.map
), param
->utype
, param
->start_tile
)) {
416 param
->transported_by_initially
= NULL
;
418 const struct unit
*transporter
=
419 transporter_for_unit_at(goto_map_unit(goto_map
), param
->start_tile
);
421 param
->transported_by_initially
= (transporter
!= NULL
422 ? unit_type_get(transporter
) : NULL
);
426 /**********************************************************************
427 Add a part. Depending on the num of already existing parts the start
428 of the new part is either the unit position (for the first part) or
429 the destination of the last part (not the first part).
430 ***********************************************************************/
431 static void add_part(struct goto_map
*goto_map
)
434 struct pf_parameter parameter
;
435 struct unit
*punit
= goto_map_unit(goto_map
);
437 goto_map
->num_parts
++;
439 fc_realloc(goto_map
->parts
,
440 goto_map
->num_parts
* sizeof(*goto_map
->parts
));
441 p
= &goto_map
->parts
[goto_map
->num_parts
- 1];
443 if (goto_map
->num_parts
== 1) {
445 p
->start_tile
= unit_tile(punit
);
446 parameter
= goto_map
->template;
448 struct part
*prev
= &goto_map
->parts
[goto_map
->num_parts
- 2];
450 p
->start_tile
= prev
->end_tile
;
451 fill_parameter_part(¶meter
, goto_map
, prev
);
454 p
->end_tile
= p
->start_tile
;
455 parameter
.start_tile
= p
->start_tile
;
456 p
->map
= pf_map_new(¶meter
);
459 /**********************************************************************
460 Remove the last part, erasing the corresponding path segment.
461 ***********************************************************************/
462 static void remove_last_part(struct goto_map
*goto_map
)
464 struct part
*p
= &goto_map
->parts
[goto_map
->num_parts
- 1];
466 fc_assert_ret(goto_map
->num_parts
>= 1);
468 reset_last_part(goto_map
);
470 /* We do not always have a path */
471 pf_path_destroy(p
->path
);
473 pf_map_destroy(p
->map
);
474 goto_map
->num_parts
--;
477 /**********************************************************************
478 Inserts a waypoint at the end of the current goto line.
479 ***********************************************************************/
480 bool goto_add_waypoint(void)
482 bool duplicate_of_last
= TRUE
;
484 fc_assert_ret_val(goto_is_active(), FALSE
);
485 if (NULL
== goto_destination
) {
486 /* Not a valid position. */
490 goto_map_list_iterate(goto_maps
, goto_map
) {
491 const struct part
*last_part
= &goto_map
->parts
[goto_map
->num_parts
- 1];
493 if (last_part
->path
== NULL
) {
494 /* The current part has zero length. */
497 if (last_part
->start_tile
!= last_part
->end_tile
) {
498 duplicate_of_last
= FALSE
;
500 } goto_map_list_iterate_end
;
501 if (duplicate_of_last
) {
505 goto_map_list_iterate(goto_maps
, goto_map
) {
507 } goto_map_list_iterate_end
;
509 refresh_tile_mapcanvas(goto_destination
, FALSE
, FALSE
);
513 /**********************************************************************
514 Returns whether there were any waypoint popped (we don't remove the
516 ***********************************************************************/
517 bool goto_pop_waypoint(void)
521 fc_assert_ret_val(goto_is_active(), FALSE
);
522 goto_map_list_iterate(goto_maps
, goto_map
) {
523 struct part
*p
= &goto_map
->parts
[goto_map
->num_parts
- 1];
524 struct tile
*end_tile
= p
->end_tile
;
526 if (goto_map
->num_parts
== 1) {
527 /* we don't have any waypoint but the start pos. */
532 remove_last_part(goto_map
);
535 * Set the end position of the previous part (now the last) to the
536 * end position of the last part (now gone). I.e. redraw a line to
537 * the mouse position.
539 update_last_part(goto_map
, end_tile
);
540 } goto_map_list_iterate_end
;
544 /**********************************************************************
545 PF callback to get the path with the minimal number of steps (out of
547 ***********************************************************************/
548 static int get_EC(const struct tile
*ptile
, enum known_type known
,
549 const struct pf_parameter
*param
)
554 /**********************************************************************
555 PF callback to prohibit going into the unknown. Also makes sure we
556 don't plan our route through enemy city/tile.
557 ***********************************************************************/
558 static enum tile_behavior
get_TB_aggr(const struct tile
*ptile
,
559 enum known_type known
,
560 const struct pf_parameter
*param
)
562 if (known
== TILE_UNKNOWN
) {
563 if (!gui_options
.goto_into_unknown
) {
566 } else if (is_non_allied_unit_tile(ptile
, param
->owner
)
567 || is_non_allied_city_tile(ptile
, param
->owner
)) {
568 /* Can attack but can't count on going through */
569 return TB_DONT_LEAVE
;
574 /**********************************************************************
575 PF callback for caravans. Caravans doesn't go into the unknown and
576 don't attack enemy units but enter enemy cities.
577 ***********************************************************************/
578 static enum tile_behavior
get_TB_caravan(const struct tile
*ptile
,
579 enum known_type known
,
580 const struct pf_parameter
*param
)
582 if (known
== TILE_UNKNOWN
) {
583 if (!gui_options
.goto_into_unknown
) {
586 } else if (is_non_allied_city_tile(ptile
, param
->owner
)) {
587 /* Units that can establish a trade route, enter a market place or
588 * establish an embassy can travel to, but not through, enemy cities.
589 * FIXME: ACTION_HELP_WONDER units cannot. */
590 return TB_DONT_LEAVE
;
591 } else if (is_non_allied_unit_tile(ptile
, param
->owner
)) {
592 /* Note this must be below the city check. */
596 /* Includes empty, allied, or allied-city tiles. */
600 /****************************************************************************
601 Return the number of MP needed to do the connect activity at this
602 position. A negative number means it's impossible.
603 ****************************************************************************/
604 static int get_activity_time(const struct tile
*ptile
,
605 const struct player
*pplayer
)
607 struct terrain
*pterrain
= tile_terrain(ptile
);
610 fc_assert_ret_val(hover_state
== HOVER_CONNECT
, -1);
612 switch (connect_activity
) {
613 case ACTIVITY_IRRIGATE
:
614 if (pterrain
->irrigation_time
== 0) {
617 extra_type_iterate(pextra
) {
618 if (BV_ISSET(connect_tgt
->conflicts
, extra_index(pextra
))
619 && tile_has_extra(ptile
, pextra
)) {
620 /* Don't replace old extras. */
623 } extra_type_iterate_end
;
625 if (tile_has_extra(ptile
, connect_tgt
)) {
629 activity_mc
= pterrain
->irrigation_time
;
631 case ACTIVITY_GEN_ROAD
:
632 fc_assert(is_extra_caused_by(connect_tgt
, EC_ROAD
));
634 if (!tile_has_extra(ptile
, connect_tgt
)) {
638 vtile
= tile_virtual_new(ptile
);
639 single_mc
= check_recursive_road_connect(vtile
, connect_tgt
, NULL
, pplayer
, 0);
640 tile_virtual_destroy(vtile
);
646 activity_mc
+= single_mc
;
650 log_error("Invalid connect activity: %d.", connect_activity
);
656 /****************************************************************************
657 When building a road or a railroad, we don't want to go next to
659 ****************************************************************************/
660 static bool is_non_allied_city_adjacent(const struct player
*pplayer
,
661 const struct tile
*ptile
)
663 adjc_iterate(&(wld
.map
), ptile
, tile1
) {
664 if (is_non_allied_city_tile(tile1
, pplayer
)) {
672 /****************************************************************************
673 PF jumbo callback for the cost of a connect by road.
674 In road-connect mode we are concerned with
675 (1) the number of steps of the resulting path
676 (2) (the tie-breaker) time to build the path (travel plus activity time).
677 In rail-connect the priorities are reversed.
679 param->data should contain the result of get_activity_rate(punit).
680 ****************************************************************************/
681 static int get_connect_road(const struct tile
*src_tile
, enum direction8 dir
,
682 const struct tile
*dest_tile
,
683 int src_cost
, int src_extra
,
684 int *dest_cost
, int *dest_extra
,
685 const struct pf_parameter
*param
)
687 int activity_time
, move_cost
, moves_left
;
688 int total_cost
, total_extra
;
689 struct road_type
*proad
;
691 if (tile_get_known(dest_tile
, param
->owner
) == TILE_UNKNOWN
) {
695 activity_time
= get_activity_time(dest_tile
, param
->owner
);
696 if (activity_time
< 0) {
700 move_cost
= param
->get_MC(src_tile
, PF_MS_NATIVE
, dest_tile
, PF_MS_NATIVE
,
702 if (move_cost
== PF_IMPOSSIBLE_MC
) {
706 if (is_non_allied_city_adjacent(param
->owner
, dest_tile
)) {
707 /* We don't want to build roads to enemies plus get ZoC problems */
711 fc_assert(connect_activity
== ACTIVITY_GEN_ROAD
);
713 proad
= extra_road_get(connect_tgt
);
716 /* No suitable road type available */
720 /* Ok, the move is possible. What are the costs? */
722 /* Extra cost here is the final length of the road */
723 total_extra
= src_extra
+ 1;
725 /* Special cases: get_MC function doesn't know that we would have built
726 * a road (railroad) on src tile by that time.
727 * We assume that settler building the road can also travel it. */
728 if (tile_has_road(dest_tile
, proad
)) {
729 move_cost
= proad
->move_cost
;
732 move_cost
= MIN(move_cost
, param
->move_rate
);
733 total_cost
= src_cost
;
734 moves_left
= param
->move_rate
- (src_cost
% param
->move_rate
);
735 if (moves_left
< move_cost
) {
736 total_cost
+= moves_left
;
738 total_cost
+= move_cost
;
741 /* Now need to include the activity cost. If we have moves left, they
742 * will count as a full turn towards the activity time */
743 moves_left
= param
->move_rate
- (total_cost
% param
->move_rate
);
744 if (activity_time
> 0) {
745 int speed
= FC_PTR_TO_INT(param
->data
);
747 activity_time
= ((activity_time
* ACTIVITY_FACTOR
)
748 + (speed
- 1)) / speed
;
750 total_cost
+= moves_left
;
752 total_cost
+= activity_time
* param
->move_rate
;
754 /* Now we determine if we have found a better path. When building
755 * road type with positive move_cost, we care most about the length
756 * of the result. When building road type with move_cost 0, we
757 * care most about construction time. */
759 /* *dest_cost == -1 means we haven't reached dest until now */
761 if (*dest_cost
!= -1) {
762 if (proad
->move_cost
> 0) {
763 if (total_extra
> *dest_extra
764 || (total_extra
== *dest_extra
&& total_cost
>= *dest_cost
)) {
765 /* No, this path is worse than what we already have */
769 if (total_cost
> *dest_cost
770 || (total_cost
== *dest_cost
&& total_extra
>= *dest_extra
)) {
776 /* Ok, we found a better path! */
777 *dest_cost
= total_cost
;
778 *dest_extra
= total_extra
;
780 return (proad
->move_cost
> 0 ?
781 total_extra
* PF_TURN_FACTOR
+ total_cost
:
782 total_cost
* PF_TURN_FACTOR
+ total_extra
);
785 /****************************************************************************
786 PF jumbo callback for the cost of a connect by irrigation.
787 Here we are only interested in how long it will take to irrigate the path.
789 param->data should contain the result of get_activity_rate(punit) / 10.
790 ****************************************************************************/
791 static int get_connect_irrig(const struct tile
*src_tile
,
793 const struct tile
*dest_tile
,
794 int src_cost
, int src_extra
,
795 int *dest_cost
, int *dest_extra
,
796 const struct pf_parameter
*param
)
798 int activity_time
, move_cost
, moves_left
, total_cost
;
800 if (tile_get_known(dest_tile
, param
->owner
) == TILE_UNKNOWN
) {
804 activity_time
= get_activity_time(dest_tile
, param
->owner
);
805 if (activity_time
< 0) {
809 if (!is_cardinal_dir(dir
)) {
813 move_cost
= param
->get_MC(src_tile
, PF_MS_NATIVE
, dest_tile
, PF_MS_NATIVE
,
815 if (move_cost
== PF_IMPOSSIBLE_MC
) {
819 if (is_non_allied_city_adjacent(param
->owner
, dest_tile
)) {
820 /* We don't want to build irrigation for enemies plus get ZoC problems */
824 /* Ok, the move is possible. What are the costs? */
826 move_cost
= MIN(move_cost
, param
->move_rate
);
827 total_cost
= src_cost
;
828 moves_left
= param
->move_rate
- (src_cost
% param
->move_rate
);
829 if (moves_left
< move_cost
) {
830 total_cost
+= moves_left
;
832 total_cost
+= move_cost
;
835 /* Now need to include the activity cost. If we have moves left, they
836 * will count as a full turn towards the activity time */
837 moves_left
= param
->move_rate
- (total_cost
% param
->move_rate
);
838 if (activity_time
> 0) {
839 int speed
= FC_PTR_TO_INT(param
->data
);
841 activity_time
= ((activity_time
* ACTIVITY_FACTOR
)
842 + (speed
- 1)) / speed
;
844 total_cost
+= moves_left
;
846 total_cost
+= activity_time
* param
->move_rate
;
848 /* *dest_cost == -1 means we haven't reached dest until now */
849 if (*dest_cost
!= -1 && total_cost
> *dest_cost
) {
853 /* Ok, we found a better path! */
854 *dest_cost
= total_cost
;
860 /**********************************************************************
861 PF callback to prohibit going into the unknown (conditionally). Also
862 makes sure we don't plan to attack anyone.
863 ***********************************************************************/
864 static enum tile_behavior
865 no_fights_or_unknown_goto(const struct tile
*ptile
,
866 enum known_type known
,
867 const struct pf_parameter
*p
)
869 if (known
== TILE_UNKNOWN
&& gui_options
.goto_into_unknown
) {
870 /* Special case allowing goto into the unknown. */
874 return no_fights_or_unknown(ptile
, known
, p
);
877 /****************************************************************************
878 Fill the PF parameter with the correct client-goto values.
879 See also goto_fill_parameter_full().
880 ****************************************************************************/
881 static void goto_fill_parameter_base(struct pf_parameter
*parameter
,
882 const struct unit
*punit
)
884 pft_fill_unit_parameter(parameter
, punit
);
886 fc_assert(parameter
->get_EC
== NULL
);
887 fc_assert(parameter
->get_TB
== NULL
);
888 fc_assert(parameter
->get_MC
!= NULL
);
889 fc_assert(parameter
->start_tile
== unit_tile(punit
));
890 fc_assert(parameter
->omniscience
== FALSE
);
892 parameter
->get_EC
= get_EC
;
893 if (is_attack_unit(punit
)
894 || utype_acts_hostile(unit_type_get(punit
))) {
895 parameter
->get_TB
= get_TB_aggr
;
896 } else if (utype_may_act_at_all(unit_type_get(punit
))
897 && !utype_acts_hostile(unit_type_get(punit
))) {
898 parameter
->get_TB
= get_TB_caravan
;
900 parameter
->get_TB
= no_fights_or_unknown_goto
;
904 /****************************************************************************
905 Fill the PF parameter with the correct client-goto values.
906 The storage behind "connect_speed" must remain valid for the lifetime
909 Note that you must call this function only if the 'hover_state' is set,
910 and we are in goto mode (usually, this function is only called from
913 See also goto_fill_parameter_base().
914 ****************************************************************************/
915 static void goto_fill_parameter_full(struct goto_map
*goto_map
,
916 const struct unit
*punit
)
918 struct pf_parameter
*parameter
= &goto_map
->template;
920 goto_fill_parameter_base(parameter
, punit
);
922 fc_assert_ret(goto_is_active());
924 switch (hover_state
) {
927 int activity_initial
;
930 if (connect_activity
== ACTIVITY_IRRIGATE
) {
931 parameter
->get_costs
= get_connect_irrig
;
933 parameter
->get_costs
= get_connect_road
;
935 parameter
->get_moves_left_req
= NULL
;
937 speed
= get_activity_rate(punit
);
938 parameter
->data
= FC_INT_TO_PTR(speed
);
940 /* Take into account the activity time at the origin */
941 activity_initial
= get_activity_time(unit_tile(punit
),
944 if (activity_initial
> 0) {
945 /* First action is activity */
946 parameter
->moves_left_initially
= parameter
->move_rate
;
947 /* Number of turns, rounding up */
948 goto_map
->connect
.initial_turns
=
949 ((activity_initial
* ACTIVITY_FACTOR
+ (speed
- 1)) / speed
);
950 if (punit
->moves_left
== 0) {
951 goto_map
->connect
.initial_turns
++;
954 goto_map
->connect
.initial_turns
= 0;
960 if (goto_last_action
== ACTION_NUKE
) {
961 /* We only want targets reachable immediatly... */
962 parameter
->move_rate
= 0;
963 /* ...then we don't need to deal with dangers or refuel points. */
964 parameter
->is_pos_dangerous
= NULL
;
965 parameter
->get_moves_left_req
= NULL
;
967 goto_map
->patrol
.return_path
= NULL
;
972 case HOVER_ACT_SEL_TGT
:
973 fc_assert_msg(hover_state
!= HOVER_NONE
, "Goto with HOVER_NONE?");
974 fc_assert_msg(hover_state
!= HOVER_PARADROP
,
975 "Goto with HOVER_PARADROP?");
976 fc_assert_msg(hover_state
!= HOVER_ACT_SEL_TGT
,
977 "Goto with HOVER_ACT_SEL_TGT?");
982 /**********************************************************************
983 Enter the goto state: activate, prepare PF-template and add the
985 ***********************************************************************/
986 void enter_goto_state(struct unit_list
*punits
)
988 fc_assert_ret(!goto_is_active());
990 /* Can't have selection rectangle and goto going on at the same time. */
991 cancel_selection_rectangle();
993 unit_list_iterate(punits
, punit
) {
994 struct goto_map
*goto_map
= goto_map_new(punit
);
996 goto_map_list_append(goto_maps
, goto_map
);
998 goto_fill_parameter_full(goto_map
, punit
);
1000 } unit_list_iterate_end
;
1001 goto_warned
= FALSE
;
1004 /**********************************************************************
1005 Tidy up and deactivate goto state.
1006 ***********************************************************************/
1007 void exit_goto_state(void)
1009 if (!goto_is_active()) {
1013 goto_map_list_iterate(goto_maps
, goto_map
) {
1014 goto_map_free(goto_map
);
1015 } goto_map_list_iterate_end
;
1016 goto_map_list_clear(goto_maps
);
1018 goto_destination
= NULL
;
1019 goto_warned
= FALSE
;
1022 /**********************************************************************
1023 Called from control_unit_killed() in client/control.c
1024 ***********************************************************************/
1025 void goto_unit_killed(struct unit
*punit
)
1027 if (!goto_is_active()) {
1031 goto_map_unit_iterate(goto_maps
, goto_map
, ptest
) {
1032 if (ptest
== punit
) {
1033 goto_map_free(goto_map
);
1034 /* Still safe using goto_map pointer, as it is not used for
1035 * dereferencing, only as value. */
1036 goto_map_list_remove(goto_maps
, goto_map
);
1037 /* stop now, links are gone! */
1040 } goto_map_unit_iterate_end
;
1043 /**********************************************************************
1044 Is goto state active?
1045 ***********************************************************************/
1046 bool goto_is_active(void)
1048 return (NULL
!= goto_maps
&& 0 != goto_map_list_size(goto_maps
));
1051 /**************************************************************************
1052 Return the path length (in turns).
1053 WARNING: not useful for determining paths of scattered groups.
1054 ***************************************************************************/
1055 bool goto_get_turns(int *min
, int *max
)
1057 fc_assert_ret_val(min
!= NULL
, FALSE
);
1058 fc_assert_ret_val(max
!= NULL
, FALSE
);
1063 if (!goto_is_active()) {
1066 if (NULL
== goto_destination
) {
1067 /* Not a valid position. */
1071 if (hover_state
== HOVER_CONNECT
) {
1072 /* In connect mode, we want to know the turn number the activity will
1074 int activity_time
= get_activity_time(goto_destination
, client_player());
1076 goto_map_list_iterate(goto_maps
, goto_map
) {
1078 int turns
= goto_map
->connect
.initial_turns
;
1081 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1082 const struct pf_path
*path
= goto_map
->parts
[i
].path
;
1084 turns
+= pf_path_last_position(goto_map
->parts
[i
].path
)->turn
;
1085 if (!moved
&& path
->length
> 1) {
1090 if (moved
&& activity_time
> 0) {
1100 } goto_map_list_iterate_end
;
1102 /* In other modes, we want to know the turn number to reach the tile. */
1103 goto_map_list_iterate(goto_maps
, goto_map
) {
1107 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1108 turns
+= pf_path_last_position(goto_map
->parts
[i
].path
)->turn
;
1110 if (hover_state
== HOVER_PATROL
1111 && goto_map
->patrol
.return_path
!= NULL
) {
1112 turns
+= pf_path_last_position(goto_map
->patrol
.return_path
)->turn
;
1121 } goto_map_list_iterate_end
;
1127 /****************************************************************************
1128 Returns the state of 'ptile': turn number to print, and whether 'ptile'
1130 ****************************************************************************/
1131 bool goto_tile_state(const struct tile
*ptile
, enum goto_tile_state
*state
,
1132 int *turns
, bool *waypoint
)
1134 fc_assert_ret_val(ptile
!= NULL
, FALSE
);
1135 fc_assert_ret_val(turns
!= NULL
, FALSE
);
1136 fc_assert_ret_val(waypoint
!= NULL
, FALSE
);
1138 if (!goto_is_active()) {
1146 if (hover_state
== HOVER_CONNECT
) {
1147 /* In connect mode, we want to know the turn number the activity will
1151 if (tile_get_known(ptile
, client_player()) == TILE_UNKNOWN
) {
1152 return FALSE
; /* We never connect on unknown tiles. */
1155 activity_time
= get_activity_time(ptile
, client_player());
1157 goto_map_list_iterate(goto_maps
, goto_map
) {
1158 const struct pf_path
*path
;
1159 const struct pf_position
*pos
= NULL
; /* Keep compiler happy! */
1160 int map_turns
= goto_map
->connect
.initial_turns
;
1161 int turns_for_map
= -2;
1165 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1166 if (i
> 0 && goto_map
->parts
[i
].start_tile
== ptile
) {
1170 path
= goto_map
->parts
[i
].path
;
1175 for (j
= 0; j
< path
->length
; j
++) {
1176 pos
= path
->positions
+ j
;
1177 if (!moved
&& j
> 0) {
1180 if (pos
->tile
!= ptile
) {
1183 if (activity_time
> 0) {
1184 if (map_turns
+ pos
->turn
+ moved
> turns_for_map
) {
1185 turns_for_map
= map_turns
+ pos
->turn
+ moved
;
1187 } else if (pos
->moves_left
== 0) {
1188 if (map_turns
+ pos
->turn
> turns_for_map
) {
1189 turns_for_map
= map_turns
+ pos
->turn
+ moved
;
1193 map_turns
+= pos
->turn
;
1196 if (ptile
== goto_destination
) {
1197 fc_assert_ret_val(pos
!= NULL
, FALSE
);
1198 if (moved
&& activity_time
> 0) {
1201 if (map_turns
> *turns
) {
1202 *state
= (activity_time
> 0 || pos
->moves_left
== 0
1203 ? GTS_EXHAUSTED_MP
: GTS_MP_LEFT
);
1205 } else if (map_turns
== *turns
1206 && *state
== GTS_MP_LEFT
1207 && (activity_time
> 0 || pos
->moves_left
== 0)) {
1208 *state
= GTS_EXHAUSTED_MP
;
1211 if (activity_time
> 0) {
1212 if (turns_for_map
> *turns
) {
1213 *state
= GTS_TURN_STEP
;
1214 *turns
= turns_for_map
;
1217 if (turns_for_map
+ 1 > *turns
) {
1218 *state
= GTS_TURN_STEP
;
1219 *turns
= turns_for_map
+ 1;
1223 } goto_map_list_iterate_end
;
1225 /* In other modes, we want to know the turn number to reach the tile. */
1226 goto_map_list_iterate(goto_maps
, goto_map
) {
1227 const struct tile
*destination
;
1228 const struct pf_path
*path
;
1229 const struct pf_position
*pos
= NULL
; /* Keep compiler happy! */
1231 int turns_for_map
= -2;
1234 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1235 if (i
> 0 && goto_map
->parts
[i
].start_tile
== ptile
) {
1239 path
= goto_map
->parts
[i
].path
;
1244 for (j
= 0; j
< path
->length
; j
++) {
1245 pos
= path
->positions
+ j
;
1246 if (pos
->tile
== ptile
1247 /* End turn case. */
1248 && (pos
->moves_left
== 0
1250 || (j
< path
->length
- 1 && (pos
+ 1)->tile
== ptile
))
1251 && map_turns
+ pos
->turn
> turns_for_map
) {
1252 turns_for_map
= map_turns
+ pos
->turn
;
1255 map_turns
+= pos
->turn
;
1258 if (hover_state
== HOVER_PATROL
1259 && goto_map
->patrol
.return_path
!= NULL
) {
1260 path
= goto_map
->patrol
.return_path
;
1261 for (j
= 0; j
< path
->length
; j
++) {
1262 pos
= path
->positions
+ j
;
1263 if (pos
->tile
== ptile
1264 /* End turn case. */
1265 && (pos
->moves_left
== 0
1267 || (j
< path
->length
- 1 && (pos
+ 1)->tile
== ptile
))
1268 && map_turns
+ pos
->turn
> turns_for_map
) {
1269 turns_for_map
= map_turns
+ pos
->turn
;
1272 map_turns
+= pos
->turn
;
1273 destination
= pos
->tile
;
1275 destination
= goto_destination
;
1278 if (ptile
== destination
) {
1279 fc_assert_ret_val(pos
!= NULL
, FALSE
);
1280 if (map_turns
> *turns
) {
1281 *state
= (pos
->moves_left
== 0 ? GTS_EXHAUSTED_MP
: GTS_MP_LEFT
);
1283 } else if (map_turns
== *turns
1284 && *state
== GTS_MP_LEFT
1285 && pos
->moves_left
== 0) {
1286 *state
= GTS_EXHAUSTED_MP
;
1289 if (turns_for_map
+ 1 > *turns
) {
1290 *state
= GTS_TURN_STEP
;
1291 *turns
= turns_for_map
+ 1;
1294 } goto_map_list_iterate_end
;
1297 return (*turns
!= -1 || *waypoint
);
1300 /**********************************************************************
1301 Puts a line to dest_tile on the map according to the current
1303 If there is no route to the dest then don't draw anything.
1304 ***********************************************************************/
1305 bool is_valid_goto_draw_line(struct tile
*dest_tile
)
1307 fc_assert_ret_val(goto_is_active(), FALSE
);
1308 if (NULL
== dest_tile
) {
1312 /* assume valid destination */
1313 goto_destination
= dest_tile
;
1315 goto_map_list_iterate(goto_maps
, goto_map
) {
1316 if (!update_last_part(goto_map
, dest_tile
)) {
1317 goto_destination
= NULL
;
1319 } goto_map_list_iterate_end
;
1321 /* Update goto data in info label. */
1322 update_unit_info_label(get_units_in_focus());
1323 return (NULL
!= goto_destination
);
1326 /****************************************************************************
1327 Send a packet to the server to request that the current orders be
1329 ****************************************************************************/
1330 void request_orders_cleared(struct unit
*punit
)
1332 struct packet_unit_orders p
;
1334 if (!can_client_issue_orders()) {
1338 /* Clear the orders by sending an empty orders path. */
1339 log_goto_packet("Clearing orders for unit %d.", punit
->id
);
1340 p
.unit_id
= punit
->id
;
1341 p
.src_tile
= tile_index(unit_tile(punit
));
1342 p
.repeat
= p
.vigilant
= FALSE
;
1344 p
.dest_tile
= tile_index(unit_tile(punit
));
1345 send_packet_unit_orders(&client
.conn
, &p
);
1348 /**************************************************************************
1349 Send a path as a goto or patrol route to the server.
1350 **************************************************************************/
1351 static void send_path_orders(struct unit
*punit
, struct pf_path
*path
,
1352 bool repeat
, bool vigilant
,
1353 enum unit_orders orders
,
1354 struct unit_order
*final_order
)
1356 struct packet_unit_orders p
;
1358 struct tile
*old_tile
;
1360 fc_assert_ret(path
!= NULL
);
1361 fc_assert_ret_msg(unit_tile(punit
) == path
->positions
[0].tile
,
1362 "Unit %d has moved without goto cancelation.",
1365 if (path
->length
== 1 && final_order
== NULL
) {
1366 return; /* No path at all, no need to spam the server. */
1369 memset(&p
, 0, sizeof(p
));
1370 p
.unit_id
= punit
->id
;
1371 p
.src_tile
= tile_index(unit_tile(punit
));
1373 p
.vigilant
= vigilant
;
1375 log_goto_packet("Orders for unit %d:", punit
->id
);
1377 /* We skip the start position. */
1378 p
.length
= path
->length
- 1;
1379 fc_assert(p
.length
< MAX_LEN_ROUTE
);
1380 old_tile
= path
->positions
[0].tile
;
1382 log_goto_packet(" Repeat: %d. Vigilant: %d. Length: %d",
1383 p
.repeat
, p
.vigilant
, p
.length
);
1385 /* If the path has n positions it takes n-1 steps. */
1386 for (i
= 0; i
< path
->length
- 1; i
++) {
1387 struct tile
*new_tile
= path
->positions
[i
+ 1].tile
;
1389 if (same_pos(new_tile
, old_tile
)) {
1390 p
.orders
[i
] = ORDER_FULL_MP
;
1391 p
.dir
[i
] = DIR8_ORIGIN
;
1392 p
.activity
[i
] = ACTIVITY_LAST
;
1393 p
.target
[i
] = EXTRA_NONE
;
1394 p
.action
[i
] = ACTION_NONE
;
1395 log_goto_packet(" packet[%d] = wait: %d,%d", i
, TILE_XY(old_tile
));
1397 p
.orders
[i
] = orders
;
1398 p
.dir
[i
] = get_direction_for_step(&(wld
.map
), old_tile
, new_tile
);
1399 p
.activity
[i
] = ACTIVITY_LAST
;
1400 p
.target
[i
] = EXTRA_NONE
;
1401 p
.action
[i
] = ACTION_NONE
;
1402 log_goto_packet(" packet[%d] = move %s: %d,%d => %d,%d",
1403 i
, dir_get_name(p
.dir
[i
]),
1404 TILE_XY(old_tile
), TILE_XY(new_tile
));
1406 old_tile
= new_tile
;
1409 if (p
.orders
[i
- 1] == ORDER_MOVE
1410 && (is_non_allied_city_tile(old_tile
, client_player()) != NULL
1411 || is_non_allied_unit_tile(old_tile
, client_player()) != NULL
)) {
1412 /* Won't be able to perform a regular move to the target tile... */
1414 /* ...and no final order exists. Choose what to do when the unit gets
1416 p
.orders
[i
- 1] = ORDER_ACTION_MOVE
;
1418 /* ...and a final order exist. Can't assume an action move. Did the
1419 * caller hope that the situation would change before the unit got
1422 /* It's currently illegal to walk into tiles with non allied units or
1423 * cities. Some actions causes the actor to enter the target tile but
1424 * that is a part of the action it self, not a regular pre action
1426 log_verbose("unit or city blocks the path of your %s",
1427 unit_rule_name(punit
));
1432 /* Append the final order after moving to the target tile. */
1433 p
.orders
[i
] = final_order
->order
;
1434 p
.dir
[i
] = final_order
->dir
;
1435 p
.activity
[i
] = (final_order
->order
== ORDER_ACTIVITY
)
1436 ? final_order
->activity
: ACTIVITY_LAST
;
1437 p
.target
[i
] = final_order
->target
;
1438 p
.action
[i
] = final_order
->action
;
1442 p
.dest_tile
= tile_index(old_tile
);
1444 send_packet_unit_orders(&client
.conn
, &p
);
1447 /**************************************************************************
1448 Send an arbitrary goto path for the unit to the server.
1449 **************************************************************************/
1450 void send_goto_path(struct unit
*punit
, struct pf_path
*path
,
1451 struct unit_order
*final_order
)
1453 send_path_orders(punit
, path
, FALSE
, FALSE
, ORDER_MOVE
, final_order
);
1456 /****************************************************************************
1457 Send orders for the unit to move it to the arbitrary tile. Returns
1458 FALSE if no path is found.
1459 ****************************************************************************/
1460 bool send_goto_tile(struct unit
*punit
, struct tile
*ptile
)
1462 struct pf_parameter parameter
;
1464 struct pf_path
*path
;
1466 goto_fill_parameter_base(¶meter
, punit
);
1467 pfm
= pf_map_new(¶meter
);
1468 path
= pf_map_path(pfm
, ptile
);
1469 pf_map_destroy(pfm
);
1472 send_goto_path(punit
, path
, NULL
);
1473 pf_path_destroy(path
);
1480 /****************************************************************************
1481 Send orders for the unit to move it to the arbitrary tile and attack
1482 everything it approaches. Returns FALSE if no path is found.
1483 ****************************************************************************/
1484 bool send_attack_tile(struct unit
*punit
, struct tile
*ptile
)
1486 struct pf_parameter parameter
;
1488 struct pf_path
*path
;
1490 goto_fill_parameter_base(¶meter
, punit
);
1491 parameter
.move_rate
= 0;
1492 parameter
.is_pos_dangerous
= NULL
;
1493 parameter
.get_moves_left_req
= NULL
;
1494 pfm
= pf_map_new(¶meter
);
1495 path
= pf_map_path(pfm
, ptile
);
1496 pf_map_destroy(pfm
);
1499 send_path_orders(punit
, path
, false, false, ORDER_ACTION_MOVE
, NULL
);
1500 pf_path_destroy(path
);
1506 /**************************************************************************
1507 Send the current patrol route (i.e., the one generated via HOVER_STATE)
1509 **************************************************************************/
1510 void send_patrol_route(void)
1512 fc_assert_ret(goto_is_active());
1513 goto_map_unit_iterate(goto_maps
, goto_map
, punit
) {
1515 struct pf_path
*path
= NULL
;
1516 struct part
*last_part
= &goto_map
->parts
[goto_map
->num_parts
- 1];
1518 if (NULL
== last_part
->path
) {
1519 /* Cannot move there */
1523 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1524 path
= pf_path_concat(path
, goto_map
->parts
[i
].path
);
1526 path
= pf_path_concat(path
, goto_map
->patrol
.return_path
);
1528 send_path_orders(punit
, path
, TRUE
, TRUE
, ORDER_MOVE
, NULL
);
1530 pf_path_destroy(path
);
1531 } goto_map_unit_iterate_end
;
1534 /**************************************************************************
1535 Fill orders to build recursive roads.
1536 **************************************************************************/
1537 static bool order_recursive_roads(struct tile
*ptile
, struct extra_type
*pextra
,
1538 struct packet_unit_orders
*p
, int rec
)
1540 if (rec
> MAX_EXTRA_TYPES
) {
1544 if (!is_extra_caused_by(pextra
, EC_ROAD
)) {
1548 extra_deps_iterate(&(pextra
->reqs
), pdep
) {
1549 if (!tile_has_extra(ptile
, pdep
)) {
1550 if (!order_recursive_roads(ptile
, pdep
, p
, rec
+ 1)) {
1554 } extra_deps_iterate_end
;
1556 p
->orders
[p
->length
] = ORDER_ACTIVITY
;
1557 p
->dir
[p
->length
] = DIR8_ORIGIN
;
1558 p
->activity
[p
->length
] = ACTIVITY_GEN_ROAD
;
1559 p
->target
[p
->length
] = extra_index(pextra
);
1560 p
->action
[p
->length
] = ACTION_NONE
;
1566 /**************************************************************************
1567 Send the current connect route (i.e., the one generated via HOVER_STATE)
1569 **************************************************************************/
1570 void send_connect_route(enum unit_activity activity
,
1571 struct extra_type
*tgt
)
1573 fc_assert_ret(goto_is_active());
1574 goto_map_unit_iterate(goto_maps
, goto_map
, punit
) {
1576 struct packet_unit_orders p
;
1577 struct tile
*old_tile
;
1578 struct pf_path
*path
= NULL
;
1579 struct part
*last_part
= &goto_map
->parts
[goto_map
->num_parts
- 1];
1581 if (NULL
== last_part
->path
) {
1582 /* Cannot move there */
1586 memset(&p
, 0, sizeof(p
));
1588 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1589 path
= pf_path_concat(path
, goto_map
->parts
[i
].path
);
1592 p
.unit_id
= punit
->id
;
1593 p
.src_tile
= tile_index(unit_tile(punit
));
1595 p
.vigilant
= FALSE
; /* Should be TRUE? */
1598 old_tile
= path
->positions
[0].tile
;
1600 for (i
= 0; i
< path
->length
; i
++) {
1602 case ACTIVITY_IRRIGATE
:
1603 if (!tile_has_extra(old_tile
, tgt
)) {
1604 /* Assume the unit can irrigate or we wouldn't be here. */
1605 p
.orders
[p
.length
] = ORDER_ACTIVITY
;
1606 p
.dir
[p
.length
] = DIR8_ORIGIN
;
1607 p
.activity
[p
.length
] = ACTIVITY_IRRIGATE
;
1608 p
.target
[p
.length
] = extra_index(tgt
);
1609 p
.action
[p
.length
] = ACTION_NONE
;
1613 case ACTIVITY_GEN_ROAD
:
1614 order_recursive_roads(old_tile
, tgt
, &p
, 0);
1617 log_error("Invalid connect activity: %d.", activity
);
1621 if (i
!= path
->length
- 1) {
1622 struct tile
*new_tile
= path
->positions
[i
+ 1].tile
;
1624 fc_assert(!same_pos(new_tile
, old_tile
));
1626 p
.orders
[p
.length
] = ORDER_MOVE
;
1627 p
.dir
[p
.length
] = get_direction_for_step(&(wld
.map
),
1628 old_tile
, new_tile
);
1629 p
.activity
[p
.length
] = ACTIVITY_LAST
;
1630 p
.target
[p
.length
] = EXTRA_NONE
;
1631 p
.action
[p
.length
] = ACTION_NONE
;
1634 old_tile
= new_tile
;
1638 p
.dest_tile
= tile_index(old_tile
);
1640 send_packet_unit_orders(&client
.conn
, &p
);
1641 } goto_map_unit_iterate_end
;
1644 /**************************************************************************
1645 Returns TRUE if the order preferably should be performed from an
1648 This function doesn't care if a direction is required or just possible.
1649 Use order_demands_direction() for that.
1650 **************************************************************************/
1651 static bool order_wants_direction(enum unit_orders order
, int act_id
,
1652 struct tile
*tgt_tile
)
1656 case ORDER_ACTION_MOVE
:
1657 /* Not only is it legal. It is mandatory. A move is always done in a
1660 case ORDER_PERFORM_ACTION
:
1661 if (!action_id_distance_accepted(act_id
, 0)) {
1662 /* Always illegal to do to a target on the actor's own tile. */
1666 if (!action_id_distance_accepted(act_id
, 1)) {
1667 /* Always illegal to perform to a target on a neighbor tile. */
1671 if (is_non_allied_city_tile(tgt_tile
, client_player()) != NULL
1672 || is_non_allied_unit_tile(tgt_tile
, client_player()) != NULL
) {
1673 /* Won't be able to move to the target tile to perform the action on
1675 /* TODO: detect situations where it also would be illegal to perform
1676 * the action from the neighbor tile. */
1686 /**************************************************************************
1687 Returns TRUE if it is certain that the order must be performed from an
1689 **************************************************************************/
1690 static bool order_demands_direction(enum unit_orders order
, int act_id
)
1694 case ORDER_ACTION_MOVE
:
1695 /* A move is always done in a direction. */
1697 case ORDER_PERFORM_ACTION
:
1698 if (!action_id_distance_accepted(act_id
, 0)) {
1699 /* Always illegal to do to a target on the actor's own tile. */
1709 /**************************************************************************
1710 Send the current goto route (i.e., the one generated via
1711 HOVER_STATE) to the server. The route might involve more than one
1712 part if waypoints were used. FIXME: danger paths are not supported.
1713 **************************************************************************/
1714 void send_goto_route(void)
1716 fc_assert_ret(goto_is_active());
1717 goto_map_unit_iterate(goto_maps
, goto_map
, punit
) {
1719 struct tile
*tgt_tile
;
1720 struct pf_path
*path
= NULL
;
1721 struct part
*last_part
= &goto_map
->parts
[goto_map
->num_parts
- 1];
1723 if (NULL
== last_part
->path
) {
1724 /* Cannot move there */
1728 for (i
= 0; i
< goto_map
->num_parts
; i
++) {
1729 path
= pf_path_concat(path
, goto_map
->parts
[i
].path
);
1732 clear_unit_orders(punit
);
1734 tgt_tile
= pf_path_last_position(path
)->tile
;
1736 /* Make the last move in a plain goto try to pop up the action
1737 * selection dialog rather than moving to the last tile if it contains
1738 * a domestic, allied or team mate city, unit or unit stack. This can,
1739 * in cases where the action requires movement left, save a turn. */
1740 /* TODO: Should this be a client option? */
1741 if (goto_last_order
== ORDER_LAST
1742 && ((is_allied_city_tile(tgt_tile
, client_player())
1743 || is_allied_unit_tile(tgt_tile
, client_player()))
1744 && (can_utype_do_act_if_tgt_diplrel(unit_type_get(punit
),
1748 || can_utype_do_act_if_tgt_diplrel(unit_type_get(punit
),
1752 || can_utype_do_act_if_tgt_diplrel(unit_type_get(punit
),
1756 /* Try to pop up the action selection dialog before moving to the
1758 goto_last_order
= ORDER_ACTION_MOVE
;
1761 if (goto_last_order
== ORDER_LAST
) {
1762 send_goto_path(punit
, path
, NULL
);
1763 } else if (path
->length
> 1
1764 || !order_demands_direction(goto_last_order
,
1765 goto_last_action
)) {
1766 struct unit_order order
;
1768 struct tile
*on_tile
;
1770 if (path
->length
> 1
1771 && ((on_tile
= path
->positions
[path
->length
- 2].tile
))
1772 && order_wants_direction(goto_last_order
, goto_last_action
,
1774 && !same_pos(on_tile
, tgt_tile
)) {
1775 /* The last order prefers to handle the last direction it self.
1776 * There exists a tile before the target tile to do it from. */
1778 /* Give the last path direction to the final order. */
1779 last_order_dir
= get_direction_for_step(&(wld
.map
), on_tile
, tgt_tile
);
1781 /* The last path direction is now spent. */
1782 pf_path_backtrack(path
, on_tile
);
1784 fc_assert(!order_demands_direction(goto_last_order
,
1787 /* Target the tile the actor is standing on. */
1788 last_order_dir
= DIR8_ORIGIN
;
1791 order
.order
= goto_last_order
;
1792 order
.dir
= DIR8_ORIGIN
;
1793 order
.dir
= last_order_dir
;
1794 order
.activity
= ACTIVITY_LAST
;
1795 order
.target
= goto_last_tgt
;
1796 order
.action
= goto_last_action
;
1798 /* ORDER_ACTIVITY would require real activity */
1799 fc_assert(goto_last_order
!= ORDER_ACTIVITY
);
1801 send_goto_path(punit
, path
, &order
);
1803 pf_path_destroy(path
);
1804 } goto_map_unit_iterate_end
;
1807 /**************************************************************************
1808 Find the path to the nearest (fastest to reach) allied city for the
1809 unit, or NULL if none is reachable.
1810 ***************************************************************************/
1811 struct pf_path
*path_to_nearest_allied_city(struct unit
*punit
)
1813 struct pf_parameter parameter
;
1815 struct pf_path
*path
= NULL
;
1817 if (is_allied_city_tile(unit_tile(punit
), unit_owner(punit
))) {
1818 /* We're already on a city - don't go anywhere. */
1822 goto_fill_parameter_base(¶meter
, punit
);
1823 pfm
= pf_map_new(¶meter
);
1825 pf_map_tiles_iterate(pfm
, ptile
, FALSE
) {
1826 if (is_allied_city_tile(ptile
, unit_owner(punit
))) {
1827 path
= pf_map_path(pfm
, ptile
);
1830 } pf_map_tiles_iterate_end
;
1832 pf_map_destroy(pfm
);
1837 /**************************************************************************
1838 Finds penultimate tile on path for given unit going to ptile
1839 ***************************************************************************/
1840 struct tile
*tile_before_end_path(struct unit
*punit
, struct tile
*ptile
)
1842 struct pf_parameter parameter
;
1845 struct pf_path
*path
;
1847 goto_fill_parameter_base(¶meter
, punit
);
1848 parameter
.move_rate
= 0;
1849 parameter
.is_pos_dangerous
= NULL
;
1850 parameter
.get_moves_left_req
= NULL
;
1851 pfm
= pf_map_new(¶meter
);
1852 path
= pf_map_path(pfm
, ptile
);
1856 if (path
->length
< 2) {
1859 dtile
= path
->positions
[path
->length
- 2].tile
;
1861 pf_map_destroy(pfm
);