Author: pepeto
Date: Wed Jan 28 09:59:14 2015
New Revision: 27874

URL: http://svn.gna.org/viewcvs/freeciv?rev=27874&view=rev
Log:
Show patrol return path and related changes.

See gna bug #22692

Modified:
    branches/S2_6/client/control.c
    branches/S2_6/client/goto.c

Modified: branches/S2_6/client/control.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_6/client/control.c?rev=27874&r1=27873&r2=27874&view=diff
==============================================================================
--- branches/S2_6/client/control.c      (original)
+++ branches/S2_6/client/control.c      Wed Jan 28 09:59:14 2015
@@ -277,6 +277,7 @@
                 || state == HOVER_NONE);
   fc_assert_ret(state == HOVER_CONNECT || activity == ACTIVITY_LAST);
   fc_assert_ret(state == HOVER_GOTO || order == ORDER_LAST);
+  exit_goto_state();
   hover_state = state;
   connect_activity = activity;
   if (tgt) {
@@ -285,7 +286,6 @@
     connect_tgt = NULL;
   }
   goto_last_order = order;
-  exit_goto_state();
 }
 
 /****************************************************************************

Modified: branches/S2_6/client/goto.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_6/client/goto.c?rev=27874&r1=27873&r2=27874&view=diff
==============================================================================
--- branches/S2_6/client/goto.c (original)
+++ branches/S2_6/client/goto.c Wed Jan 28 09:59:14 2015
@@ -60,8 +60,14 @@
   struct unit *focus;
   struct part *parts;
   int num_parts;
-  int initial_turns;
-  int connect_speed;  /* scaled by ACTIVITY_FACTOR */
+  union {
+    struct {
+      int initial_turns;
+    } connect;
+    struct {
+      struct pf_path *return_path;
+    } patrol;
+  };
   struct pf_parameter template;
 };
 
@@ -87,7 +93,9 @@
 
 static void reset_last_part(struct goto_map *goto_map);
 static void remove_last_part(struct goto_map *goto_map);
-
+static void fill_parameter_part(struct pf_parameter *param,
+                                const struct goto_map *goto_map,
+                                const struct part *p);
 
 /**************************************************************************
   Various stuff for the goto routes
@@ -97,15 +105,13 @@
 /****************************************************************************
   Create a new goto map.
 ****************************************************************************/
-static struct goto_map *goto_map_new(void)
+static struct goto_map *goto_map_new(struct unit *punit)
 {
   struct goto_map *goto_map = fc_malloc(sizeof(*goto_map));
 
-  goto_map->focus = NULL;
+  goto_map->focus = punit;
   goto_map->parts = NULL;
   goto_map->num_parts = 0;
-  goto_map->initial_turns = 0;
-  goto_map->connect_speed = 0;
 
   return goto_map;
 }
@@ -120,6 +126,9 @@
       remove_last_part(goto_map);
     }
     free(goto_map->parts);
+  }
+  if (hover_state == HOVER_PATROL && goto_map->patrol.return_path) {
+    pf_path_destroy(goto_map->patrol.return_path);
   }
   free(goto_map);
 }
@@ -172,6 +181,75 @@
   return (NULL != goto_destination && ptile == goto_destination);
 }
 
