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

I have updated your patch according to the preceeding
discussions, as it seemed a much easier solution than
having to muck about in the ai_fill_unit_param internals.

I replaced the "ignores zoc" condition with a check for
whether the unit is a military unit or not. This way
all units that would have to cancel a treaty to move
into peaceful borders do not try to do so, while units
that can move freely in peaceful territory go ahead and
explore it (e.g. explorers, workers, settlers, diplomats,
etc.).

Also, some minor style/comment/formatting fixes and a
version for trunk.


-----------------------------------------------------------------------
一緒に未踏の地を探検しませんか。
diff --git a/ai/aiexplorer.c b/ai/aiexplorer.c
index 3f7ffde..ac2ecb7 100644
--- a/ai/aiexplorer.c
+++ b/ai/aiexplorer.c
@@ -63,6 +63,63 @@ static int likely_ocean(struct tile *ptile, struct player *pplayer)
 }
 
 /**************************************************************************
+  Returns TRUE if a unit owned by the given player can safely "explore" the
+  given tile. This mainly takes care that military units do not try to
+  move into another player's territory in violation of a treaty.
+**************************************************************************/
+static bool ai_may_explore(const struct tile *ptile,
+                           const struct player *pplayer,
+                           const bv_flags unit_flags)
+{
+  /* Don't allow military units to cross borders. */
+  if (!BV_ISSET(unit_flags, F_CIVILIAN)
+      && players_non_invade(tile_owner(ptile), pplayer)) {
+    return FALSE;
+  }
+
+  /* Can't visit tiles with non-allied units. */
+  if (is_non_allied_unit_tile(ptile, pplayer)) {
+    return FALSE;
+  }
+
+  /* Non-allied cities are taboo even if no units are inside. */
+  if (tile_city(ptile) && !pplayers_allied(tile_owner(ptile), pplayer)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/***************************************************************************
+  TB function used by ai_explorer_goto().
+***************************************************************************/
+static enum tile_behavior ai_explorer_tb(const struct tile *ptile,
+                                         enum known_type k,
+                                         const struct pf_parameter *param)
+{
+  if (!ai_may_explore(ptile, param->owner, param->unit_flags)) {
+    return TB_IGNORE;
+  }
+  return TB_NORMAL;
+}
+
+/***************************************************************************
+  Constrained goto using ai_may_explore().
+***************************************************************************/
+static bool ai_explorer_goto(struct unit *punit, struct tile *ptile)
+{
+  struct pf_parameter parameter;
+  struct ai_risk_cost risk_cost;
+
+  ai_fill_unit_param(&parameter, &risk_cost, punit, ptile);
+  parameter.get_TB = ai_explorer_tb;
+
+  UNIT_LOG(LOG_DEBUG, punit, "ai_explorer_goto to %d,%d",
+           ptile->x, ptile->y);
+  return ai_unit_goto_constrained(punit, ptile, &parameter);
+}
+
+/**************************************************************************
 Return a value indicating how desirable it is to explore the given tile.
 In general, we want to discover unknown terrain of the opposite kind to
 our natural terrain, i.e. pedestrians like ocean and boats like land.
@@ -114,12 +171,13 @@ static int explorer_desirable(struct tile *ptile, struct player *pplayer,
   int unknown = 0;
 
   /* First do some checks that would make a tile completely non-desirable.
-   * If there
-   * is a city on the tile, or if the tile is not accessible, or if the 
-   * tile is on a different continent, or if we're a barbarian and
-   * the tile has a hut, don't go there. */
-  if (tile_city(ptile)
-      || (is_barbarian(pplayer) && tile_has_special(ptile, S_HUT))) {
+   * If we're a barbarian and the tile has a hut, don't go there. */
+  if (is_barbarian(pplayer) && tile_has_special(ptile, S_HUT)) {
+    return 0;
+  }
+
+  /* Do no try to cross borders and break a treaty, etc. */
+  if (!ai_may_explore(ptile, punit->owner, unit_type(punit)->flags)) {
     return 0;
   }
 
@@ -298,7 +356,7 @@ enum unit_move_result ai_manage_explorer(struct unit *punit)
   if (best_tile != NULL) {
     /* TODO: read the path off the map we made.  Then we can make a path 
      * which goes beside the unknown, with a good EC callback... */
-    if (!ai_unit_goto(punit, best_tile)) {
+    if (!ai_explorer_goto(punit, best_tile)) {
       /* Died?  Strange... */
       return MR_DEATH;
     }
diff --git a/ai/aiexplorer.c b/ai/aiexplorer.c
index 7f44a20..75fe158 100644
--- a/ai/aiexplorer.c
+++ b/ai/aiexplorer.c
@@ -108,6 +108,64 @@ static bool is_likely_trireme_loss(struct tile *ptile, struct player *pplayer,
 }
 
 /**************************************************************************
+  Returns TRUE if a unit owned by the given player can safely "explore" the
+  given tile. This mainly takes care that military units do not try to
+  move into another player's territory in violation of a treaty.
+**************************************************************************/
+static bool ai_may_explore(const struct tile *ptile,
+                           const struct player *pplayer,
+                           const bv_flags unit_flags)
+{
+  /* Don't allow military units to cross borders. */
+  if (!BV_ISSET(unit_flags, F_NONMIL)
+      && players_non_invade(tile_owner(ptile), pplayer)) {
+    return FALSE;
+  }
+
+  /* Can't visit tiles with non-allied units. */
+  if (is_non_allied_unit_tile(ptile, pplayer)) {
+    return FALSE;
+  }
+
+  /* Non-allied cities are taboo even if no units are inside. */
+  if (tile_get_city(ptile)
+      && !pplayers_allied(tile_owner(ptile), pplayer)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/***************************************************************************
+  TB function used by ai_explorer_goto().
+***************************************************************************/
+static enum tile_behavior ai_explorer_tb(const struct tile *ptile,
+                                         enum known_type k,
+                                         struct pf_parameter *param)
+{
+  if (!ai_may_explore(ptile, param->owner, param->unit_flags)) {
+    return TB_IGNORE;
+  }
+  return TB_NORMAL;
+}
+
+/***************************************************************************
+  Constrained goto using ai_may_explore().
+***************************************************************************/
+static bool ai_explorer_goto(struct unit *punit, struct tile *ptile)
+{
+  struct pf_parameter parameter;
+  struct ai_risk_cost risk_cost;
+
+  ai_fill_unit_param(&parameter, &risk_cost, punit, ptile);
+  parameter.get_TB = ai_explorer_tb;
+
+  UNIT_LOG(LOG_DEBUG, punit, "ai_explorer_goto to %d,%d",
+           ptile->x, ptile->y);
+  return ai_unit_goto_constrained(punit, ptile, &parameter);
+}
+
+/**************************************************************************
 Return a value indicating how desirable it is to explore the given tile.
 In general, we want to discover unknown terrain of the opposite kind to
 our natural terrain, i.e. pedestrians like ocean and boats like land.
@@ -159,17 +217,19 @@ static int explorer_desirable(struct tile *ptile, struct player *pplayer,
   int unknown = 0;
 
   /* First do some checks that would make a tile completely non-desirable.
-   * If we're a trireme and we could die at the given tile, or if there
-   * is a city on the tile, or if the tile is not accessible, or if the 
-   * tile is on a different continent, or if we're a barbarian and
-   * the tile has a hut, don't go there. */
+   * If we're a trireme and we could die at the given tile, or if we're a
+   * barbarian and the tile has a hut, don't go there. */
   if ((unit_has_type_flag(punit, F_TRIREME) && 
        is_likely_trireme_loss(ptile, pplayer, punit))
-      || tile_get_city(ptile)
       || (is_barbarian(pplayer) && tile_has_special(ptile, S_HUT))) {
     return 0;
   }
 
+  /* Do no try to cross borders and break a treaty, etc. */
+  if (!ai_may_explore(ptile, punit->owner, unit_type(punit)->flags)) {
+    return 0;
+  }
+
   /* What value we assign to the number of land and water tiles
    * depends on if we're a land or water unit. */
   if (is_ground_unit(punit)) {
@@ -345,7 +405,7 @@ enum unit_move_result ai_manage_explorer(struct unit *punit)
   if (best_tile != NULL) {
     /* TODO: read the path off the map we made.  Then we can make a path 
      * which goes beside the unknown, with a good EC callback... */
-    if (!ai_unit_goto(punit, best_tile)) {
+    if (!ai_explorer_goto(punit, best_tile)) {
       /* Died?  Strange... */
       return MR_DEATH;
     }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to