<URL: http://bugs.freeciv.org/Ticket/Display.html?id=20772 >

Updating the patch for S2_1 at revision 13590.

Seulement dans common/aicore.old: aicore
Seulement dans common/aicore: .deps
diff -uad common/aicore.old/path_finding.c common/aicore/path_finding.c
--- common/aicore.old/path_finding.c	2007-09-14 19:20:47.000000000 +0200
+++ common/aicore/path_finding.c	2007-09-14 19:34:11.000000000 +0200
@@ -66,7 +66,7 @@
  * from mainstream node.
  */
 struct danger_node {
-  bool is_dangerous;
+  enum dangerous_level is_dangerous;
   bool waited;			/* TRUE if waited to get here */
   struct pf_danger_pos {
     enum direction8 dir;
@@ -498,8 +498,8 @@
   pf_map->lattice[pf_map->tile->index].extra_cost = 0;
   pf_map->lattice[pf_map->tile->index].dir_to_here = -1;
   if (pf_map->params->is_pos_dangerous) {
-    /* The starting point is safe */
-    pf_map->d_lattice[pf_map->tile->index].is_dangerous = FALSE;
+    /* The starting point cannot be set dangerous */
+    pf_map->d_lattice[pf_map->tile->index].is_dangerous = DL_SAFE;
   }
 
   return pf_map;
@@ -833,7 +833,7 @@
   }
 
   /* First iteration for determining segment length */
-  while(d_node->is_dangerous) {
+  while(d_node->is_dangerous != DL_SAFE) {
     length++;
     ptile = mapstep(ptile, DIR_REVERSE(node->dir_to_here));
     node = &pf_map->lattice[ptile->index];
@@ -864,14 +864,14 @@
   }
 
   /* Make sure we reached a safe node */
-  assert(!pf_map->d_lattice[ptile->index].is_dangerous);
+  assert(pf_map->d_lattice[ptile->index].is_dangerous == DL_SAFE);
 }
 
 /**********************************************************************
   Adjust cost taking into account possibility of making the move
 **********************************************************************/
-static int danger_adjust_cost(const struct pf_map *pf_map, int cost, 
-                              bool to_danger, int moves_left)
+static int danger_adjust_cost(const struct pf_map *pf_map, int cost,
+                              enum dangerous_level to_danger, int moves_left)
 {
 
   if (cost == PF_IMPOSSIBLE_MC) {
@@ -881,7 +881,7 @@
   cost = MIN(cost, get_move_rate(pf_map->params));
 
   if (pf_map->params->turn_mode == TM_BEST_TIME) {
-    if (to_danger && cost >= moves_left) {
+    if (to_danger != DL_SAFE && cost >= moves_left) {
       /* We would have to end the turn on a dangerous tile! */
       return PF_IMPOSSIBLE_MC;
     }
@@ -889,7 +889,7 @@
     /* Default is TM_WORST_TIME.  
      * It should be specified explicitly though! */
     if (cost > moves_left
-        || (to_danger && cost == moves_left)) {
+        || (to_danger != DL_SAFE && cost == moves_left)) {
       /* This move is impossible (at least without waiting) 
        * or we would end our turn on a dangerous tile */
       return PF_IMPOSSIBLE_MC;
@@ -950,8 +950,8 @@
 
       /* Dangerous tiles can be updated even after being processed */
       if ((pf_map->status[index1] == NS_PROCESSED 
-           || pf_map->status[index1] == NS_WAITING) 
-          && !d_node1->is_dangerous) {
+	   || pf_map->status[index1] == NS_WAITING) 
+	  && d_node1->is_dangerous == DL_SAFE) {
 	continue;
       }
 
@@ -999,7 +999,7 @@
       }
 
       /* Update costs and add to queue, if this is a better route to xy1 */
-      if (!d_node1->is_dangerous) {
+      if (d_node1->is_dangerous != DL_DANGEROUS) {
 	int cost_of_path = get_total_CC(pf_map, cost, extra);
 
 	if (pf_map->status[index1] == NS_UNINIT
@@ -1013,7 +1013,7 @@
             free(d_node1->danger_segment);
             d_node1->danger_segment = NULL;
           }
-	  if (d_node->is_dangerous) {
+	  if (d_node->is_dangerous != DL_SAFE) {
 	    /* Transition from red to blue, need to record the path back */
 	    create_danger_segment(pf_map, d_node1);
 	  } else {
@@ -1051,7 +1051,7 @@
     adjc_dir_iterate_end;
   }
 
-  if (!d_node->is_dangerous
+  if (d_node->is_dangerous == DL_SAFE
       && pf_map->status[pf_map->tile->index] != NS_WAITING
       && (get_moves_left(pf_map, node->cost)
 	  < get_move_rate(pf_map->params))) {
@@ -1086,7 +1086,7 @@
     freelog(LOG_DEBUG, "Considering waiting at (%d, %d)",
 	    pf_map->tile->x, pf_map->tile->y);
     return danger_iterate_map(pf_map);
-  } else if (pf_map->d_lattice[index].is_dangerous) {
+  } else if (pf_map->d_lattice[index].is_dangerous != DL_SAFE) {
     /* We don't return dangerous tiles */
     freelog(LOG_DEBUG, "Reached dangerous tile (%d, %d)",
 	    pf_map->tile->x, pf_map->tile->y);
@@ -1124,13 +1124,13 @@
   /* First iterate to find path length */
   while(!same_pos(iter_tile, pf_map->params->start_tile)) {
 
-    if (!d_node->is_dangerous && d_node->waited) {
+    if (d_node->is_dangerous == DL_SAFE && d_node->waited) {
       length += 2;
     } else {
       length++;
     }
 
-    if (!d_node->is_dangerous) {
+    if (d_node->is_dangerous != DL_DANGEROUS) {
       /* We are in the normal node and dir_to_here field is valid */
       dir_next = node->dir_to_here;
       /* d_node->danger_segment is the indicator of what lies ahead
@@ -1165,7 +1165,7 @@
     bool old_waited = FALSE;
 
     /* 1: Deal with waiting */
-    if (!d_node->is_dangerous) {
+    if (d_node->is_dangerous == DL_SAFE) {
       if (waited) {
         /* Waited at _this_ tile, need to record it twice in the path.
          * Here we record our state _after_ waiting (e.g. full move points) */
@@ -1189,7 +1189,7 @@
 
     /* 2: Fill the current position */
     path->positions[i].tile = iter_tile;
-    if (!d_node->is_dangerous) {
+    if (d_node->is_dangerous != DL_DANGEROUS) {
       path->positions[i].total_MC = node->cost;
       path->positions[i].total_EC = node->extra_cost;
     } else {
@@ -1214,7 +1214,7 @@
     }
 
     /* 4: Calculate the next direction */
-    if (!d_node->is_dangerous) {
+    if (d_node->is_dangerous != DL_DANGEROUS) {
       /* We are in the normal node and dir_to_here field is valid */
       dir_next = node->dir_to_here;
       /* d_node->danger_segment is the indicator of what lies ahead
@@ -1249,7 +1249,7 @@
   utiny_t status = pf_map->status[index];
   struct danger_node *d_node = &pf_map->d_lattice[index];
 
-  if (d_node->is_dangerous) {
+  if (d_node->is_dangerous == DL_DANGEROUS) {
     /* "Best" path to a dangerous tile is undefined */
     /* TODO: return the "safest" path */
     return NULL;
diff -uad common/aicore.old/path_finding.h common/aicore/path_finding.h
--- common/aicore.old/path_finding.h	2007-09-14 19:20:47.000000000 +0200
+++ common/aicore/path_finding.h	2007-09-14 19:28:50.000000000 +0200
@@ -285,6 +285,13 @@
   TM_WORST_TIME
 };
 
+/* Dangerous level */
+enum dangerous_level {
+  DL_SAFE,      /* Safe tile */
+  DL_UNSAFE,    /* Not safe, but ok for move */
+  DL_DANGEROUS, /* Not safe and dangerous move */
+};
+
 /* Full specification of a position and time to reach it. */
 struct pf_position {
   struct tile *tile;
@@ -357,11 +364,12 @@
    * If this callback is NULL, ZoC are ignored.*/
   bool (*get_zoc) (const struct player *pplayer, const struct tile *ptile);
 
-  /* If this callback is non-NULL and returns TRUE this position is
-   * dangerous. The unit will never end a turn at a dangerous
-   * position. Can be NULL. */
-  bool (*is_pos_dangerous) (const struct tile *ptile, enum known_type,
-                            struct pf_parameter * param);
+  /* If this callback is non-NULL and returns DL_DANGEROUS this position is
+   * dangerous. If the position is safe, it returns DL_SAFE, else DL_UNSAFE.
+   * The unit will never end a turn at a dangerous position. Can be NULL. */
+  enum dangerous_level (*is_pos_dangerous) (const struct tile *ptile,
+                                            enum known_type,
+                                            struct pf_parameter * param);
 
   /* This is a jumbo callback which overrides all previous ones.  It takes 
    * care of everything (ZOC, known, costs etc).  
diff -uad common/aicore.old/pf_tools.c common/aicore/pf_tools.c
--- common/aicore.old/pf_tools.c	2007-09-14 19:20:47.000000000 +0200
+++ common/aicore/pf_tools.c	2007-09-14 19:28:34.000000000 +0200
@@ -510,57 +510,90 @@
   Allow one move onto land (for use for ferries and land
   bombardment)
 ***********************************************************************/
-static bool trireme_is_pos_dangerous(const struct tile *ptile,
-				     enum known_type known,
-				     struct pf_parameter *param)
+static enum dangerous_level trireme_is_pos_dangerous(const struct tile *ptile,
+				                     enum known_type known,
+				                     struct pf_parameter *param)
 {
   /* Assume that unknown tiles are unsafe. */
   if (known == TILE_UNKNOWN) {
-    return TRUE;
+    return DL_DANGEROUS;
   }
 
   /* We test TER_UNSAFE even though under the current ruleset there is no
    * way for a trireme to be on a TER_UNSAFE tile. */
   /* Unsafe or unsafe-ocean tiles without cities are dangerous. */
   /* Pretend all land tiles are safe. */
-  return (ptile->city == NULL
-	  && is_ocean(ptile->terrain)
-	  && (terrain_has_flag(ptile->terrain, TER_UNSAFE) 
-	      || (is_ocean(ptile->terrain) && !is_safe_ocean(ptile))));
+  if (!tile_get_city(ptile)
+      && (terrain_has_flag(ptile->terrain, TER_UNSAFE)
+          || (is_ocean(ptile->terrain) && !is_safe_ocean(ptile)))) {
+    return DL_DANGEROUS;
+  }
+  return DL_SAFE;
+}
+
+/****************************************************************************
+  Check if there is a safe position to move.
+****************************************************************************/
+static bool is_there_safe_pos_near(const struct tile *src_tile,
+                                   struct player *pplayer, int max_moves)
+{
+  square_iterate(src_tile, max_moves / SINGLE_MOVE, ptile) {
+    if (tile_get_known(ptile, pplayer) != TILE_KNOWN) {
+      /* Cannot guess if the tile is safe */
+      continue;
+    }
+    if (is_allied_city_tile(ptile, pplayer)
+        || tile_has_special(ptile, S_AIRBASE)) {
+      return TRUE;
+    }
+  } square_iterate_end;
+  
+  return FALSE;
 }
+
 /****************************************************************************
   Position-dangerous callback for air units.
 ****************************************************************************/
-static bool air_is_pos_dangerous(const struct tile *ptile,
-				 enum known_type known,
-				 struct pf_parameter *param)
+static enum dangerous_level air_is_pos_dangerous(const struct tile *ptile,
+				                 enum known_type known,
+			                         struct pf_parameter *param)
 {
-  int moves = SINGLE_MOVE * real_map_distance(param->start_tile, ptile);
-  int fuel = param->fuel_left_initially - 1;
+  int moves_left;
+  bool is_enemy_tile;
 
   if (is_allied_city_tile(ptile, param->owner)) {
-    return FALSE;
+    return DL_SAFE;
   }
 
   if (tile_has_special(ptile, S_AIRBASE)) {
     /* All airbases are considered non-dangerous, although non-allied ones
      * are inaccessible. */
-    return FALSE;
+    return DL_SAFE;
   }
 
-  if (param->moves_left_initially + param->move_rate * fuel >= moves * 2) {
-    if (param->fuel_left_initially > 1
-        || ((param->fuel_left_initially > 2
-             || !BV_ISSET(param->unit_flags, F_ONEATTACK))
-            && (is_enemy_unit_tile(ptile, param->owner)
-                || (ptile->city && is_enemy_city_tile(ptile, param->owner))))) {
-      /* allow movement if fuelled, and attacks, even suicidal ones */
-      return FALSE;
+  moves_left = param->moves_left_initially
+               + param->move_rate * (param->fuel_left_initially - 1)
+               - SINGLE_MOVE * real_map_distance(param->start_tile, ptile);
+  is_enemy_tile = (is_enemy_unit_tile(ptile, param->owner)
+                   || (ptile->city && is_enemy_city_tile(ptile, param->owner)));
+  
+  if (BV_ISSET(param->unit_flags, F_MISSILE)
+      && moves_left >= 0 && is_enemy_tile) {
+    /* Suicidal attack */
+    return DL_SAFE;
+  }
+  
+  if (is_there_safe_pos_near(ptile, param->owner, moves_left)) {
+    if (!BV_ISSET(param->unit_flags, F_ONEATTACK)
+        || param->fuel == 0 || !is_enemy_tile
+        || (param->fuel_left_initially > 1 && moves_left >= param->move_rate)) {
+      /* Safe move or attack */
+      return DL_UNSAFE;
     }
   }
-
+  
   /* Carriers are ignored since they are likely to move. */
-  return TRUE;
+  return DL_DANGEROUS;
 }
 
 /**********************************************************************
@@ -568,35 +601,43 @@
   Allow one move onto land (for use for ferries and land
   bombardment)
 ***********************************************************************/
-static bool is_overlap_pos_dangerous(const struct tile *ptile,
-				     enum known_type known,
-				     struct pf_parameter *param)
+static enum dangerous_level is_overlap_pos_dangerous(const struct tile *ptile,
+				                     enum known_type known,
+				                     struct pf_parameter *param)
 {
   /* Unsafe tiles without cities are dangerous. */
   /* Pretend all land tiles are safe. */
-  return (ptile->city == NULL
-	  && is_ocean(ptile->terrain)
-	  && terrain_has_flag(ptile->terrain, TER_UNSAFE));
+  if (ptile->city == NULL
+      && is_ocean(ptile->terrain)
+      && terrain_has_flag(ptile->terrain, TER_UNSAFE)) {
+    return DL_DANGEROUS;
+  }
+  return DL_SAFE;
 }
 
 /**********************************************************************
   Position-dangerous callback for typical units.
 ***********************************************************************/
-static bool is_pos_dangerous(const struct tile *ptile, enum known_type known,
-			     struct pf_parameter *param)
+static enum dangerous_level is_pos_dangerous(const struct tile *ptile,
+                                             enum known_type known,
+			                     struct pf_parameter *param)
 {
   /* Unsafe tiles without cities are dangerous. */
-  return (ptile->terrain != T_UNKNOWN
-	  && terrain_has_flag(ptile->terrain, TER_UNSAFE)
-	  && ptile->city == NULL);
+  if (ptile->terrain != T_UNKNOWN
+      && terrain_has_flag(ptile->terrain, TER_UNSAFE)
+      && ptile->city == NULL) {
+    return DL_DANGEROUS;
+  }
+  return DL_SAFE;
 }
 
 /****************************************************************************
   Position-dangerous callback for amphibious movement.
 ****************************************************************************/
-static bool amphibious_is_pos_dangerous(const struct tile *ptile,
-					enum known_type known,
-					struct pf_parameter *param)
+static enum dangerous_level 
+amphibious_is_pos_dangerous(const struct tile *ptile,
+			    enum known_type known,
+			    struct pf_parameter *param)
 {
   struct pft_amphibious *amphibious = param->data;
   const bool ocean = is_ocean(ptile->terrain);
@@ -607,7 +648,7 @@
   } else if (!ocean && amphibious->land.is_pos_dangerous) {
     return amphibious->land.is_pos_dangerous(ptile, known, param);
   }
-  return FALSE;
+  return DL_SAFE;
 }
 
 /* =====================  Tools for filling parameters =============== */
@@ -653,7 +694,7 @@
       parameter->is_pos_dangerous = NULL;
     } else {
       /* Otherwise, don't risk fuel loss. */
-      parameter->is_pos_dangerous = air_is_pos_dangerous;
+      parameter->is_pos_dangerous = NULL;
       parameter->turn_mode = TM_WORST_TIME;
     }
     break;
Seulement dans common/aicore: .svn
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to