+/****************************************************************************
+  Show goto lines.
+****************************************************************************/
+static void goto_path_redraw(const struct pf_path *new_path,
+                             const struct pf_path *old_path)
+{
+  int start_index = 0;
+  int i;
+
+  fc_assert_ret(new_path != NULL);
+
+  if (old_path != NULL) {
+    /* We had a path drawn already. Determine how much of it we can reuse
+     * in drawing the new path. */
+    for (i = 0; i < new_path->length - 1 && i < old_path->length - 1; i++) {
+      struct pf_position *old_pos = old_path->positions + i;
+      struct pf_position *new_pos = new_path->positions + i;
+
+      if (old_pos->dir_to_next_pos != new_pos->dir_to_next_pos
+          || old_pos->tile != new_pos->tile) {
+        break;
+      }
+    }
+    start_index = i;
+
+    /* Erase everything we cannot reuse. */
+    for (; i < old_path->length - 1; i++) {
+      struct pf_position *pos = old_path->positions + i;
+
+      if (is_valid_dir(pos->dir_to_next_pos)) {
+        mapdeco_remove_gotoline(pos->tile, pos->dir_to_next_pos);
+      } else {
+        fc_assert(pos->tile == (pos + 1)->tile);
+      }
+    }
+  }
+
+  /* Draw the new path. */
+  for (i = start_index; i < new_path->length - 1; i++) {
+    struct pf_position *pos = new_path->positions + i;
+
+    if (is_valid_dir(pos->dir_to_next_pos)) {
+      mapdeco_add_gotoline(pos->tile, pos->dir_to_next_pos);
+    } else {
+      fc_assert(pos->tile == (pos + 1)->tile);
+    }
+  }
+}
+
+/****************************************************************************
+  Remove goto lines.
+****************************************************************************/
+static void goto_path_undraw(const struct pf_path *path)
+{
+  int i;
+
+  fc_assert_ret(path != NULL);
+
+  for (i = 0; i < path->length - 1; i++) {
+    struct pf_position *pos = path->positions + i;
+
+    if (is_valid_dir(pos->dir_to_next_pos)) {
+      mapdeco_remove_gotoline(pos->tile, pos->dir_to_next_pos);
+    } else {
+      fc_assert(pos->tile == (pos + 1)->tile);
+    }
+  }
+}
+
 /********************************************************************** 
   Change the destination of the last part to the given location.
   If a path cannot be found, the destination is set to the start.
@@ -180,9 +258,14 @@
 static bool update_last_part(struct goto_map *goto_map,
                             struct tile *ptile)
 {
-  struct pf_path *new_path;
+  struct pf_path *old_path, *new_path;
   struct part *p = &goto_map->parts[goto_map->num_parts - 1];
-  int i, start_index = 0;
+
+  old_path = p->path;
+  if (old_path != NULL && pf_path_last_position(old_path)->tile == ptile) {
+    /* Nothing to update. */
+    return TRUE;
+  }
 
   log_debug("update_last_part(%d,%d) old (%d,%d)-(%d,%d)",
             TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
@@ -200,20 +283,16 @@
         goto_warned = TRUE;
       }
 
-      if (p->path) {
-        /* Remove the goto lines. */
-        for (i = 0; i < p->path->length - 1; i++) {
-          struct pf_position *a = &p->path->positions[i];
-
-          if (is_valid_dir(a->dir_to_next_pos)) {
-            mapdeco_remove_gotoline(a->tile, a->dir_to_next_pos);
-          } else {
-            fc_assert(i < p->path->length - 1
-                      && a->tile == p->path->positions[i + 1].tile);
-          }
-        }
-        pf_path_destroy(p->path);
+      if (old_path != NULL) {
+        goto_path_undraw(old_path);
+        pf_path_destroy(old_path);
         p->path = NULL;
+      }
+      if (hover_state == HOVER_PATROL
+          && goto_map->patrol.return_path != NULL) {
+        goto_path_undraw(goto_map->patrol.return_path);
+        pf_path_destroy(goto_map->patrol.return_path);
+        goto_map->patrol.return_path = NULL;
       }
       return FALSE;
     }
@@ -225,54 +304,79 @@
   log_goto_path("  path found:");
   pf_path_print(new_path, LOG_GOTO_PATH);
 
