Author: cazfi
Date: Wed Dec 16 14:48:44 2015
New Revision: 31012

URL: http://svn.gna.org/viewcvs/freeciv?rev=31012&view=rev
Log:
Fixed pathfinding, especially when used for client goto functionality, handling 
of invalid
direction when there's no actual movement from tile to tile but two consequtive 
steps take
place on the same tile.

Reported by mir3x <mir3x>

See bug #24135

Modified:
    trunk/common/aicore/path_finding.c
    trunk/common/fc_types.h
    trunk/common/map.c

Modified: trunk/common/aicore/path_finding.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/aicore/path_finding.c?rev=31012&r1=31011&r2=31012&view=diff
==============================================================================
--- trunk/common/aicore/path_finding.c  (original)
+++ trunk/common/aicore/path_finding.c  Wed Dec 16 14:48:44 2015
@@ -96,10 +96,6 @@
 /* Down-cast macro. */
 #define PF_MAP(pfm) ((struct pf_map *) (pfm))
 
-/* Used as an enum direction8. */
-#define PF_DIR_NONE (-1)
-
-
 /* ========================== Common functions =========================== */
 
 /****************************************************************************
@@ -211,9 +207,10 @@
   signed short cost;    /* total_MC. 'cost' may be negative, see comment in
                          * pf_turns(). */
   unsigned extra_cost;  /* total_EC. Can be huge, (higher than 'cost'). */
-  signed dir_to_here : 4; /* Direction from which we came. It can be either
-                           * an 'enum direction8' or PF_DIR_NONE (so we need
-                           * 4 bits instead of 3). */
+  unsigned dir_to_here : 4; /* Direction from which we came. It's
+                             * an 'enum direction8' including
+                             * possibility of direction8_invalid (so we need
+                             * 4 bits) */
   unsigned status : 3;  /* 'enum pf_node_status' really. */
 
   /* Cached values */
@@ -424,7 +421,7 @@
 #endif /* PF_DEBUG */
   pos->fuel_left = 1;
   pos->dir_to_here = node->dir_to_here;
