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

 This patch adds terrain flag "FreshWater" and uses it instead of
hardcoded TERRAIN_LAKE_IDENTIFIER


 - Gets rid of hardcoded TERRAIN_LAKE_IDENTIFIER
 - Lake type terrain is not needed. If ruleset does not provide one,
normal ocean types are used
 - There can be several lake types and random one is used in each lake tile


 Further FIXME is that map_regenerate_water() is used only for
REgenerating water. Initial mapgenerating works quite differently, and
has no support for freshwater lakes at all!

 Lakes are really rare. One has to set landmass to MAX and still most
maps have no such very small bodies of water. DEFAULT_SEA_LAKE_SIZE
should be adjusted up a bit, or prefereable read from ruleset.


 - ML

diff -Nurd -X.diff_ignore freeciv/common/terrain.c freeciv/common/terrain.c
--- freeciv/common/terrain.c    2008-04-09 16:29:22.000000000 +0300
+++ freeciv/common/terrain.c    2008-06-12 18:02:15.000000000 +0300
@@ -207,6 +207,47 @@
 }
 
 /****************************************************************************
+  Return terrain having the flag. If several terrains have the flag,
+  random one is returned.
+****************************************************************************/
+struct terrain *rand_terrain_by_flag(enum terrain_flag_id flag)
+{
+  int num = 0;
+  struct terrain *terr = NULL;
+
+  terrain_type_iterate(pterr) {
+    if (terrain_has_flag(pterr, flag)) {
+      num++;
+      if (myrand(num) == 1) {
+        terr = pterr;
+      }
+    }
+  } terrain_type_iterate_end;
+
+  return terr;
+}
+
+/****************************************************************************
+  Fill terrain with flag to buffer. Returns number of terrains found.
+  Return value can be greater than size of buffer.
+****************************************************************************/
+int terrains_by_flag(enum terrain_flag_id flag, struct terrain **buffer, int 
bufsize)
+{
+  int num = 0;
+
+  terrain_type_iterate(pterr) {
+    if (terrain_has_flag(pterr, flag)) {
+      if (num < bufsize) {
+        buffer[num] = pterr;
+      }
+      num++;
+    }
+  } terrain_type_iterate_end;
+
+  return num;
+}
+
+/****************************************************************************
   Return the (translated) name of the terrain.
   You don't have to free the return pointer.
 ****************************************************************************/
@@ -245,7 +286,8 @@
     "Starter",
     "CanHaveRiver",
     "UnsafeCoast",
-    "Oceanic"
+    "Oceanic",
+    "Freshwater"
   };
 
   assert(ARRAY_SIZE(flag_names) == TER_COUNT);
diff -Nurd -X.diff_ignore freeciv/common/terrain.h freeciv/common/terrain.h
--- freeciv/common/terrain.h    2008-03-08 16:12:52.000000000 +0200
+++ freeciv/common/terrain.h    2008-06-12 17:57:28.000000000 +0300
@@ -106,7 +106,8 @@
   TER_STARTER, /* Players will start on this terrain type. */
   TER_CAN_HAVE_RIVER, /* Terrains with this type can have S_RIVER on them. */
   TER_UNSAFE_COAST,/*this tile is not safe as coast, (all ocean / ice) */ 
-  TER_OCEANIC, /* This is an ocean terrain. */
+  TER_OCEANIC,     /* This is an water terrain. */
+  TER_FRESHWATER,  /* Fresh water terrain */
   TER_LAST
 };
 #define TER_FIRST (TER_NO_BARBS)
@@ -144,8 +145,8 @@
   char graphic_alt[MAX_LEN_NAME];
 
   char identifier; /* Single-character identifier used in savegames. */
+
 #define TERRAIN_WATER_IDENTIFIER ' '
-#define TERRAIN_LAKE_IDENTIFIER '+'
 #define TERRAIN_SEA_IDENTIFIER '-'
 #define TERRAIN_COAST_IDENTIFIER '.'
 #define TERRAIN_SHELF_IDENTIFIER ','
@@ -213,6 +214,7 @@
 struct terrain *find_terrain_by_identifier(const char identifier);
 struct terrain *find_terrain_by_rule_name(const char *name);
 struct terrain *find_terrain_by_translated_name(const char *name);
+struct terrain *rand_terrain_by_flag(enum terrain_flag_id flag);
 
 char terrain_identifier(const struct terrain *pterrain);
 const char *terrain_rule_name(const struct terrain *pterrain);
@@ -222,6 +224,8 @@
 enum terrain_flag_id find_terrain_flag_by_rule_name(const char *s);
 #define terrain_has_flag(terr, flag) BV_ISSET((terr)->flags, flag)
 