-  if (p->path) {
-    /* We had a path drawn already.  Determine how much of it we can reuse
-     * in drawing the new path. */
-    for (i = 0; i < MIN(new_path->length, p->path->length) - 1; i++) {
-      struct pf_position *a = &p->path->positions[i];
-      struct pf_position *b = &new_path->positions[i];
-
-      if (a->dir_to_next_pos != b->dir_to_next_pos
-         || !same_pos(a->tile, b->tile)) {
-       break;
-      }
-    }
-    start_index = i;
-
-    /* Erase everything we cannot reuse */
-    for (; i < p->path->length - 1; i++) {
-      struct pf_position *a = &p->path->positions[i];
-
-      if (is_valid_dir(a->dir_to_next_pos)) {
-        mapdeco_remove_gotoline(a->tile, a->dir_to_next_pos);
-      } else {
-        fc_assert(i < p->path->length - 1
-                  && a->tile == p->path->positions[i + 1].tile);
-      }
-    }
-    pf_path_destroy(p->path);
-    p->path = NULL;
-  }
-
-  /* Draw the new path */
-  for (i = start_index; i < new_path->length - 1; i++) {
-    struct pf_position *a = &new_path->positions[i];
-
-    if (is_valid_dir(a->dir_to_next_pos)) {
-      mapdeco_add_gotoline(a->tile, a->dir_to_next_pos);
-    } else {
-      fc_assert(i < new_path->length - 1
-                && a->tile == new_path->positions[i + 1].tile);
-    }
-  }
   p->path = new_path;
   p->end_tile = ptile;
-  p->end_moves_left = pf_path_last_position(p->path)->moves_left;
-  p->end_fuel_left = pf_path_last_position(p->path)->fuel_left;
+  p->end_moves_left = pf_path_last_position(new_path)->moves_left;
+  p->end_fuel_left = pf_path_last_position(new_path)->fuel_left;
+
+  if (hover_state == HOVER_PATROL) {
+    struct pf_parameter parameter;
+    struct pf_map *pfm;
+    struct pf_path *return_path;
+
+    fill_parameter_part(&parameter, goto_map, p);
+    pfm = pf_map_new(&parameter);
+    return_path = pf_map_path(pfm, goto_map->parts[0].start_tile);
+    pf_map_destroy(pfm);
+
+    if (return_path == NULL) {
+      log_goto_path("  no return path found");
+
+      if (p->start_tile == ptile) {
+        /* This mean we cannot reach the start point.  It is probably,
+         * a path-finding bug, but don't make infinite recursion. */
+
+        if (!goto_warned) {
+          log_error("No path found to reach the start point.");
+          goto_warned = TRUE;
+        }
+
+        if (old_path != NULL) {
+          goto_path_undraw(old_path);
+          pf_path_destroy(old_path);
+        }
+        pf_path_destroy(new_path);
+        p->path = NULL;
+        if (goto_map->patrol.return_path != NULL) {
+          goto_path_undraw(goto_map->patrol.return_path);
+          pf_path_destroy(goto_map->patrol.return_path);
+          goto_map->patrol.return_path = NULL;
+        }
+        return FALSE;
+      }
+
+      p->path = old_path;
+      p->end_tile = pf_path_last_position(old_path)->tile;
+      p->end_moves_left = pf_path_last_position(old_path)->moves_left;
+      p->end_fuel_left = pf_path_last_position(old_path)->fuel_left;
+      pf_path_destroy(new_path);
+      reset_last_part(goto_map);
+      return FALSE;
+    }
+
+    log_goto_path("  returned path found:");
+    pf_path_print(return_path, LOG_GOTO_PATH);
+
+    if (goto_map->patrol.return_path != NULL) {
+      /* We cannot re-use old path because:
+       * 1- the start tile isn't the same.
+       * 2- the turn number neither (impossible to do in backward mode). */
+      goto_path_undraw(goto_map->patrol.return_path);
+      pf_path_destroy(goto_map->patrol.return_path);
+    }
+    goto_path_redraw(return_path, NULL);
+    goto_map->patrol.return_path = return_path;
+  }
+
+  goto_path_redraw(new_path, old_path);
+  pf_path_destroy(old_path);
 
   log_goto_path("To (%d,%d) part %d: total_MC: %d",
                 TILE_XY(ptile), goto_map->num_parts,
-                pf_path_last_position(p->path)->total_MC);
+                pf_path_last_position(hover_state == HOVER_PATROL
+                                      ? goto_map->patrol.return_path
+                                      : new_path)->total_MC);
+
   return TRUE;
 }
 