-  pos->dir_to_next_pos = PF_DIR_NONE;   /* This field does not apply. */
+  pos->dir_to_next_pos = direction8_invalid();   /* This field does not apply. 
*/
 
   if (node->cost > 0) {
     pf_finalize_position(params, pos);
@@ -441,7 +438,7 @@
 {
   struct pf_normal_node *node = pfnm->lattice + tile_index(dest_tile);
   const struct pf_parameter *params = pf_map_parameter(PF_MAP(pfnm));
-  enum direction8 dir_next = PF_DIR_NONE;
+  enum direction8 dir_next = direction8_invalid();
   struct pf_path *path;
   struct tile *ptile;
   int i;
@@ -927,7 +924,7 @@
    * (see pf_turns()). */
   node->cost = pf_move_rate(params) - pf_moves_left_initially(params);
   node->extra_cost = 0;
-  node->dir_to_here = PF_DIR_NONE;
+  node->dir_to_here = direction8_invalid();
   node->status = NS_PROCESSED;
 
   return PF_MAP(pfnm);
@@ -946,9 +943,10 @@
   signed short cost;    /* total_MC. 'cost' may be negative, see comment in
                          * pf_turns(). */
   unsigned extra_cost;  /* total_EC. Can be huge, (higher than 'cost'). */
-  signed dir_to_here : 4; /* Direction from which we came. It can be either
-                           * an 'enum direction8' or PF_DIR_NONE (so we need
-                           * 4 bits instead of 3). */
+  unsigned dir_to_here : 4; /* Direction from which we came. It's
+                             * an 'enum direction8' including
+                             * possibility of direction8_invalid (so we need
+                             * 4 bits) */
   unsigned status : 3;  /* 'enum pf_node_status' really. */
 
   /* Cached values */
@@ -1180,7 +1178,7 @@
 #endif /* PF_DEBUG */
   pos->fuel_left = 1;
   pos->dir_to_here = node->dir_to_here;
-  pos->dir_to_next_pos = PF_DIR_NONE;   /* This field does not apply. */
+  pos->dir_to_next_pos = direction8_invalid();   /* This field does not apply. 
*/
 
   if (node->cost > 0) {
     pf_finalize_position(params, pos);
@@ -1214,7 +1212,7 @@
                              struct tile *ptile)
 {
   struct pf_path *path = fc_malloc(sizeof(*path));
-  enum direction8 dir_next = PF_DIR_NONE;
+  enum direction8 dir_next = direction8_invalid();
   struct pf_danger_pos *danger_seg = NULL;
   bool waited = FALSE;
   struct pf_danger_node *node = pfdm->lattice + tile_index(ptile);
@@ -1287,7 +1285,7 @@
                          + params->moves_left_initially);
         pos->dir_to_next_pos = dir_next;
         pf_finalize_position(params, pos);
-        /* Set old_waited so that we record PF_DIR_NONE as a direction at
+        /* Set old_waited so that we record direction8_invalid() as a 
direction at
          * the step we were going to wait. */
         old_waited = TRUE;
         i--;
@@ -1317,7 +1315,7 @@
     pos->fuel_left = 1;
     pos->total_MC -= (pf_move_rate(params)
                       - pf_moves_left_initially(params));
-    pos->dir_to_next_pos = (old_waited ? PF_DIR_NONE : dir_next);
+    pos->dir_to_next_pos = (old_waited ? direction8_invalid() : dir_next);
     if (node->cost > 0) {
       pf_finalize_position(params, pos);
     }
@@ -1385,7 +1383,7 @@
 #endif /* PF_DEBUG */
 
   /* First iteration for determining segment length */
-  while (node->is_dangerous && PF_DIR_NONE != node->dir_to_here) {
+  while (node->is_dangerous && direction8_is_valid(node->dir_to_here)) {
     length++;
     ptile = mapstep(ptile, DIR_REVERSE(node->dir_to_here));
     node = pfdm->lattice + tile_index(ptile);
@@ -1416,7 +1414,7 @@
 
 #ifdef PF_DEBUG
   /* Make sure we reached a safe node or the start point */
-  fc_assert_ret(!node->is_dangerous || PF_DIR_NONE == node->dir_to_here);
+  fc_assert_ret(!node->is_dangerous || 
!direction8_is_valid(node->dir_to_here));
 #endif
 }
 
@@ -1492,7 +1490,7 @@
    * (the data of the tile for the pf_map), and index (the index of the
    * position in the Freeciv map). */
 
-  if (PF_DIR_NONE == node->dir_to_here
+  if (!direction8_is_valid(node->dir_to_here)
       && NULL != params->transported_by_initially) {
 #ifdef PF_DEBUG
     fc_assert(tile == params->start_tile);
@@ -1916,7 +1914,7 @@
    * (see pf_turns()). */
   node->cost = pf_move_rate(params) - pf_moves_left_initially(params);
   node->extra_cost = 0;
-  node->dir_to_here = PF_DIR_NONE;
+  node->dir_to_here = direction8_invalid();
   node->status = (node->is_dangerous ? NS_NEW : NS_PROCESSED);
 
   return PF_MAP(pfdm);
@@ -1940,9 +1938,10 @@
                          * pf_turns(). */
   unsigned extra_cost;  /* total_EC. Can be huge, (higher than 'cost'). */
   unsigned moves_left : 12; /* Moves left at this position. */
-  signed dir_to_here : 4; /* Direction from which we came. It can be either
-                           * an 'enum direction8' or PF_DIR_NONE (so we need
-                           * 4 bits instead of 3). */
+  unsigned dir_to_here : 4; /* Direction from which we came. It's
+                             * an 'enum direction8' including
+                             * possibility of direction8_invalid (so we need
+                             * 4 bits) */
   unsigned status : 3;  /* 'enum pf_node_status' really. */
 
   /* Cached values */
@@ -2330,7 +2329,7 @@
   pos->total_MC = (head->cost - pf_move_rate(params)
                    + pf_moves_left_initially(params));
   pos->dir_to_here = head->dir_to_here;
-  pos->dir_to_next_pos = PF_DIR_NONE;   /* This field does not apply. */
+  pos->dir_to_next_pos = direction8_invalid();   /* This field does not apply. 
*/
   pf_fuel_finalize_position(pos, params, node, head);
 }
 
@@ -2357,7 +2356,7 @@
                            struct tile *ptile)
 {
   struct pf_path *path = fc_malloc(sizeof(*path));
-  enum direction8 dir_next = PF_DIR_NONE;
+  enum direction8 dir_next = direction8_invalid();
   struct pf_fuel_node *node = pffm->lattice + tile_index(ptile);
   struct pf_fuel_pos *segment = node->segment;
   int length = 1;
@@ -2375,7 +2374,7 @@
   /* First iterate to find path length. */
   /* NB: the start point could be reached in the middle of a segment.
    * See comment for pf_fuel_map_create_segment(). */
-  while (PF_DIR_NONE != segment->dir_to_here) {
+  while (direction8_is_valid(segment->dir_to_here)) {
     if (node->moves_left_req == 0) {
       /* A refuel point. */
       if (segment != node->segment) {
@@ -2425,7 +2424,7 @@
       pos->moves_left = params->move_rate;
       pos->fuel_left = params->fuel;
       pos->dir_to_next_pos = dir_next;
-      dir_next = PF_DIR_NONE;
+      dir_next = direction8_invalid();
       segment = node->segment;
       i--;
       if (NULL == segment) {
@@ -2517,7 +2516,7 @@
     pos = pf_fuel_pos_replace(pos, node);
     node->pos = pos;
     next->prev = pf_fuel_pos_ref(pos);
-  } while (0 != node->moves_left_req && PF_DIR_NONE != node->dir_to_here);
+  } while (0 != node->moves_left_req && 
direction8_is_valid(node->dir_to_here));
 }
 
 /****************************************************************************
@@ -2620,7 +2619,7 @@
    * (the data of the tile for the pf_map), and index (the index of the
    * position in the Freeciv map). */
 
-  if (PF_DIR_NONE == node->dir_to_here
+  if (!direction8_is_valid(node->dir_to_here)
       && NULL != params->transported_by_initially) {
 #ifdef PF_DEBUG
     fc_assert(tile == params->start_tile);
@@ -3114,7 +3113,7 @@
   node->moves_left = pf_moves_left_initially(params);
   node->cost = pf_move_rate(params) - node->moves_left;
   node->extra_cost = 0;
-  node->dir_to_here = PF_DIR_NONE;
+  node->dir_to_here = direction8_invalid();
   node->status = NS_PROCESSED;
 
   return PF_MAP(pffm);
@@ -3333,8 +3332,8 @@
   pos->fuel_left = param->fuel_left_initially;
   pos->total_MC = 0;
   pos->total_EC = 0;
-  pos->dir_to_next_pos = PF_DIR_NONE;
-  pos->dir_to_here = PF_DIR_NONE;
+  pos->dir_to_next_pos = direction8_invalid();
+  pos->dir_to_here = direction8_invalid();
 }
 
 /****************************************************************************

Modified: trunk/common/fc_types.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/fc_types.h?rev=31012&r1=31011&r2=31012&view=diff
==============================================================================
--- trunk/common/fc_types.h     (original)
+++ trunk/common/fc_types.h     Wed Dec 16 14:48:44 2015
@@ -212,6 +212,7 @@
 #define SPECENUM_VALUE6NAME "South"
 #define SPECENUM_VALUE7 DIR8_SOUTHEAST
 #define SPECENUM_VALUE7NAME "Southeast"
+#define SPECENUM_INVALID ((enum direction8) (DIR8_SOUTHEAST + 1))
 #include "specenum_gen.h"
 
 /* No direction. Understood as the origin tile that a direction would have

Modified: trunk/common/map.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/map.c?rev=31012&r1=31011&r2=31012&view=diff
==============================================================================
--- trunk/common/map.c  (original)
+++ trunk/common/map.c  Wed Dec 16 14:48:44 2015
@@ -85,8 +85,8 @@
 const int DIR_DX[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
 const int DIR_DY[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
 
-static bool dir_cardinality[8];
-static bool dir_validity[8];
+static bool dir_cardinality[9]; /* Including invalid one */
+static bool dir_validity[9];    /* Including invalid one */
 
 static bool is_valid_dir_calculate(enum direction8 dir);
 static bool is_cardinal_dir_calculate(enum direction8 dir);
@@ -311,6 +311,13 @@
   fc_assert(map_num_tiles() <= MAP_MAX_SIZE * 1000);
 
   game.map.num_valid_dirs = game.map.num_cardinal_dirs = 0;
+
+  /* Values for direction8_invalid() */
+  fc_assert(direction8_invalid() == 8);
+  dir_validity[8] = FALSE;
+  dir_cardinality[8] = FALSE;
+
+  /* Values for actual directions */
   for (dir = 0; dir < 8; dir++) {
     if (is_valid_dir_calculate(dir)) {
       game.map.valid_dirs[game.map.num_valid_dirs] = dir;
@@ -1213,7 +1220,7 @@
 **************************************************************************/
 bool is_valid_dir(enum direction8 dir)
 {
-  fc_assert_ret_val(direction8_is_valid(dir), FALSE);
+  fc_assert_ret_val(dir <= direction8_invalid(), FALSE);
 
   return dir_validity[dir];
 }
@@ -1269,7 +1276,7 @@
 **************************************************************************/
 bool is_cardinal_dir(enum direction8 dir)
 {
-  fc_assert_ret_val(direction8_is_valid(dir), FALSE);
+  fc_assert_ret_val(dir <= direction8_invalid(), FALSE);
 
   return dir_cardinality[dir];
 }


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

Reply via email to