+int terrains_by_flag(enum terrain_flag_id flag, struct terrain **buffer, int 
bufsize);
+
 bool is_terrain_flag_near_tile(const struct tile *ptile,
                               enum terrain_flag_id flag);
 int count_terrain_flag_near_tile(const struct tile *ptile,
diff -Nurd -X.diff_ignore freeciv/data/civ1/terrain.ruleset 
freeciv/data/civ1/terrain.ruleset
--- freeciv/data/civ1/terrain.ruleset   2008-05-02 07:13:05.000000000 +0300
+++ freeciv/data/civ1/terrain.ruleset   2008-06-12 17:58:11.000000000 +0300
@@ -231,7 +231,7 @@
 cooler_wetter_result = "no"
 cooler_drier_result  = "no"
 native_to            = "Sea", "Air", "Missile"
-flags                = "Oceanic", "NoCities", "NoPollution"
+flags                = "Oceanic", "NoCities", "NoPollution", "FreshWater"
 property_ocean_depth = 0
 helptext             = _("\
 Oceans cover much of the world, and only sea units (Triremes and\
diff -Nurd -X.diff_ignore freeciv/data/civ2/terrain.ruleset 
freeciv/data/civ2/terrain.ruleset
--- freeciv/data/civ2/terrain.ruleset   2007-10-29 23:26:30.000000000 +0200
+++ freeciv/data/civ2/terrain.ruleset   2008-06-12 17:58:02.000000000 +0300
@@ -239,7 +239,7 @@
 cooler_wetter_result = "no"
 cooler_drier_result  = "no"
 native_to            = "Sea", "Air", "Missile", "Helicopter"
-flags                = "Oceanic", "NoCities", "NoPollution"
+flags                = "Oceanic", "NoCities", "NoPollution", "FreshWater"
 property_ocean_depth = 0
 helptext             = _("\
 Oceans cover much of the world, and only sea units (Triremes and\
diff -Nurd -X.diff_ignore freeciv/data/default/terrain.ruleset 
freeciv/data/default/terrain.ruleset
--- freeciv/data/default/terrain.ruleset        2008-03-30 13:28:03.000000000 
+0300
+++ freeciv/data/default/terrain.ruleset        2008-06-12 19:17:31.000000000 
+0300
@@ -245,7 +245,7 @@
 cooler_wetter_result = "no"
 cooler_drier_result  = "no"
 native_to            = "Sea", "Air", "Missile", "Helicopter", "Trireme"
-flags                = "Oceanic", "NoCities", "NoPollution"
+flags                = "Oceanic", "NoCities", "NoPollution", "FreshWater"
 property_ocean_depth = 0
 helptext             = _("\
 Oceans cover much of the world, and only sea units (Triremes and\
diff -Nurd -X.diff_ignore freeciv/server/maphand.c freeciv/server/maphand.c
--- freeciv/server/maphand.c    2008-04-05 01:48:20.000000000 +0300
+++ freeciv/server/maphand.c    2008-06-12 19:25:44.000000000 +0300
@@ -188,12 +188,15 @@
   Assumes assign_continent_numbers() and recalculate_lake_surrounders()
   have already been done!
   FIXME: insufficiently generalized, use terrain property.
+  FIXME: Results differ from initially generated waters, but this is not
+         used at all in normal map generation.
 **************************************************************************/
 void map_regenerate_water(void)
 {
+#define MAX_ALT_TER_TYPES 5
 #define DEFAULT_LAKE_SEA_SIZE (4)  /* should be configurable */
 #define DEFAULT_NEAR_COAST (6)
-  struct terrain *lake = find_terrain_by_identifier(TERRAIN_LAKE_IDENTIFIER);
+  struct terrain *lakes[MAX_ALT_TER_TYPES];
   struct terrain *sea = find_terrain_by_identifier(TERRAIN_SEA_IDENTIFIER);
   struct terrain *coast = find_terrain_by_identifier(TERRAIN_COAST_IDENTIFIER);
   struct terrain *shelf = find_terrain_by_identifier(TERRAIN_SHELF_IDENTIFIER);
@@ -202,6 +205,16 @@
   int coast_count = 0;
   int shelf_count = 0;
   int floor_count = 0;
+  int num_laketypes;
+
+  num_laketypes = terrains_by_flag(TER_FRESHWATER, lakes, sizeof(lakes));
+  if (num_laketypes > MAX_ALT_TER_TYPES) {
+    freelog(LOG_NORMAL, "Number of lake types in ruleset %d, considering only 
%d ones.",
+            num_laketypes, MAX_ALT_TER_TYPES);
+    num_laketypes = MAX_ALT_TER_TYPES;
+  }
+
+#undef MAX_ALT_TER_TYPES
 
   /* coasts, lakes, and seas */
   whole_map_iterate(ptile) {
@@ -215,8 +228,9 @@
       continue;
     }
     if (0 < lake_surrounders[-here]) {
-      if (DEFAULT_LAKE_SEA_SIZE < ocean_sizes[-here]) {
-        tile_change_terrain(ptile, lake);
+      if (DEFAULT_LAKE_SEA_SIZE < ocean_sizes[-here]
+          && num_laketypes > 0) {
+        tile_change_terrain(ptile, lakes[myrand(num_laketypes)]);
       } else {
         tile_change_terrain(ptile, sea);
       }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to