Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2004:
[Freeciv-Dev] (PR#9637) Ocean numbers
Home

[Freeciv-Dev] (PR#9637) Ocean numbers

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#9637) Ocean numbers
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxxx>
Date: Mon, 9 Aug 2004 04:44:44 -0700
Reply-to: rt@xxxxxxxxxxx

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

> [jdorje - Sun Aug 08 22:23:08 2004]:
> 
> And also...
> 
> I think you need to change the CONTINENT type in packets.def.  Currently 
> it is a UINT16.  It should be an SINT8, right?  And this change will 
> require a new capability.

It works fine as it is.  Do I have to change the type?

For the record, attached is the second version of patch with the check
for change (still) and with one loop for both oceans and continents.

G.
? cont.txt
? isles.gz
? rrr
? ttt.diff
? ttt.gz
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.203
diff -u -r1.203 map.h
--- common/map.h        5 Aug 2004 10:41:34 -0000       1.203
+++ common/map.h        9 Aug 2004 10:53:41 -0000
@@ -44,7 +44,7 @@
                           Player_no is index */
   int assigned; /* these can save a lot of CPU usage -- Syela */
   struct city *worked;      /* city working tile, or NULL if none */
-  unsigned short continent;
+  signed short continent;
   signed char move_cost[8]; /* don't know if this helps! */
   struct player *owner;     /* Player owning this tile, or NULL. */
   struct {
@@ -169,6 +169,7 @@
   bool have_huts;
   bool have_rivers_overlay;    /* only applies if !have_specials */
   int num_continents;
+  int num_oceans;
   struct tile *tiles;
 
   /* Only used by server. */
Index: server/mapgen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/mapgen.c,v
retrieving revision 1.142
diff -u -r1.142 mapgen.c
--- server/mapgen.c     5 Aug 2004 10:41:34 -0000       1.142
+++ server/mapgen.c     9 Aug 2004 10:53:41 -0000
@@ -1203,48 +1203,59 @@
 }
 
 /**************************************************************************
- Number this tile and recursive adjacent tiles with specified
- continent number, by flood-fill algorithm.
+  Number this tile and recursive adjacent tiles with specified
+  continent number, by flood-fill algorithm.
+  is_land tells us whether we are assigning continent numbers or ocean 
+  numbers.
 **************************************************************************/
-static void assign_continent_flood(int x, int y, int nr)
+static void assign_continent_flood(int x, int y, bool is_land, int nr)
 {
   if (map_get_continent(x, y) != 0) {
     return;
   }
 
-  if (is_ocean(map_get_terrain(x, y))) {
+  if ((is_land && is_ocean(map_get_terrain(x, y)))
+      || (!is_land && !is_ocean(map_get_terrain(x, y)))) {
     return;
   }
 
   map_set_continent(x, y, nr);
 
   adjc_iterate(x, y, x1, y1) {
-    assign_continent_flood(x1, y1, nr);
+    assign_continent_flood(x1, y1, is_land, nr);
   } adjc_iterate_end;
 }
 
 /**************************************************************************
- Assign continent numbers to all tiles.
- Also sets map.num_continents (note 0 is ocean, and continents
- have numbers 1 to map.num_continents _inclusive_).
- Note this is not used by generators 2,3 or 4 at map creation
- time, as these assign their own continent numbers.
+  Assign continent and ocean numbers to all tiles, 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_.
 **************************************************************************/
 void assign_continent_numbers(void)
 {
+  /* Initialize */
   map.num_continents = 0;
+  map.num_oceans = 0;
   whole_map_iterate(x, y) {
     map_set_continent(x, y, 0);
   } whole_map_iterate_end;
 
+  /* Assign new numbers */
   whole_map_iterate(x, y) {
-    if (map_get_continent(x, y) == 0 
-        && !is_ocean(map_get_terrain(x, y))) {
-      assign_continent_flood(x, y, ++map.num_continents);
+    if (map_get_continent(x, y) != 0) {
+      /* Already assigned */
+      continue;
     }
+    if (!is_ocean(map_get_terrain(x, y))) {
+      assign_continent_flood(x, y, TRUE, ++map.num_continents);
+    } else {
+      assign_continent_flood(x, y, FALSE, --map.num_oceans);
+    }      
   } whole_map_iterate_end;
 
-  freelog(LOG_VERBOSE, "Map has %d continents", map.num_continents);
+  freelog(LOG_VERBOSE, "Map has %d continents and %d oceans", 
+         map.num_continents, map.num_oceans);
 }
 
 /****************************************************************************
@@ -2326,7 +2337,9 @@
   } whole_map_iterate_end;
   if (!map.alltemperate) {
     make_polar();
-    assign_continent_numbers(); /* set poles numbers */
+    /* Set poles numbers.  After the map is generated continents will 
+     * be renumbered. */
+    assign_continent_numbers(); 
   }
   make_island(0, 0, pstate, 0);
   islands[2].starters = 0;
Index: server/maphand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v
retrieving revision 1.136
diff -u -r1.136 maphand.c
--- server/maphand.c    28 Jul 2004 15:24:43 -0000      1.136
+++ server/maphand.c    9 Aug 2004 10:53:41 -0000
@@ -1332,98 +1332,43 @@
 }
 
 /**************************************************************************
-  Recursively renumber the client continent at (x,y) with continent
-  number 'new'.  Ie, renumber (x,y) tile and recursive adjacent
-  land tiles with the same previous continent ('old').
-**************************************************************************/
-static void renumber_continent(int x, int y, int newnum)
-{
-  unsigned short old;
+  Checks for continent change after ocean<-->land change at (x,y).
 
-  if(!normalize_map_pos(&x, &y)) {
-    return;
-  }
-  
-  old = map_get_continent(x, y);
-  
-  map_set_continent(x, y, newnum);
-  adjc_iterate(x, y, i, j) {
-    if (!is_ocean(map_get_terrain(i, j))
-        && map_get_continent(i, j) == old) {
-      freelog(LOG_DEBUG,
-              " renumbering continent %d to %d at (%d %d)", old, newnum, i, j);
-      renumber_continent(i, j, newnum);
-    }
-  } adjc_iterate_end;
-}
-
-/**************************************************************************
-  We just transformed (x,y). If we changed it from ocean to land, check to
-  see if we merged a continent. (assign a continent number if we didn't)
-  If we changed it from land to ocean, check to see if we split a continent 
-  in pieces.
-
-  There are two special cases: we raised atlantis and have ourselves a shiny
-  new island. so we set it to map.num_continents + 1 (this btw is impossible
-  under the current transform rules, but it's an easy enough case that we 
-  check for it here anyway), or we sunk a little atoll. In that case, we'll 
-  return FALSE, even though we lost a continent. 
-  It shouldn't make a difference.
-
-  As a bonus, we set the transformed tile's new continent number here.
+  The check is based on the reasoning that if continent renumbering does 
+  change the continent and ocean numbers, this change _must_ manifest 
+  itself around the tile which was changed (as well as in other places).  
+  So we save all continent numbers, renumber the continents and check 
+  the new numbers against the saved ones.
+  The only case not covered is then creating a lake or a new island (which
+  is impossible under current rules).  But then the number of 
+  oceans/continents would increase and we can easily check this too.
 **************************************************************************/
-static bool check_for_continent_change(int x, int y)
+static void check_continent_change(int x, int y)
 {
-  unsigned short con = 0, unused = map.num_continents + 1;
-
-  if (is_ocean(map_get_terrain(x, y))) {
-    map_set_continent(x, y, 0);
-    /* check for land surrounding this tile. */
-    adjc_iterate(x, y, i, j) {
-      if (!is_ocean(map_get_terrain(i, j))) {
-        /* we found a land tile, check for another */
-        adjc_iterate(x, y, l, m) {
-          if (!(l == i && j == m) && !is_ocean(map_get_terrain(l, m))) {
-            /* we found a second adjacent land tile. renumber it */
-            con = map_get_continent(l, m);
-            renumber_continent(l, m, unused);
-
-            /* did the original tile get renumbered? if it did, then we
-             * didn't split the continent. if it's different, then 
-             * we are the proud owner of separate continents */
-            if (map_get_continent(i, j) == unused) {
-              renumber_continent(l, m, con);
-            } else {
-              return TRUE;
-            }
-          }
-        } adjc_iterate_end; 
-      }
-    } adjc_iterate_end;
-  } else {
-    /* check for land surrounding this tile. */
-    adjc_iterate(x, y, i, j) {
-      if (!is_ocean(map_get_terrain(i, j))) {
-        if (con == 0) {
-          con = map_get_continent(i, j);
-        } else if (map_get_continent(i, j) != con) {
-          return TRUE;
-        }
-      }
-    } adjc_iterate_end;
-
-    if (con == 0) {
-      /* we raised atlantis */
-      map_set_continent(x, y, ++map.num_continents);
-
-      allot_island_improvs();
-    } else {
-      /* set the tile to something adjacent to it */
-      map_set_continent(x, y, con);
-    }
+  int old_num[8];
+  int old_n_cont = map.num_continents;
+  int old_n_oceans = map.num_oceans;
+  bool change;
+
+  /* Save the old numbers */
+  adjc_dir_iterate(x, y, x1, y1, dir) {
+    old_num[dir] = map_get_continent(x1, y1);
+  } adjc_dir_iterate_end;
+
+  /* Assign the new numbers */
+  assign_continent_numbers();
+
+  /* Check if the numbers changed */
+  change = (old_n_cont != map.num_continents 
+           || old_n_oceans != map.num_oceans);
+  adjc_dir_iterate(x, y, x1, y1, dir) {
+    change = (change || (old_num[dir] != map_get_continent(x1, y1)));
+  } adjc_dir_iterate_end;
+
+  if (change) {
+    allot_island_improvs();
+    send_all_known_tiles(NULL);
   }
-
-  return FALSE;
 }
 
 /**************************************************************************
@@ -1431,7 +1376,7 @@
   (Should be called after any potential ocean/land terrain changes.)
   Also, returns an enum ocean_land_change, describing the change, if any.
 
-  if we did a land change, we do everything in our power to avoid reassigning
+  if we did a land change, we try to avoid reassigning
   continent numbers.
 **************************************************************************/
 enum ocean_land_change check_terrain_ocean_land_change(int x, int y,
@@ -1444,13 +1389,7 @@
     ocean_to_land_fix_rivers(x, y);
     city_landlocked_sell_coastal_improvements(x, y);
 
-    if (check_for_continent_change(x, y)) {
-      assign_continent_numbers();
-
-      allot_island_improvs();
-
-      send_all_known_tiles(NULL);
-    }
+    check_continent_change(x, y);
     
     map_update_borders_landmass_change(x, y);
 
@@ -1459,13 +1398,7 @@
   } else if (!is_ocean(oldter) && is_ocean(newter)) {
     /* land to ocean ... */
 
-    if (check_for_continent_change(x, y)) {
-      assign_continent_numbers();
-
-      allot_island_improvs();
-
-      send_all_known_tiles(NULL);
-    }
+    check_continent_change(x, y);
 
     map_update_borders_landmass_change(x, y);
 
Index: server/sanitycheck.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sanitycheck.c,v
retrieving revision 1.45
diff -u -r1.45 sanitycheck.c
--- server/sanitycheck.c        27 Jul 2004 16:43:48 -0000      1.45
+++ server/sanitycheck.c        9 Aug 2004 10:53:41 -0000
@@ -103,10 +103,15 @@
     struct tile *ptile = map_get_tile(x, y);
     struct city *pcity = map_get_city(x, y);
     int cont = map_get_continent(x, y);
+
+    assert(cont != 0);
     if (is_ocean(map_get_terrain(x, y))) {
-      assert(cont == 0);
+      adjc_iterate(x, y, x1, y1) {
+       if (is_ocean(map_get_terrain(x1, y1))) {
+         assert(map_get_continent(x1, y1) == cont);
+       }
+      } adjc_iterate_end;
     } else {
-      assert(cont != 0);
       adjc_iterate(x, y, x1, y1) {
        if (!is_ocean(map_get_terrain(x1, y1))) {
          assert(map_get_continent(x1, y1) == cont);
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.179
diff -u -r1.179 srv_main.c
--- server/srv_main.c   5 Aug 2004 11:34:18 -0000       1.179
+++ server/srv_main.c   9 Aug 2004 10:53:41 -0000
@@ -1688,9 +1688,7 @@
     map_fractal_generate();
   }
 
-  if (map.num_continents == 0) {
-    assign_continent_numbers();
-  }
+  assign_continent_numbers();
 
   gamelog_map();
   /* start the game */

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