Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2004:
[Freeciv-Dev] (PR#9908) Make AI understand channels
Home

[Freeciv-Dev] (PR#9908) Make AI understand channels

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#9908) Make AI understand channels
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Thu, 2 Sep 2004 07:41:32 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=9908 >

On Sat, 21 Aug 2004, Gregory Berkolaiko wrote:
> On Mon, 16 Aug 2004, Per Inge Mathisen wrote:
> > I thought about adding ocean check to goto_is_sane(), but problem is we
> > might have a canal in a city. So I thought about making an aidata matrix
> > of canals that exist, but then I wondered if that was really worth the
> > trouble...
>
> Yes, it is worth the trouble, I need it for ferry building, so someone has
> to do it.

Done. Patch attached.

  - Per

Index: ai/aidata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v
retrieving revision 1.36
diff -u -r1.36 aidata.c
--- ai/aidata.c 30 Aug 2004 21:20:33 -0000      1.36
+++ ai/aidata.c 2 Sep 2004 14:39:12 -0000
@@ -143,6 +143,35 @@
   /* Increase from fear to terror if opponent actually has nukes */
   if (danger_of_nukes) ai->threats.nuclear++; /* sum of both fears */
 
+  /*** Channels ***/
+
+  /* Ways to cross from one ocean to another through a city. */
+  ai->channels = fc_calloc((ai->num_oceans + 1) * (ai->num_oceans + 1), 
+                           sizeof(int));
+  players_iterate(aplayer) {
+    if (pplayers_allied(pplayer, aplayer)) {
+      city_list_iterate(aplayer->cities, pcity) {
+        adjc_iterate(pcity->x, pcity->y, x2, y2) {
+          struct tile *ptile = map_get_tile(x2, y2);
+
+          if (is_ocean(ptile->terrain)) {
+            adjc_iterate(pcity->x, pcity->y, x3, y3) {
+              struct tile *ptile2 = map_get_tile(x3, y3);
+
+              if (is_ocean(ptile2->terrain) 
+                  && ptile->continent != ptile2->continent) {
+                ai->channels[(-ptile->continent) * ai->num_oceans
+                             + (-ptile2->continent)] = TRUE;
+                ai->channels[(-ptile2->continent) * ai->num_oceans
+                             + (-ptile->continent)] = TRUE;
+              }
+            } adjc_iterate_end;
+          }
+        } adjc_iterate_end;
+      } city_list_iterate_end;
+    }
+  } players_iterate_end;
+
   /*** Exploration ***/
 
   ai->explore.land_done = TRUE;
@@ -326,6 +355,7 @@
   free(ai->threats.continent); ai->threats.continent = NULL;
   free(ai->stats.workers);     ai->stats.workers = NULL;
   free(ai->stats.cities);      ai->stats.cities = NULL;
+  free(ai->channels);          ai->channels = NULL;
 }
 
 /**************************************************************************
@@ -354,6 +384,7 @@
 
   ai->govt_reeval = 0;
   ai->government_want = fc_calloc(game.government_count + 1, sizeof(int));
+  ai->channels = NULL;
 
   ai->diplomacy.target = NULL;
   ai->diplomacy.strategy = WIN_OPEN;
@@ -387,3 +418,13 @@
 
   free(ai->government_want);
 }
+
+/**************************************************************************
+  Is there a channel going from ocean c1 to ocean c2?
+**************************************************************************/
+bool ai_channel(struct player *pplayer, Continent_id c1, Continent_id c2)
+{
+  struct ai_data *ai = ai_data_get(pplayer);
+
+  return (c1 == c2 || ai->channels[ai->num_oceans * c1 + c2]);
+}
Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.15
diff -u -r1.15 aidata.h
--- ai/aidata.h 29 Aug 2004 19:43:37 -0000      1.15
+++ ai/aidata.h 2 Sep 2004 14:39:12 -0000
@@ -86,6 +86,9 @@
     bool sea_done;    /* nothing more to explore at sea */
   } explore;
 
+  /* Keep track of available ocean channels */
+  bool *channels;
+
   /* This struct is used for statistical unit building, eg to ensure
    * that we don't build too few or too many units of a given type. */
   struct {
@@ -136,5 +139,6 @@
 
 struct ai_data *ai_data_get(struct player *pplayer);
 
+bool ai_channel(struct player *pplayer, Continent_id c1, Continent_id c2);
 
 #endif
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.181
diff -u -r1.181 gotohand.c
--- server/gotohand.c   9 Aug 2004 05:24:35 -0000       1.181
+++ server/gotohand.c   2 Sep 2004 14:39:13 -0000
@@ -33,6 +33,7 @@
 #include "unithand.h"
 #include "unittools.h"
 
+#include "aidata.h"
 #include "aitools.h"
 
 #include "gotohand.h"
@@ -1231,6 +1232,9 @@
 bool goto_is_sane(struct unit *punit, int x, int y, bool omni)
 {  
   struct player *pplayer = unit_owner(punit);
+  struct city *pcity = map_get_city(x, y);
+  Continent_id my_continent = map_get_continent(punit->x, punit->y);
+  Continent_id xy_continent = map_get_continent(x, y);
 
   if (same_pos(punit->x, punit->y, x, y)) {
     return TRUE;
@@ -1249,37 +1253,39 @@
        * and with a boat */
       if (ground_unit_transporter_capacity(x, y, pplayer) > 0) {
         adjc_iterate(x, y, tmp_x, tmp_y) {
-          if (map_get_continent(tmp_x, tmp_y) == 
-              map_get_continent(punit->x, punit->y))
+          if (map_get_continent(tmp_x, tmp_y) == my_continent) {
             /* The target is adjacent to our continent! */
             return TRUE;
+          }
         } adjc_iterate_end;
       }
     } else {
       /* Going to a land tile: better be our continent */
-      if (map_get_continent(punit->x, punit->y) == map_get_continent(x, y)) {
+      if (my_continent == xy_continent) {
         return TRUE;
       } else {
         /* Well, it's not our continent, but maybe we are on a boat
          * adjacent to the target continent? */
        adjc_iterate(punit->x, punit->y, tmp_x, tmp_y) {
-         if (map_get_continent(tmp_x, tmp_y) == map_get_continent(x, y)) {
+         if (map_get_continent(tmp_x, tmp_y) == xy_continent) {
            return TRUE;
           }
        } adjc_iterate_end;
       }
-    }
-      
+    }      
     return FALSE;
 
   case SEA_MOVING:
-    if (is_ocean(map_get_terrain(x, y))
-        || is_ocean_near_tile(x, y)) {
-      /* The target is sea or is accessible from sea 
-       * (allow for bombardment and visiting ports) */
-      return TRUE;
+    if (is_ocean(map_get_terrain(x, y))) {
+      if (ai_channel(pplayer, xy_continent, my_continent)) {
+        return TRUE; /* Ocean -> Ocean travel ok. */
+      }
+    } else if (is_ocean_near_tile(x, y)
+               && ((pcity && pplayers_allied(city_owner(pcity), pplayer))
+                   || !unit_flag(punit, F_NO_LAND_ATTACK))) {
+      return TRUE; /* Not ocean, but allied city or bombardment, so ok. */
     }
-    return FALSE;
+    return FALSE; /* Not ok. */
 
   default:
     return TRUE;

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#9908) Make AI understand channels, Per I. Mathisen <=