Complete.Org: Mailing Lists: Archives: freeciv-dev: July 2003:
[Freeciv-Dev] Re: (PR#3776) Goto sees ZOC but ignores it
Home

[Freeciv-Dev] Re: (PR#3776) Goto sees ZOC but ignores it

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: ChrisK@xxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#3776) Goto sees ZOC but ignores it
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxx>
Date: Tue, 15 Jul 2003 13:41:10 -0700
Reply-to: rt@xxxxxxxxxxxxxx

[ChrisK@xxxxxxxx - Sun Mar 23 23:24:35 2003]:

> CVS 23 MAR 2003 GTK 1
> 
> Here is a special case where goto computes a route through
> the enemy's ZOC while that ZOC is fully visible.
> 
> Login as chris. Start. Send tank from Umtata to the tile south of /
> next to Swazi.

Please try the attached patch.  Well, actually I have tried it already 
and it works.  But maybe you can find other cases where a fix is needed.

Note: fogged cities are considered occupied for the purposes of ZoC.  
Hopefully this resolves 3387 as well.

Best wishes,
G.

Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.53
diff -u -r1.53 goto.c
--- client/goto.c       2003/07/07 19:14:36     1.53
+++ client/goto.c       2003/07/15 20:36:02
@@ -25,6 +25,7 @@
 #include "pf_tools.h"
 #include "unit.h"
 
+#include "climap.h"
 #include "clinet.h"
 #include "control.h"
 #include "mapview_g.h"
@@ -337,6 +338,38 @@
   return TB_NORMAL;
 }
 
+/**************************************************************************
+  Is this square controlled by the pplayer?
+
+  This function is analogous to is_my_zoc of common/unit.c, but
+  because here at the client we do not possess full information, it
+  tries to guess.
+**************************************************************************/
+static bool get_ZOC(struct player *pplayer, int x0, int y0)
+{
+  square_iterate(x0, y0, 1, x1, y1) {
+    struct tile *ptile = map_get_tile(x1, y1);
+    struct city *pcity;
+
+    if (is_ocean(ptile->terrain)) {
+      continue;
+    }
+    if (is_non_allied_unit_tile(ptile, pplayer)) {
+      /* Note: above function will return NULL if there is a city there,
+       * even if the city is occupied */
+      return FALSE;
+    }
+    pcity = is_non_allied_city_tile(ptile, pplayer);
+    if (pcity && (pcity->occupied || tile_get_known(x1, y1) != TILE_KNOWN)) {
+      /* If the city is fogged, we assume it's occupied */
+      return FALSE;
+    }
+  } square_iterate_end;
+
+  return TRUE;
+}
+
+
 /********************************************************************** 
   Enter the goto state: activate, prepare PF-template and add the 
   initial part.
@@ -355,6 +388,7 @@
   assert(goto_map.template.get_TB == NULL);
   goto_map.template.get_TB = get_TB;
   goto_map.template.turn_mode = TM_WORST_TIME;
+  goto_map.template.get_zoc = get_ZOC;
 
   add_part();
   is_active = TRUE;
Index: common/aicore/path_finding.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.c,v
retrieving revision 1.9
diff -u -r1.9 path_finding.c
--- common/aicore/path_finding.c        2003/05/03 13:28:48     1.9
+++ common/aicore/path_finding.c        2003/07/15 20:36:02
@@ -205,17 +205,18 @@
     node->behavior = TB_NORMAL;
   }
 
-  if (params->zoc_used) {
+  if (params->get_zoc) {
     struct tile *tile = map_get_tile(x, y);
     bool my_zoc = (tile->city || tile->terrain == T_OCEAN
-                  || is_my_zoc(params->owner, x, y));
-    bool allied = (is_allied_unit_tile(tile, params->owner) != NULL);
-    bool enemy = (is_enemy_unit_tile(tile, params->owner) != NULL);
-
-    /* if my zoc 2 else if allied 1 else 0 */
-    /* Essentially, enemy tile is like allied tile, we should be allowed
-     * to go there (attack), but not to leave, necessarily */
-    node->zoc_number = (my_zoc ? 2 : ((allied || enemy) ? 1 : 0));
+                  || params->get_zoc(params->owner, x, y));
+    /* ZoC rules cannot prevent us from moving into/attacking an occupied 
+     * tile.  Other rules can, but we don't care about them here. */ 
+    bool occupied = (unit_list_size(&(map_get_tile(x, y)->units)) > 0
+                     || map_get_city(x, y));
+
+    /* 2 means can move unrestricted from/into it, 
+     * 1 means can move unrestricted into it, but not necessarily from it */
+    node->zoc_number = (my_zoc ? 2 : (occupied ? 1 : 0));
   }
 
   /* Evaluate the extra cost of the destination */