@@ -638,7 +742,7 @@
    * will count as a full turn towards the activity time */
   moves_left = param->move_rate - (total_cost % param->move_rate);
   if (activity_time > 0) {
-    int speed = *(int *)param->data;
+    int speed = FC_PTR_TO_INT(param->data);
     activity_time = ((activity_time * ACTIVITY_FACTOR)
                      + (speed - 1)) / speed;
     activity_time--;
@@ -731,7 +835,7 @@
    * will count as a full turn towards the activity time */
   moves_left = param->move_rate - (total_cost % param->move_rate);
   if (activity_time > 0) {
-    int speed = *(int *)param->data;
+    int speed = FC_PTR_TO_INT(param->data);
     activity_time = ((activity_time * ACTIVITY_FACTOR)
                      + (speed - 1)) / speed;
     activity_time--;
@@ -773,7 +877,7 @@
   See also goto_fill_parameter_full().
 ****************************************************************************/
 static void goto_fill_parameter_base(struct pf_parameter *parameter,
-                                     struct unit *punit)
+                                     const struct unit *punit)
 {
   pft_fill_unit_parameter(parameter, punit);
 
@@ -806,41 +910,47 @@
 
   See also goto_fill_parameter_base().
 ****************************************************************************/
-static void goto_fill_parameter_full(struct pf_parameter *parameter,
-                                     struct unit *punit,
-                                     int *initial_turns, int *connect_speed)
-{
+static void goto_fill_parameter_full(struct goto_map *goto_map,
+                                     const struct unit *punit)
+{
+  struct pf_parameter *parameter = &goto_map->template;
+
   goto_fill_parameter_base(parameter, punit);
 
   fc_assert_ret(goto_is_active());
 
   switch (hover_state) {
   case HOVER_CONNECT:
-    if (connect_activity == ACTIVITY_IRRIGATE) {
-      parameter->get_costs = get_connect_irrig;
-    } else {
-      parameter->get_costs = get_connect_road;
-    }
-    parameter->get_moves_left_req = NULL;
-
-    *connect_speed = get_activity_rate(punit);
-    parameter->data = connect_speed;
-
-    /* Take into account the activity time at the origin */
     {
-      int activity_initial = get_activity_time(unit_tile(punit),
-                                               unit_owner(punit));
+      int activity_initial;
+      int speed;
+
+      if (connect_activity == ACTIVITY_IRRIGATE) {
+        parameter->get_costs = get_connect_irrig;
+      } else {
+        parameter->get_costs = get_connect_road;
+      }
+      parameter->get_moves_left_req = NULL;
+
+      speed = get_activity_rate(punit);
+      parameter->data = FC_INT_TO_PTR(speed);
+
+      /* Take into account the activity time at the origin */
+      activity_initial = get_activity_time(unit_tile(punit),
+                                           unit_owner(punit));
+
       if (activity_initial > 0) {
         /* First action is activity */
         parameter->moves_left_initially = parameter->move_rate;
         /* Number of turns, rounding up */
-        *initial_turns = ((activity_initial * ACTIVITY_FACTOR)
-                          + (*connect_speed - 1)) / *connect_speed;
+        goto_map->connect.initial_turns =
+            ((activity_initial * ACTIVITY_FACTOR + (speed - 1)) / speed);
         if (punit->moves_left == 0) {
-          (*initial_turns)++;
+          goto_map->connect.initial_turns++;
         }
-      }
-      /* Else '*initial_turns = 0' is done in goto_map_new(). */
+      } else {
+        goto_map->connect.initial_turns = 0;
+      }
     }
     break;
   case HOVER_NUKE:
@@ -852,6 +962,7 @@
     break;
   case HOVER_GOTO:
   case HOVER_PATROL:
+    goto_map->patrol.return_path = NULL;
     break;
   case HOVER_NONE:
   case HOVER_PARADROP:
@@ -874,14 +985,11 @@
   cancel_selection_rectangle();
 
   unit_list_iterate(punits, punit) {
-    struct goto_map *goto_map = goto_map_new();
-
-    goto_map->focus = punit;
+    struct goto_map *goto_map = goto_map_new(punit);
+
     goto_map_list_append(goto_maps, goto_map);
 
-    goto_fill_parameter_full(&goto_map->template, punit,
-                             &goto_map->initial_turns,
-                             &goto_map->connect_speed);
+    goto_fill_parameter_full(goto_map, punit);
     add_part(goto_map);
   } unit_list_iterate_end;
   goto_warned = FALSE;
@@ -961,7 +1069,7 @@
 
     goto_map_list_iterate(goto_maps, goto_map) {
       bool moved = FALSE;
-      int turns = goto_map->initial_turns;
+      int turns = goto_map->connect.initial_turns;
       int i;
 
       for (i = 0; i < goto_map->num_parts; i++) {
@@ -993,6 +1101,10 @@
       for (i = 0; i < goto_map->num_parts; i++) {
         turns += pf_path_last_position(goto_map->parts[i].path)->turn;
       }
+      if (hover_state == HOVER_PATROL
+          && goto_map->patrol.return_path != NULL) {
+        turns += pf_path_last_position(goto_map->patrol.return_path)->turn;
+      }
 
       if (turns < *min) {
         *min = turns;
@@ -1039,7 +1151,7 @@
     goto_map_list_iterate(goto_maps, goto_map) {
       const struct pf_path *path;
       const struct pf_position *pos = NULL; /* Keep compiler happy! */
-      int map_turns = goto_map->initial_turns;
+      int map_turns = goto_map->connect.initial_turns;
       int turns_for_map = -2;
       bool moved = FALSE;
       int i, j;
@@ -1106,6 +1218,7 @@
   } else {
     /* In other modes, we want to know the turn number to reach the tile. */
     goto_map_list_iterate(goto_maps, goto_map) {
+      const struct tile *destination;
       const struct pf_path *path;
       const struct pf_position *pos = NULL; /* Keep compiler happy! */
       int map_turns = 0;
@@ -1136,7 +1249,27 @@
         map_turns += pos->turn;
       }
 
-      if (ptile == goto_destination) {
+      if (hover_state == HOVER_PATROL
+          && goto_map->patrol.return_path != NULL) {
+        path = goto_map->patrol.return_path;
+        for (j = 0; j < path->length; j++) {
+          pos = path->positions + j;
+          if (pos->tile == ptile
+              /* End turn case. */
+              && (pos->moves_left == 0
+                  /* Waiting case. */
+                  || (j < path->length - 1 && (pos + 1)->tile == ptile))
+              && map_turns + pos->turn > turns_for_map) {
+            turns_for_map = map_turns + pos->turn;
+          }
+        }
+        map_turns += pos->turn;
+        destination = pos->tile;
+      } else {
+        destination = goto_destination;
+      }
+
+      if (ptile == destination) {
         fc_assert_ret_val(pos != NULL, FALSE);
         if (map_turns > *turns) {
           *state = (pos->moves_left == 0 ? GTS_EXHAUSTED_MP : GTS_MP_LEFT);
@@ -1326,10 +1459,7 @@
   fc_assert_ret(goto_is_active());
   goto_map_unit_iterate(goto_maps, goto_map, punit) {
     int i;
-    struct pf_map *pfm;
-    struct pf_path *return_path;
     struct pf_path *path = NULL;
-    struct pf_parameter parameter;
     struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
 
     if (NULL == last_part->path) {
@@ -1337,22 +1467,10 @@
       continue;
     }
 
-    fill_parameter_part(&parameter, goto_map, last_part);
-    pfm = pf_map_new(&parameter);
-    return_path = pf_map_path(pfm, goto_map->parts[0].start_tile);
-    if (!return_path) {
-      /* Cannot make a path */
-      pf_map_destroy(pfm);
-      continue;
-    }
-
     for (i = 0; i < goto_map->num_parts; i++) {
       path = pf_path_concat(path, goto_map->parts[i].path);
     }
-    path = pf_path_concat(path, return_path);
-
-    pf_map_destroy(pfm);
-    pf_path_destroy(return_path);
+    path = pf_path_concat(path, goto_map->patrol.return_path);
 
     send_path_orders(punit, path, TRUE, TRUE, NULL);
 


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to