Removed silencing of gtk warning logs from gtk3.22-client.
[freeciv.git] / client / goto.c
blobad3c1ca45e54b74710c683f3198f8133b56d30cc
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <string.h>
20 /* utility */
21 #include "log.h"
22 #include "mem.h"
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"
34 /* client/include */
35 #include "client_main.h"
36 #include "control.h"
37 #include "mapview_g.h"
39 /* client */
40 #include "goto.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.
52 struct part {
53 struct tile *start_tile, *end_tile;
54 int end_moves_left, end_fuel_left;
55 struct pf_path *path;
56 struct pf_map *map;
59 struct goto_map {
60 struct unit *focus;
61 struct part *parts;
62 int num_parts;
63 union {
64 struct {
65 int initial_turns;
66 } connect;
67 struct {
68 struct pf_path *return_path;
69 } patrol;
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
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
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;
116 return goto_map;
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);
133 free(goto_map);
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));
146 return punit;
149 /**********************************************************************
150 Called only by handle_map_info() in client/packhand.c.
151 ***********************************************************************/
152 void init_client_goto(void)
154 free_client_goto();
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);
169 goto_maps = NULL;
172 goto_destination = NULL;
173 goto_warned = FALSE;
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 /****************************************************************************
185 Show goto lines.
186 ****************************************************************************/
187 static void goto_path_redraw(const struct pf_path *new_path,
188 const struct pf_path *old_path)
190 int start_index = 0;
191 int i;
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) {
204 break;
207 start_index = i;
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);
215 } else {
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);
227 } else {
228 fc_assert(pos->tile == (pos + 1)->tile);
233 /****************************************************************************
234 Remove goto lines.
235 ****************************************************************************/
236 static void goto_path_undraw(const struct pf_path *path)
238 int i;
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);
247 } else {
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,
259 struct tile *ptile)
261 struct pf_path *old_path, *new_path;
262 struct part *p = &goto_map->parts[goto_map->num_parts - 1];
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;
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);
274 if (!new_path) {
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. */
281 if (!goto_warned) {
282 log_error("No path found to reach the start point.");
283 goto_warned = TRUE;
286 if (old_path != NULL) {
287 goto_path_undraw(old_path);
288 pf_path_destroy(old_path);
289 p->path = NULL;
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;
297 return FALSE;
300 reset_last_part(goto_map);
301 return FALSE;
304 log_goto_path(" path found:");
305 pf_path_print(new_path, LOG_GOTO_PATH);
307 p->path = new_path;
308 p->end_tile = ptile;
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;
314 struct pf_map *pfm;
315 struct pf_path *return_path;
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);
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. */
329 if (!goto_warned) {
330 log_error("No path found to reach the start point.");
331 goto_warned = TRUE;
334 if (old_path != NULL) {
335 goto_path_undraw(old_path);
336 pf_path_destroy(old_path);
338 pf_path_destroy(new_path);
339 p->path = NULL;
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;
345 return FALSE;
348 p->path = old_path;
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);
354 return FALSE;
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);
380 return TRUE;
383 /**********************************************************************
384 Change the drawn path to a size of 0 steps by setting it to the
385 start position.
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);
409 return;
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(param->utype, param->start_tile)) {
416 param->transported_by_initially = NULL;
417 } else {
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)
433 struct part *p;
434 struct pf_parameter parameter;
435 struct unit *punit = goto_map_unit(goto_map);
437 goto_map->num_parts++;
438 goto_map->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) {
444 /* first part */
445 p->start_tile = unit_tile(punit);
446 parameter = goto_map->template;
447 } else {
448 struct part *prev = &goto_map->parts[goto_map->num_parts - 2];
450 p->start_tile = prev->end_tile;
451 fill_parameter_part(&parameter, goto_map, prev);
453 p->path = NULL;
454 p->end_tile = p->start_tile;
455 parameter.start_tile = p->start_tile;
456 p->map = pf_map_new(&parameter);
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);
469 if (p->path) {
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. */
487 return FALSE;
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. */
495 return FALSE;
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) {
502 return FALSE;
505 goto_map_list_iterate(goto_maps, goto_map) {
506 add_part(goto_map);
507 } goto_map_list_iterate_end;
509 refresh_tile_mapcanvas(goto_destination, FALSE, FALSE);
510 return TRUE;
513 /**********************************************************************
514 Returns whether there were any waypoint popped (we don't remove the
515 initial position)
516 ***********************************************************************/
517 bool goto_pop_waypoint(void)
519 bool popped = FALSE;
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. */
528 continue;
530 popped = TRUE;
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;
541 return popped;
544 /**********************************************************************
545 PF callback to get the path with the minimal number of steps (out of
546 all shortest paths).
547 ***********************************************************************/
548 static int get_EC(const struct tile *ptile, enum known_type known,
549 const struct pf_parameter *param)
551 return 1;
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) {
564 return TB_IGNORE;
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;
571 return TB_NORMAL;
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) {
584 return TB_IGNORE;
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. */
593 return TB_IGNORE;
596 /* Includes empty, allied, or allied-city tiles. */
597 return TB_NORMAL;
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);
608 int activity_mc = 0;
610 fc_assert_ret_val(hover_state == HOVER_CONNECT, -1);
612 switch (connect_activity) {
613 case ACTIVITY_IRRIGATE:
614 if (pterrain->irrigation_time == 0) {
615 return -1;
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. */
621 return -1;
623 } extra_type_iterate_end;
625 if (tile_has_extra(ptile, connect_tgt)) {
626 break;
629 activity_mc = pterrain->irrigation_time;
630 break;
631 case ACTIVITY_GEN_ROAD:
632 fc_assert(is_extra_caused_by(connect_tgt, EC_ROAD));
634 if (!tile_has_extra(ptile, connect_tgt)) {
635 struct tile *vtile;
636 int single_mc;
638 vtile = tile_virtual_new(ptile);
639 single_mc = check_recursive_road_connect(vtile, connect_tgt, NULL, pplayer, 0);
640 tile_virtual_destroy(vtile);
642 if (single_mc < 0) {
643 return -1;
646 activity_mc += single_mc;
648 break;
649 default:
650 log_error("Invalid connect activity: %d.", connect_activity);
653 return activity_mc;
656 /****************************************************************************
657 When building a road or a railroad, we don't want to go next to
658 nonallied cities
659 ****************************************************************************/
660 static bool is_non_allied_city_adjacent(const struct player *pplayer,
661 const struct tile *ptile)
663 adjc_iterate(ptile, tile1) {
664 if (is_non_allied_city_tile(tile1, pplayer)) {
665 return TRUE;
667 } adjc_iterate_end;
669 return FALSE;
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) {
692 return -1;
695 activity_time = get_activity_time(dest_tile, param->owner);
696 if (activity_time < 0) {
697 return -1;
700 move_cost = param->get_MC(src_tile, PF_MS_NATIVE, dest_tile, PF_MS_NATIVE,
701 param);
702 if (move_cost == PF_IMPOSSIBLE_MC) {
703 return -1;
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 */
708 return -1;
711 fc_assert(connect_activity == ACTIVITY_GEN_ROAD);
713 proad = extra_road_get(connect_tgt);
715 if (proad == NULL) {
716 /* No suitable road type available */
717 return -1;
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;
737 } else {
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);
746 activity_time = ((activity_time * ACTIVITY_FACTOR)
747 + (speed - 1)) / speed;
748 activity_time--;
749 total_cost += moves_left;
751 total_cost += activity_time * param->move_rate;
753 /* Now we determine if we have found a better path. When building
754 * road type with positive move_cost, we care most about the length
755 * of the result. When building road type with move_cost 0, we
756 * care most about construction time. */
758 /* *dest_cost==-1 means we haven't reached dest until now */
760 if (*dest_cost != -1) {
761 if (proad->move_cost > 0) {
762 if (total_extra > *dest_extra
763 || (total_extra == *dest_extra && total_cost >= *dest_cost)) {
764 /* No, this path is worse than what we already have */
765 return -1;
767 } else {
768 if (total_cost > *dest_cost
769 || (total_cost == *dest_cost && total_extra >= *dest_extra)) {
770 return -1;
775 /* Ok, we found a better path! */
776 *dest_cost = total_cost;
777 *dest_extra = total_extra;
779 return (proad->move_cost > 0 ?
780 total_extra * PF_TURN_FACTOR + total_cost :
781 total_cost * PF_TURN_FACTOR + total_extra);
784 /****************************************************************************
785 PF jumbo callback for the cost of a connect by irrigation.
786 Here we are only interested in how long it will take to irrigate the path.
788 param->data should contain the result of get_activity_rate(punit) / 10.
789 ****************************************************************************/
790 static int get_connect_irrig(const struct tile *src_tile,
791 enum direction8 dir,
792 const struct tile *dest_tile,
793 int src_cost, int src_extra,
794 int *dest_cost, int *dest_extra,
795 const struct pf_parameter *param)
797 int activity_time, move_cost, moves_left, total_cost;
799 if (tile_get_known(dest_tile, param->owner) == TILE_UNKNOWN) {
800 return -1;
803 activity_time = get_activity_time(dest_tile, param->owner);
804 if (activity_time < 0) {
805 return -1;
808 if (!is_cardinal_dir(dir)) {
809 return -1;
812 move_cost = param->get_MC(src_tile, PF_MS_NATIVE, dest_tile, PF_MS_NATIVE,
813 param);
814 if (move_cost == PF_IMPOSSIBLE_MC) {
815 return -1;
818 if (is_non_allied_city_adjacent(param->owner, dest_tile)) {
819 /* We don't want to build irrigation for enemies plus get ZoC problems */
820 return -1;
823 /* Ok, the move is possible. What are the costs? */
825 move_cost = MIN(move_cost, param->move_rate);
826 total_cost = src_cost;
827 moves_left = param->move_rate - (src_cost % param->move_rate);
828 if (moves_left < move_cost) {
829 total_cost += moves_left;
830 } else {
831 total_cost += move_cost;
834 /* Now need to include the activity cost. If we have moves left, they
835 * will count as a full turn towards the activity time */
836 moves_left = param->move_rate - (total_cost % param->move_rate);
837 if (activity_time > 0) {
838 int speed = FC_PTR_TO_INT(param->data);
839 activity_time = ((activity_time * ACTIVITY_FACTOR)
840 + (speed - 1)) / speed;
841 activity_time--;
842 total_cost += moves_left;
844 total_cost += activity_time * param->move_rate;
846 /* *dest_cost==-1 means we haven't reached dest until now */
847 if (*dest_cost != -1 && total_cost > *dest_cost) {
848 return -1;
851 /* Ok, we found a better path! */
852 *dest_cost = total_cost;
853 *dest_extra = 0;
855 return total_cost;
858 /**********************************************************************
859 PF callback to prohibit going into the unknown (conditionally). Also
860 makes sure we don't plan to attack anyone.
861 ***********************************************************************/
862 static enum tile_behavior
863 no_fights_or_unknown_goto(const struct tile *ptile,
864 enum known_type known,
865 const struct pf_parameter *p)
867 if (known == TILE_UNKNOWN && gui_options.goto_into_unknown) {
868 /* Special case allowing goto into the unknown. */
869 return TB_NORMAL;
872 return no_fights_or_unknown(ptile, known, p);
875 /****************************************************************************
876 Fill the PF parameter with the correct client-goto values.
877 See also goto_fill_parameter_full().
878 ****************************************************************************/
879 static void goto_fill_parameter_base(struct pf_parameter *parameter,
880 const struct unit *punit)
882 pft_fill_unit_parameter(parameter, punit);
884 fc_assert(parameter->get_EC == NULL);
885 fc_assert(parameter->get_TB == NULL);
886 fc_assert(parameter->get_MC != NULL);
887 fc_assert(parameter->start_tile == unit_tile(punit));
888 fc_assert(parameter->omniscience == FALSE);
890 parameter->get_EC = get_EC;
891 if (is_attack_unit(punit)
892 || utype_acts_hostile(unit_type_get(punit))) {
893 parameter->get_TB = get_TB_aggr;
894 } else if (utype_may_act_at_all(unit_type_get(punit))
895 && !utype_acts_hostile(unit_type_get(punit))) {
896 parameter->get_TB = get_TB_caravan;
897 } else {
898 parameter->get_TB = no_fights_or_unknown_goto;
902 /****************************************************************************
903 Fill the PF parameter with the correct client-goto values.
904 The storage behind "connect_speed" must remain valid for the lifetime
905 of the pf_map.
907 Note that you must call this function only if the 'hover_state' is set,
908 and we are in goto mode (usually, this function is only called from
909 enter_goto_state()).
911 See also goto_fill_parameter_base().
912 ****************************************************************************/
913 static void goto_fill_parameter_full(struct goto_map *goto_map,
914 const struct unit *punit)
916 struct pf_parameter *parameter = &goto_map->template;
918 goto_fill_parameter_base(parameter, punit);
920 fc_assert_ret(goto_is_active());
922 switch (hover_state) {
923 case HOVER_CONNECT:
925 int activity_initial;
926 int speed;
928 if (connect_activity == ACTIVITY_IRRIGATE) {
929 parameter->get_costs = get_connect_irrig;
930 } else {
931 parameter->get_costs = get_connect_road;
933 parameter->get_moves_left_req = NULL;
935 speed = get_activity_rate(punit);
936 parameter->data = FC_INT_TO_PTR(speed);
938 /* Take into account the activity time at the origin */
939 activity_initial = get_activity_time(unit_tile(punit),
940 unit_owner(punit));
942 if (activity_initial > 0) {
943 /* First action is activity */
944 parameter->moves_left_initially = parameter->move_rate;
945 /* Number of turns, rounding up */
946 goto_map->connect.initial_turns =
947 ((activity_initial * ACTIVITY_FACTOR + (speed - 1)) / speed);
948 if (punit->moves_left == 0) {
949 goto_map->connect.initial_turns++;
951 } else {
952 goto_map->connect.initial_turns = 0;
955 break;
956 case HOVER_NUKE:
957 /* We only want targets reachable immediatly... */
958 parameter->move_rate = 0;
959 /* ...then we don't need to deal with dangers or refuel points. */
960 parameter->is_pos_dangerous = NULL;
961 parameter->get_moves_left_req = NULL;
962 break;
963 case HOVER_GOTO:
964 case HOVER_PATROL:
965 goto_map->patrol.return_path = NULL;
966 break;
967 case HOVER_NONE:
968 case HOVER_PARADROP:
969 case HOVER_ACT_SEL_TGT:
970 fc_assert_msg(hover_state != HOVER_NONE, "Goto with HOVER_NONE?");
971 fc_assert_msg(hover_state != HOVER_PARADROP,
972 "Goto with HOVER_PARADROP?");
973 fc_assert_msg(hover_state != HOVER_ACT_SEL_TGT,
974 "Goto with HOVER_ACT_SEL_TGT?");
975 break;
979 /**********************************************************************
980 Enter the goto state: activate, prepare PF-template and add the
981 initial part.
982 ***********************************************************************/
983 void enter_goto_state(struct unit_list *punits)
985 fc_assert_ret(!goto_is_active());
987 /* Can't have selection rectangle and goto going on at the same time. */
988 cancel_selection_rectangle();
990 unit_list_iterate(punits, punit) {
991 struct goto_map *goto_map = goto_map_new(punit);
993 goto_map_list_append(goto_maps, goto_map);
995 goto_fill_parameter_full(goto_map, punit);
996 add_part(goto_map);
997 } unit_list_iterate_end;
998 goto_warned = FALSE;
1001 /**********************************************************************
1002 Tidy up and deactivate goto state.
1003 ***********************************************************************/
1004 void exit_goto_state(void)
1006 if (!goto_is_active()) {
1007 return;
1010 goto_map_list_iterate(goto_maps, goto_map) {
1011 goto_map_free(goto_map);
1012 } goto_map_list_iterate_end;
1013 goto_map_list_clear(goto_maps);
1015 goto_destination = NULL;
1016 goto_warned = FALSE;
1019 /**********************************************************************
1020 Called from control_unit_killed() in client/control.c
1021 ***********************************************************************/
1022 void goto_unit_killed(struct unit *punit)
1024 if (!goto_is_active()) {
1025 return;
1028 goto_map_unit_iterate(goto_maps, goto_map, ptest) {
1029 if (ptest == punit) {
1030 goto_map_free(goto_map);
1031 /* Still safe using goto_map pointer, as it is not used for
1032 * dereferencing, only as value. */
1033 goto_map_list_remove(goto_maps, goto_map);
1034 /* stop now, links are gone! */
1035 break;
1037 } goto_map_unit_iterate_end;
1040 /**********************************************************************
1041 Is goto state active?
1042 ***********************************************************************/
1043 bool goto_is_active(void)
1045 return (NULL != goto_maps && 0 != goto_map_list_size(goto_maps));
1048 /**************************************************************************
1049 Return the path length (in turns).
1050 WARNING: not useful for determining paths of scattered groups.
1051 ***************************************************************************/
1052 bool goto_get_turns(int *min, int *max)
1054 fc_assert_ret_val(min != NULL, FALSE);
1055 fc_assert_ret_val(max != NULL, FALSE);
1057 *min = FC_INFINITY;
1058 *max = -1;
1060 if (!goto_is_active()) {
1061 return FALSE;
1063 if (NULL == goto_destination) {
1064 /* Not a valid position. */
1065 return FALSE;
1068 if (hover_state == HOVER_CONNECT) {
1069 /* In connect mode, we want to know the turn number the activity will
1070 * be finished. */
1071 int activity_time = get_activity_time(goto_destination, client_player());
1073 goto_map_list_iterate(goto_maps, goto_map) {
1074 bool moved = FALSE;
1075 int turns = goto_map->connect.initial_turns;
1076 int i;
1078 for (i = 0; i < goto_map->num_parts; i++) {
1079 const struct pf_path *path = goto_map->parts[i].path;
1081 turns += pf_path_last_position(goto_map->parts[i].path)->turn;
1082 if (!moved && path->length > 1) {
1083 moved = TRUE;
1087 if (moved && activity_time > 0) {
1088 turns++;
1091 if (turns < *min) {
1092 *min = turns;
1094 if (turns > *max) {
1095 *max = turns;
1097 } goto_map_list_iterate_end;
1098 } else {
1099 /* In other modes, we want to know the turn number to reach the tile. */
1100 goto_map_list_iterate(goto_maps, goto_map) {
1101 int turns = 0;
1102 int i;
1104 for (i = 0; i < goto_map->num_parts; i++) {
1105 turns += pf_path_last_position(goto_map->parts[i].path)->turn;
1107 if (hover_state == HOVER_PATROL
1108 && goto_map->patrol.return_path != NULL) {
1109 turns += pf_path_last_position(goto_map->patrol.return_path)->turn;
1112 if (turns < *min) {
1113 *min = turns;
1115 if (turns > *max) {
1116 *max = turns;
1118 } goto_map_list_iterate_end;
1121 return TRUE;
1124 /****************************************************************************
1125 Returns the state of 'ptile': turn number to print, and whether 'ptile'
1126 is a waypoint.
1127 ****************************************************************************/
1128 bool goto_tile_state(const struct tile *ptile, enum goto_tile_state *state,
1129 int *turns, bool *waypoint)
1131 fc_assert_ret_val(ptile != NULL, FALSE);
1132 fc_assert_ret_val(turns != NULL, FALSE);
1133 fc_assert_ret_val(waypoint != NULL, FALSE);
1135 if (!goto_is_active()) {
1136 return FALSE;
1139 *state = -1;
1140 *turns = -1;
1141 *waypoint = FALSE;
1143 if (hover_state == HOVER_CONNECT) {
1144 /* In connect mode, we want to know the turn number the activity will
1145 * be finished. */
1146 int activity_time;
1148 if (tile_get_known(ptile, client_player()) == TILE_UNKNOWN) {
1149 return FALSE; /* We never connect on unknown tiles. */
1152 activity_time = get_activity_time(ptile, client_player());
1154 goto_map_list_iterate(goto_maps, goto_map) {
1155 const struct pf_path *path;
1156 const struct pf_position *pos = NULL; /* Keep compiler happy! */
1157 int map_turns = goto_map->connect.initial_turns;
1158 int turns_for_map = -2;
1159 bool moved = FALSE;
1160 int i, j;
1162 for (i = 0; i < goto_map->num_parts; i++) {
1163 if (i > 0 && goto_map->parts[i].start_tile == ptile) {
1164 *waypoint = TRUE;
1167 path = goto_map->parts[i].path;
1168 if (path == NULL) {
1169 continue;
1172 for (j = 0; j < path->length; j++) {
1173 pos = path->positions + j;
1174 if (!moved && j > 0) {
1175 moved = TRUE;
1177 if (pos->tile != ptile) {
1178 continue;
1180 if (activity_time > 0) {
1181 if (map_turns + pos->turn + moved > turns_for_map) {
1182 turns_for_map = map_turns + pos->turn + moved;
1184 } else if (pos->moves_left == 0) {
1185 if (map_turns + pos->turn > turns_for_map) {
1186 turns_for_map = map_turns + pos->turn + moved;
1190 map_turns += pos->turn;
1193 if (ptile == goto_destination) {
1194 fc_assert_ret_val(pos != NULL, FALSE);
1195 if (moved && activity_time > 0) {
1196 map_turns++;
1198 if (map_turns > *turns) {
1199 *state = (activity_time > 0 || pos->moves_left == 0
1200 ? GTS_EXHAUSTED_MP : GTS_MP_LEFT);
1201 *turns = map_turns;
1202 } else if (map_turns == *turns
1203 && *state == GTS_MP_LEFT
1204 && (activity_time > 0 || pos->moves_left == 0)) {
1205 *state = GTS_EXHAUSTED_MP;
1207 } else {
1208 if (activity_time > 0) {
1209 if (turns_for_map > *turns) {
1210 *state = GTS_TURN_STEP;
1211 *turns = turns_for_map;
1213 } else {
1214 if (turns_for_map + 1 > *turns) {
1215 *state = GTS_TURN_STEP;
1216 *turns = turns_for_map + 1;
1220 } goto_map_list_iterate_end;
1221 } else {
1222 /* In other modes, we want to know the turn number to reach the tile. */
1223 goto_map_list_iterate(goto_maps, goto_map) {
1224 const struct tile *destination;
1225 const struct pf_path *path;
1226 const struct pf_position *pos = NULL; /* Keep compiler happy! */
1227 int map_turns = 0;
1228 int turns_for_map = -2;
1229 int i, j;
1231 for (i = 0; i < goto_map->num_parts; i++) {
1232 if (i > 0 && goto_map->parts[i].start_tile == ptile) {
1233 *waypoint = TRUE;
1236 path = goto_map->parts[i].path;
1237 if (path == NULL) {
1238 continue;
1241 for (j = 0; j < path->length; j++) {
1242 pos = path->positions + j;
1243 if (pos->tile == ptile
1244 /* End turn case. */
1245 && (pos->moves_left == 0
1246 /* Waiting case. */
1247 || (j < path->length - 1 && (pos + 1)->tile == ptile))
1248 && map_turns + pos->turn > turns_for_map) {
1249 turns_for_map = map_turns + pos->turn;
1252 map_turns += pos->turn;
1255 if (hover_state == HOVER_PATROL
1256 && goto_map->patrol.return_path != NULL) {
1257 path = goto_map->patrol.return_path;
1258 for (j = 0; j < path->length; j++) {
1259 pos = path->positions + j;
1260 if (pos->tile == ptile
1261 /* End turn case. */
1262 && (pos->moves_left == 0
1263 /* Waiting case. */
1264 || (j < path->length - 1 && (pos + 1)->tile == ptile))
1265 && map_turns + pos->turn > turns_for_map) {
1266 turns_for_map = map_turns + pos->turn;
1269 map_turns += pos->turn;
1270 destination = pos->tile;
1271 } else {
1272 destination = goto_destination;
1275 if (ptile == destination) {
1276 fc_assert_ret_val(pos != NULL, FALSE);
1277 if (map_turns > *turns) {
1278 *state = (pos->moves_left == 0 ? GTS_EXHAUSTED_MP : GTS_MP_LEFT);
1279 *turns = map_turns;
1280 } else if (map_turns == *turns
1281 && *state == GTS_MP_LEFT
1282 && pos->moves_left == 0) {
1283 *state = GTS_EXHAUSTED_MP;
1285 } else {
1286 if (turns_for_map + 1 > *turns) {
1287 *state = GTS_TURN_STEP;
1288 *turns = turns_for_map + 1;
1291 } goto_map_list_iterate_end;
1294 return (*turns != -1 || *waypoint);
1297 /**********************************************************************
1298 Puts a line to dest_tile on the map according to the current
1299 goto_map.
1300 If there is no route to the dest then don't draw anything.
1301 ***********************************************************************/
1302 bool is_valid_goto_draw_line(struct tile *dest_tile)
1304 fc_assert_ret_val(goto_is_active(), FALSE);
1305 if (NULL == dest_tile) {
1306 return FALSE;
1309 /* assume valid destination */
1310 goto_destination = dest_tile;
1312 goto_map_list_iterate(goto_maps, goto_map) {
1313 if (!update_last_part(goto_map, dest_tile)) {
1314 goto_destination = NULL;
1316 } goto_map_list_iterate_end;
1318 /* Update goto data in info label. */
1319 update_unit_info_label(get_units_in_focus());
1320 return (NULL != goto_destination);
1323 /****************************************************************************
1324 Send a packet to the server to request that the current orders be
1325 cleared.
1326 ****************************************************************************/
1327 void request_orders_cleared(struct unit *punit)
1329 struct packet_unit_orders p;
1331 if (!can_client_issue_orders()) {
1332 return;
1335 /* Clear the orders by sending an empty orders path. */
1336 log_goto_packet("Clearing orders for unit %d.", punit->id);
1337 p.unit_id = punit->id;
1338 p.src_tile = tile_index(unit_tile(punit));
1339 p.repeat = p.vigilant = FALSE;
1340 p.length = 0;
1341 p.dest_tile = tile_index(unit_tile(punit));
1342 send_packet_unit_orders(&client.conn, &p);
1345 /**************************************************************************
1346 Send a path as a goto or patrol route to the server.
1347 **************************************************************************/
1348 static void send_path_orders(struct unit *punit, struct pf_path *path,
1349 bool repeat, bool vigilant,
1350 enum unit_orders orders,
1351 struct unit_order *final_order)
1353 struct packet_unit_orders p;
1354 int i;
1355 struct tile *old_tile;
1357 fc_assert_ret(path != NULL);
1358 fc_assert_ret_msg(unit_tile(punit) == path->positions[0].tile,
1359 "Unit %d has moved without goto cancelation.",
1360 punit->id);
1362 if (path->length == 1 && final_order == NULL) {
1363 return; /* No path at all, no need to spam the server. */
1366 memset(&p, 0, sizeof(p));
1367 p.unit_id = punit->id;
1368 p.src_tile = tile_index(unit_tile(punit));
1369 p.repeat = repeat;
1370 p.vigilant = vigilant;
1372 log_goto_packet("Orders for unit %d:", punit->id);
1374 /* We skip the start position. */
1375 p.length = path->length - 1;
1376 fc_assert(p.length < MAX_LEN_ROUTE);
1377 old_tile = path->positions[0].tile;
1379 log_goto_packet(" Repeat: %d. Vigilant: %d. Length: %d",
1380 p.repeat, p.vigilant, p.length);
1382 /* If the path has n positions it takes n-1 steps. */
1383 for (i = 0; i < path->length - 1; i++) {
1384 struct tile *new_tile = path->positions[i + 1].tile;
1386 if (same_pos(new_tile, old_tile)) {
1387 p.orders[i] = ORDER_FULL_MP;
1388 p.dir[i] = DIR8_ORIGIN;
1389 p.activity[i] = ACTIVITY_LAST;
1390 p.target[i] = EXTRA_NONE;
1391 log_goto_packet(" packet[%d] = wait: %d,%d", i, TILE_XY(old_tile));
1392 } else {
1393 p.orders[i] = orders;
1394 p.dir[i] = get_direction_for_step(old_tile, new_tile);
1395 p.activity[i] = ACTIVITY_LAST;
1396 p.target[i] = EXTRA_NONE;
1397 log_goto_packet(" packet[%d] = move %s: %d,%d => %d,%d",
1398 i, dir_get_name(p.dir[i]),
1399 TILE_XY(old_tile), TILE_XY(new_tile));
1401 old_tile = new_tile;
1404 if (p.orders[i - 1] == ORDER_MOVE
1405 && (is_non_allied_city_tile(old_tile, client_player()) != NULL
1406 || is_non_allied_unit_tile(old_tile, client_player()) != NULL
1407 || ((is_allied_city_tile(old_tile, client_player())
1408 || is_allied_unit_tile(old_tile, client_player()))
1409 && (can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1410 ACTION_ANY,
1411 DRO_FOREIGN,
1412 FALSE)
1413 || can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1414 ACTION_ANY,
1415 DS_ALLIANCE,
1416 TRUE)
1417 || can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1418 ACTION_ANY,
1419 DS_TEAM,
1420 TRUE))))) {
1421 /* Can't move to the target tile because of non allied unit/city or can
1422 * move to the target tile but may be able to perform an action to an
1423 * allied unit/city at the target tile. */
1424 p.orders[i - 1] = ORDER_ACTION_MOVE;
1427 if (final_order) {
1428 p.orders[i] = final_order->order;
1429 p.dir[i] = final_order->dir;
1430 p.activity[i] = (final_order->order == ORDER_ACTIVITY)
1431 ? final_order->activity : ACTIVITY_LAST;
1432 p.target[i] = final_order->target;
1433 p.length++;
1436 p.dest_tile = tile_index(old_tile);
1438 send_packet_unit_orders(&client.conn, &p);
1441 /**************************************************************************
1442 Send an arbitrary goto path for the unit to the server.
1443 **************************************************************************/
1444 void send_goto_path(struct unit *punit, struct pf_path *path,
1445 struct unit_order *final_order)
1447 send_path_orders(punit, path, FALSE, FALSE, ORDER_MOVE, final_order);
1450 /****************************************************************************
1451 Send orders for the unit to move it to the arbitrary tile. Returns
1452 FALSE if no path is found.
1453 ****************************************************************************/
1454 bool send_goto_tile(struct unit *punit, struct tile *ptile)
1456 struct pf_parameter parameter;
1457 struct pf_map *pfm;
1458 struct pf_path *path;
1460 goto_fill_parameter_base(&parameter, punit);
1461 pfm = pf_map_new(&parameter);
1462 path = pf_map_path(pfm, ptile);
1463 pf_map_destroy(pfm);
1465 if (path) {
1466 send_goto_path(punit, path, NULL);
1467 pf_path_destroy(path);
1468 return TRUE;
1469 } else {
1470 return FALSE;
1474 /****************************************************************************
1475 Send orders for the unit to move it to the arbitrary tile and attack
1476 everything it approaches. Returns FALSE if no path is found.
1477 ****************************************************************************/
1478 bool send_attack_tile(struct unit *punit, struct tile *ptile)
1480 struct pf_parameter parameter;
1481 struct pf_map *pfm;
1482 struct pf_path *path;
1484 goto_fill_parameter_base(&parameter, punit);
1485 parameter.move_rate = 0;
1486 parameter.is_pos_dangerous = NULL;
1487 parameter.get_moves_left_req = NULL;
1488 pfm = pf_map_new(&parameter);
1489 path = pf_map_path(pfm, ptile);
1490 pf_map_destroy(pfm);
1492 if (path) {
1493 send_path_orders(punit, path, false, false, ORDER_ACTION_MOVE, NULL);
1494 pf_path_destroy(path);
1495 return TRUE;
1497 return FALSE;
1500 /**************************************************************************
1501 Send the current patrol route (i.e., the one generated via HOVER_STATE)
1502 to the server.
1503 **************************************************************************/
1504 void send_patrol_route(void)
1506 fc_assert_ret(goto_is_active());
1507 goto_map_unit_iterate(goto_maps, goto_map, punit) {
1508 int i;
1509 struct pf_path *path = NULL;
1510 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1512 if (NULL == last_part->path) {
1513 /* Cannot move there */
1514 continue;
1517 for (i = 0; i < goto_map->num_parts; i++) {
1518 path = pf_path_concat(path, goto_map->parts[i].path);
1520 path = pf_path_concat(path, goto_map->patrol.return_path);
1522 send_path_orders(punit, path, TRUE, TRUE, ORDER_MOVE, NULL);
1524 pf_path_destroy(path);
1525 } goto_map_unit_iterate_end;
1528 /**************************************************************************
1529 Fill orders to build recursive roads.
1530 **************************************************************************/
1531 static bool order_recursive_roads(struct tile *ptile, struct extra_type *pextra,
1532 struct packet_unit_orders *p, int rec)
1534 if (rec > MAX_EXTRA_TYPES) {
1535 return FALSE;
1538 if (!is_extra_caused_by(pextra, EC_ROAD)) {
1539 return FALSE;
1542 extra_deps_iterate(&(pextra->reqs), pdep) {
1543 if (!tile_has_extra(ptile, pdep)) {
1544 if (!order_recursive_roads(ptile, pdep, p, rec + 1)) {
1545 return FALSE;
1548 } extra_deps_iterate_end;
1550 p->orders[p->length] = ORDER_ACTIVITY;
1551 p->dir[p->length] = DIR8_ORIGIN;
1552 p->activity[p->length] = ACTIVITY_GEN_ROAD;
1553 p->target[p->length] = extra_index(pextra);
1554 p->length++;
1556 return TRUE;
1559 /**************************************************************************
1560 Send the current connect route (i.e., the one generated via HOVER_STATE)
1561 to the server.
1562 **************************************************************************/
1563 void send_connect_route(enum unit_activity activity,
1564 struct extra_type *tgt)
1566 fc_assert_ret(goto_is_active());
1567 goto_map_unit_iterate(goto_maps, goto_map, punit) {
1568 int i;
1569 struct packet_unit_orders p;
1570 struct tile *old_tile;
1571 struct pf_path *path = NULL;
1572 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1574 if (NULL == last_part->path) {
1575 /* Cannot move there */
1576 continue;
1579 memset(&p, 0, sizeof(p));
1581 for (i = 0; i < goto_map->num_parts; i++) {
1582 path = pf_path_concat(path, goto_map->parts[i].path);
1585 p.unit_id = punit->id;
1586 p.src_tile = tile_index(unit_tile(punit));
1587 p.repeat = FALSE;
1588 p.vigilant = FALSE; /* Should be TRUE? */
1590 p.length = 0;
1591 old_tile = path->positions[0].tile;
1593 for (i = 0; i < path->length; i++) {
1594 switch (activity) {
1595 case ACTIVITY_IRRIGATE:
1596 if (!tile_has_extra(old_tile, tgt)) {
1597 /* Assume the unit can irrigate or we wouldn't be here. */
1598 p.orders[p.length] = ORDER_ACTIVITY;
1599 p.dir[p.length] = DIR8_ORIGIN;
1600 p.activity[p.length] = ACTIVITY_IRRIGATE;
1601 p.target[p.length] = extra_index(tgt);
1602 p.length++;
1604 break;
1605 case ACTIVITY_GEN_ROAD:
1606 order_recursive_roads(old_tile, tgt, &p, 0);
1607 break;
1608 default:
1609 log_error("Invalid connect activity: %d.", activity);
1610 break;
1613 if (i != path->length - 1) {
1614 struct tile *new_tile = path->positions[i + 1].tile;
1616 fc_assert(!same_pos(new_tile, old_tile));
1618 p.orders[p.length] = ORDER_MOVE;
1619 p.dir[p.length] = get_direction_for_step(old_tile, new_tile);
1620 p.activity[p.length] = ACTIVITY_LAST;
1621 p.target[p.length] = EXTRA_NONE;
1622 p.length++;
1624 old_tile = new_tile;
1628 p.dest_tile = tile_index(old_tile);
1630 send_packet_unit_orders(&client.conn, &p);
1631 } goto_map_unit_iterate_end;
1634 /**************************************************************************
1635 Send the current goto route (i.e., the one generated via
1636 HOVER_STATE) to the server. The route might involve more than one
1637 part if waypoints were used. FIXME: danger paths are not supported.
1638 **************************************************************************/
1639 void send_goto_route(void)
1641 fc_assert_ret(goto_is_active());
1642 goto_map_unit_iterate(goto_maps, goto_map, punit) {
1643 int i;
1644 struct pf_path *path = NULL;
1645 struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
1647 if (NULL == last_part->path) {
1648 /* Cannot move there */
1649 continue;
1652 for (i = 0; i < goto_map->num_parts; i++) {
1653 path = pf_path_concat(path, goto_map->parts[i].path);
1656 clear_unit_orders(punit);
1657 if (goto_last_order == ORDER_LAST) {
1658 send_goto_path(punit, path, NULL);
1659 } else {
1660 struct unit_order order;
1662 order.order = goto_last_order;
1663 order.dir = DIR8_ORIGIN;
1664 order.activity = ACTIVITY_LAST;
1665 order.target = EXTRA_NONE;
1667 /* ORDER_MOVE would require real direction,
1668 * ORDER_ACTIVITY would require real activity */
1669 fc_assert(goto_last_order != ORDER_MOVE
1670 && goto_last_order != ORDER_ACTIVITY);
1672 send_goto_path(punit, path, &order);
1674 pf_path_destroy(path);
1675 } goto_map_unit_iterate_end;
1678 /**************************************************************************
1679 Find the path to the nearest (fastest to reach) allied city for the
1680 unit, or NULL if none is reachable.
1681 ***************************************************************************/
1682 struct pf_path *path_to_nearest_allied_city(struct unit *punit)
1684 struct pf_parameter parameter;
1685 struct pf_map *pfm;
1686 struct pf_path *path = NULL;
1688 if (is_allied_city_tile(unit_tile(punit), unit_owner(punit))) {
1689 /* We're already on a city - don't go anywhere. */
1690 return NULL;
1693 goto_fill_parameter_base(&parameter, punit);
1694 pfm = pf_map_new(&parameter);
1696 pf_map_tiles_iterate(pfm, ptile, FALSE) {
1697 if (is_allied_city_tile(ptile, unit_owner(punit))) {
1698 path = pf_map_path(pfm, ptile);
1699 break;
1701 } pf_map_tiles_iterate_end;
1703 pf_map_destroy(pfm);
1705 return path;
1708 /**************************************************************************
1709 Finds penultimate tile on path for given unit going to ptile
1710 ***************************************************************************/
1711 struct tile *tile_before_end_path(struct unit *punit, struct tile *ptile)
1713 struct pf_parameter parameter;
1714 struct pf_map *pfm;
1715 struct tile *dtile;
1716 struct pf_path *path;
1718 goto_fill_parameter_base(&parameter, punit);
1719 parameter.move_rate = 0;
1720 parameter.is_pos_dangerous = NULL;
1721 parameter.get_moves_left_req = NULL;
1722 pfm = pf_map_new(&parameter);
1723 path = pf_map_path(pfm, ptile);
1724 if (path == NULL) {
1725 return NULL;
1727 if (path->length < 2) {
1728 dtile = NULL;
1729 } else {
1730 dtile = path->positions[path->length - 2].tile;
1732 pf_map_destroy(pfm);
1734 return dtile;