Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2004:
[Freeciv-Dev] (PR#9818) Inland lakes and borders
Home

[Freeciv-Dev] (PR#9818) Inland lakes and borders

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#9818) Inland lakes and borders
From: "Mateusz Stefek" <mstefek@xxxxxxxxx>
Date: Thu, 26 Aug 2004 05:37:34 -0700
Reply-to: rt@xxxxxxxxxxx

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

Now that we have ocean numbers it seems natural that the next step we
should code are inland lakes in borders code. 

It isn't as easy as it looks. 
We have to know which continent surrounds the lake. This information is
needed, because we don't want to claim inland lakes on a different 
continent than the city is placed.

I decided that a lake is an ocean with no more than 10 tiles.

One problem with this patch is that an inland lake with an island on it
won't be claimed, because it's "surrounded" by two oceans.

I also attach one map with which you can compare old and new method.
--
mateusz
Index: maphand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v
retrieving revision 1.143
diff -u -r1.143 maphand.c
--- maphand.c   24 Aug 2004 20:27:11 -0000      1.143
+++ maphand.c   26 Aug 2004 12:15:17 -0000
@@ -40,6 +40,14 @@
 
 #include "maphand.h"
 
+#define MAXIMUM_CLAIMED_OCEAN_SIZE (10)
+
+/* Continent which is adjacent to a given ocean. -1 if the ocean is surrounded
+   by more than one continent */
+Continent_id lake_surrounders[MAP_NCONT];
+
+int ocean_sizes[MAP_NCONT];
+
 /**************************************************************************
   Number this tile and nearby tiles (recursively) with the specified
   continent number, using a flood-fill algorithm.
@@ -65,11 +73,45 @@
 }
 
 /**************************************************************************
+  Calculate lake_surrounders[] and ocean_sizes[] arrays
+**************************************************************************/
+static void calculate_inland_lakes(void)
+{
+  int i;
+
+  for (i = 1; i <= map.num_oceans; i++) {
+    ocean_sizes[i] = 0;
+    lake_surrounders[i] = 0;
+  }
+  
+  whole_map_iterate(x, y) {
+    Continent_id cont = map_get_continent(x, y);
+    if (cont > 0) {
+      /* land */
+      adjc_iterate(x, y, x2, y2) {
+        Continent_id cont2 = map_get_continent(x2, y2);
+       if (cont2 < 0) {
+         if (lake_surrounders[-cont2] == 0) {
+           lake_surrounders[-cont2] = cont;
+         } else if (lake_surrounders[-cont2] != cont) {
+           lake_surrounders[-cont2] = -1;
+         }
+       }
+      } adjc_iterate_end;
+    } else {
+      ocean_sizes[-cont]++;
+    }
+  } whole_map_iterate_end;
+}
+
+/**************************************************************************
   Assign continent and ocean numbers to all tiles, and set
   map.num_continents and map.num_oceans.
 
   Continents have numbers 1 to map.num_continents _inclusive_.
   Oceans have (negative) numbers -1 to -map.num_oceans _inclusive_.
+  
+  Also recalculate ocean_sizes[] and lake_surrounders[] arrays
 **************************************************************************/
 void assign_continent_numbers(void)
 {
@@ -98,6 +140,8 @@
     }
   } whole_map_iterate_end;
 
+  calculate_inland_lakes();
+
   freelog(LOG_VERBOSE, "Map has %d continents and %d oceans", 
          map.num_continents, map.num_oceans);
 }
@@ -1410,37 +1454,47 @@
 }
 
 /*************************************************************************
-  Returns TRUE if the given ocean tile is surrounded by at least 5 land
-  tiles of the same continent (N.B. will probably need modifications to
-  deal with topologies in which tiles do not have 8 neighbours). If this
-  is the case, the continent number of the land tiles is returned in *contp.
-  If multiple continents border the tile, FALSE is always returned.
-  This enables small seas (usually long inlets or inland lakes) to be
-  claimed by nations, rather than remaining as international waters. This
-  should in the long run perhaps be replaced with more general detection
-  of inland seas.
+  Ocean tile can be claimed iff one of the following conditions stands:
+  a) it is an inland lake not larger than MAXIMUM_OCEAN_SIZE
+  b) it is adjacent to only one continent and not more than two ocean tiles
+  c) It is one tile away from a city (This function doesn't check it)
+  The city, which claims the ocean has to be placed on the correct continent.
+  in case a) The continent which surrounds the inland lake
+  in case b) The only continent which is adjacent to the tile
+  The correct continent is returned in *contp.
 *************************************************************************/
 static bool is_claimed_ocean(int x, int y, Continent_id *contp)
 {
-  Continent_id cont = 0, numland = 0;
-
-  adjc_iterate(x, y, xp, yp) {
-    if (!is_ocean(map_get_terrain(xp, yp))) {
-      Continent_id thiscont = map_get_continent(xp, yp);
-
-      if (cont == 0) {
-       cont = thiscont;
-      }
-      if (cont == thiscont) {
-       numland++;
-      } else {
-       return FALSE;
+  Continent_id cont = map_get_continent(x, y);
+  Continent_id cont2, other;
+  int ocean_tiles;
+  
+  if (ocean_sizes[-cont] <= MAXIMUM_CLAIMED_OCEAN_SIZE &&
+      lake_surrounders[-cont] > 0) {
+    *contp = lake_surrounders[-cont];
+    return TRUE;
+  }
+  
+  other = 0;
+  ocean_tiles = 0;
+  adjc_iterate(x, y, x2, y2) {
+    cont2 = map_get_continent(x2, y2);
+    if (cont2 == cont) {
+      ocean_tiles++;
+    } else {
+      if (other == 0) {
+        other = cont2;
+      } else if (other != cont2) {
+        return FALSE;
       }
     }
   } adjc_iterate_end;
-
-  *contp = cont;
-  return (numland >= 5);
+  if (ocean_tiles <= 2) {
+    *contp = other;
+    return TRUE;
+  } else {
+    return FALSE;
+  }
 }
 
 /*************************************************************************

Attachment: borders.gz
Description: application/gzip


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