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

Daniel Markstedt wrote:
> I'm generally for freedom. If the player wants to goto their stealth
> fighter to certain death, the gui should allow them to do it. It's not
> uncommon to make suicide attacks with air units anyway. Let's leave
> this behavior as it is.
> 
...
> The issue here is that the pathfinding code believes this goto can be
> completed, while the poor stealth fighter in fact only gets halfway
> and crashes. It must somehow believe the air unit will become refuled
> just because a friendly city is nearby. This is IMHO in the scope of
> this ticket.
> 
These are incompatible goals.  Here's the coding compromise:

* for AI, allow 1/2 round trip only when starting at fueling base.

* for user, allow up to 1/2 the remaining fuel, no matter where we're
starting.  This allows a user to set waypoints to control the path.  But
at the final step, they won't necessarily be able to land.

   int have = get_moves_left_initially(param);

   if (have >= moves * 2
    && (is_possible_base_fuel(param->start_tile, param)
     || !param->owner->ai.control)) {
     /* has enough fuel for round trip. */
     return FALSE;
   }

Found an existing static function for determining remaining moves in
path_finding.c -- made it accessible.  There are (at least) 3 different
ways being used to calculate this; perhaps this narrows down the solution.


> Certainly not for 2.1. It would be a useful feature if city-hopping
> could be done automagically, but as you say it can be done with
> waypoints.
> 
Found airgoto.c make_list_of_refuel_points() -- it just doesn't seem to
be used (or work) consistently.

(heavy sigh)

Anyway, I just checked this in to S2_1, and will handle the other branches
only after verification....

Committed S2_1 revision 13944.

Index: common/aicore/path_finding.h
===================================================================
--- common/aicore/path_finding.h        (revision 13943)
+++ common/aicore/path_finding.h        (working copy)
@@ -397,7 +397,7 @@
 /* The map itself.  Opaque type. */
 struct pf_map;
 
-/* ==================== Functions =================================== */
+/* ==================== Map/Path Functions ========================== */
 
 /* Returns a map which can be used to query for paths or to iterate
  * over all paths. Does not perform any computations itself, just sets
@@ -449,4 +449,8 @@
 /* Return the current parameters for the given map. */
 struct pf_parameter *pf_get_parameter(struct pf_map *map);
 
+/* ==================== Parameter Functions ========================= */
+
+int get_moves_left_initially(const struct pf_parameter *param);
+
 #endif
Index: common/aicore/pf_tools.c
===================================================================
--- common/aicore/pf_tools.c    (revision 13943)
+++ common/aicore/pf_tools.c    (working copy)
@@ -529,7 +529,19 @@
          && (terrain_has_flag(ptile->terrain, TER_UNSAFE) 
              || (is_ocean(ptile->terrain) && !is_safe_ocean(ptile))));
 }
+
 /****************************************************************************
+  Refueling base for air units.
+****************************************************************************/
+static bool is_possible_base_fuel(const struct tile *ptile,
+                                  struct pf_parameter *param)
+{
+  /* All airbases are considered possible, simply attack enemies. */
+  return (is_allied_city_tile(ptile, param->owner)
+       || tile_has_special(ptile, S_AIRBASE));
+}
+
+/****************************************************************************
   Position-dangerous callback for air units.
 ****************************************************************************/
 static bool is_pos_dangerous_fuel(const struct tile *ptile,
@@ -537,29 +549,30 @@
                                   struct pf_parameter *param)
 {
   int moves = SINGLE_MOVE * real_map_distance(param->start_tile, ptile);
-  int fuel = param->move_rate * param->fuel_left_initially;
+  int have = get_moves_left_initially(param);
 
-  if (fuel < moves) {
+  if (have < moves) {
     /* not enough fuel. */
     return TRUE;
   }
 
-  if (fuel >= moves * 2) {
+  if (have >= moves * 2
+   && (is_possible_base_fuel(param->start_tile, param)
+    || !param->owner->ai.control)) {
     /* has enough fuel for round trip. */
     return FALSE;
   }
 
-  if (fuel >= moves
-   && (is_allied_city_tile(ptile, param->owner)
-    || tile_has_special(ptile, S_AIRBASE))) {
-    /* All airbases are considered non-dangerous, although non-allied ones
-     * are inaccessible. */
+  if (TILE_UNKNOWN != known
+   && (is_possible_base_fuel(ptile, param)
+    || is_enemy_city_tile(ptile, param->owner))) {
+    /* allow attacks, even suicidal ones */
     return FALSE;
   }
 
-  if (is_enemy_unit_tile(ptile, param->owner)
-   || is_enemy_city_tile(ptile, param->owner)) {
-    /* allow attacks, even suicidal ones */
+  if (TILE_KNOWN == known
+   && is_enemy_unit_tile(ptile, param->owner)) {
+    /* don't reveal unknown units */
     return FALSE;
   }
 
Index: common/aicore/path_finding.c
===================================================================
--- common/aicore/path_finding.c        (revision 13943)
+++ common/aicore/path_finding.c        (working copy)
@@ -121,7 +121,7 @@
   turn.  Thus the rest of the PF code doesn't actually know that the unit
   has fuel, it just thinks it has that many more MP.
 ****************************************************************************/
-static int get_moves_left_initially(const struct pf_parameter *param)
+int get_moves_left_initially(const struct pf_parameter *param)
 {
   return (param->moves_left_initially
          + (param->fuel_left_initially - 1) * param->move_rate);
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to