@@ -279,7 +280,7 @@
       }
 
       /* Is the move ZOC-ok? */
-      if (pf_map->params->zoc_used
+      if (pf_map->params->get_zoc
          && !(node->zoc_number > 1 || node1->zoc_number > 0)) {
        continue;
       }
@@ -834,7 +835,7 @@
       }
 
       /* Is the move ZOC-ok? */
-      if (pf_map->params->zoc_used
+      if (pf_map->params->get_zoc
          && !(node->zoc_number > 1 || node1->zoc_number > 2)) {
        continue;
       }
Index: common/aicore/path_finding.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.h,v
retrieving revision 1.2
diff -u -r1.2 path_finding.h
--- common/aicore/path_finding.h        2003/04/04 15:47:49     1.2
+++ common/aicore/path_finding.h        2003/07/15 20:36:02
@@ -125,8 +125,9 @@
  * we won't be able to leave (at least alive).
  * 
  * There are few other options in the path-finding, including "omniscience" 
- * (if true, all tiles are assumed to be KNOWN) and "zoc_used" (if true, we 
- * will consider restrictions imposed by zones of control upon our movements).
+ * (if true, all tiles are assumed to be KNOWN) and "get_zoc" callback (if 
+ * not NULL, we will consider restrictions imposed upon our movements by 
+ * zones of control).
  *
  *  
  * FORMULAE:
@@ -298,7 +299,6 @@
 
   struct player *owner;
 
-  bool zoc_used;               /* Do we care about zones of control? */
   bool omniscience;            /* Do we care if the tile is visible? */
 
   enum turn_mode turn_mode;    /* See definitions. */
@@ -323,11 +323,20 @@
   int (*get_EC) (int x, int y, enum known_type known,
                 struct pf_parameter * param);
 
+  /* Although the rules governing ZoC are universal, the amount of
+   * information available at server and client is different. To 
+   * compensate for it, we might need to supply our own version 
+   * of "common" is_my_zoc.  Also AI might need to partially ignore 
+   * ZoC for strategic planning purposes (take into account enemy cities 
+   * but not units for example).
+   * If this callback is NULL, ZoC are ignored.*/
+  bool (*get_zoc) (struct player *pplayer, int x, int y);
+
   /* 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) (int x, int y, enum known_type,
-                           struct pf_parameter * param);
+  bool (*is_pos_dangerous) (int x, int y, enum known_type,
+                            struct pf_parameter * param);
 
   /* User provided data. Can be used to attach arbitrary information
    * to the map. */
Index: common/aicore/pf_tools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/pf_tools.c,v
retrieving revision 1.2
diff -u -r1.2 pf_tools.c
--- common/aicore/pf_tools.c    2003/05/15 12:38:11     1.2
+++ common/aicore/pf_tools.c    2003/07/15 20:36:02
@@ -283,8 +283,12 @@
     die("unknown move_type");
   }
 
-  parameter->zoc_used = (unit_type(punit)->move_type == LAND_MOVING
-                        && !unit_flag(punit, F_IGZOC));
+  if (unit_type(punit)->move_type == LAND_MOVING 
+      && !unit_flag(punit, F_IGZOC)) {
+    parameter->get_zoc = is_my_zoc;
+  } else {
+    parameter->get_zoc = NULL;
+  }
 
   if (unit_flag(punit, F_TRIREME)
       && base_trireme_loss_pct(unit_owner(punit)) > 0) {
@@ -323,7 +327,7 @@
     die("Unsupported move_type");
   }
 
-  parameter->zoc_used = FALSE;
+  parameter->get_zoc = NULL;
 
   if (unit_flag(punit, F_TRIREME)
       && base_trireme_loss_pct(unit_owner(punit)) > 0) {

[Prev in Thread] Current Thread [Next in Thread]