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

Attached patch adds a function that recreates shallow coastal
areas for generator 3 (the island generator). This at least
makes triremes usable in the default ruleset.

The method is to make a "depth map" and use the gaussian
diffusion filter (smooth_int_map) to spread the height of 
the surrounding land into the ocean tiles. Then the function
pick_ocean is used to reassign ocean types based on these
new depth values.

Also, pick_ocean is moved to utilities.[ch] so that it can
be used outside of mapgen.c.


-----------------------------------------------------------------------
一つだけは確かだ。神様なのが欲しくない。
diff --git a/server/generator/mapgen.c b/server/generator/mapgen.c
index c8bf227..b36a183 100644
--- a/server/generator/mapgen.c
+++ b/server/generator/mapgen.c
@@ -325,30 +325,6 @@ static struct terrain *pick_terrain(enum mapgen_terrain_property target,
 }
 
 /**************************************************************************
-  Picks an ocean terrain to match the given depth.
-  Return NULL when there is no available ocean.
-**************************************************************************/
-static struct terrain *pick_ocean(int depth)
-{
-  struct terrain *best_terrain = NULL;
-  int best_match = TERRAIN_OCEAN_DEPTH_MAXIMUM;
-
-  terrain_type_iterate(pterrain) {
-    if (terrain_has_flag(pterrain, TER_OCEANIC)
-      &&  TERRAIN_OCEAN_DEPTH_MINIMUM <= pterrain->property[MG_OCEAN_DEPTH]) {
-      int match = abs(depth - pterrain->property[MG_OCEAN_DEPTH]);
-
-      if (best_match > match) {
-	best_match = match;
-	best_terrain = pterrain;
-      }
-    }
-  } terrain_type_iterate_end;
-
-  return best_terrain;
-}
-
-/**************************************************************************
   make_relief() will convert all squares that are higher than thill to
   mountains and hills. Note that thill will be adjusted according to
   the map.steepness value, so increasing map.mountains will result in
@@ -1235,6 +1211,10 @@ void map_fractal_generate(bool autosize, struct unit_type *initial_unit)
 	/* "variable" single player */
 	mapgenerator2();
       }
+
+      if (map.generator == 3) {
+        smooth_water_depth();
+      }
     }
 
     if (map.generator == 2) {
diff --git a/server/generator/utilities.c b/server/generator/utilities.c
index b381a54..e9d2e4a 100644
--- a/server/generator/utilities.c
+++ b/server/generator/utilities.c
@@ -459,3 +459,104 @@ struct terrain *most_shallow_ocean(void)
 
   return shallow;
 }
+
+/**************************************************************************
+  Picks an ocean terrain to match the given depth.
+  Return NULL when there is no available ocean.
+**************************************************************************/
+struct terrain *pick_ocean(int depth)
+{
+  struct terrain *best_terrain = NULL;
+  int best_match = TERRAIN_OCEAN_DEPTH_MAXIMUM;
+
+  terrain_type_iterate(pterrain) {
+    if (terrain_has_flag(pterrain, TER_OCEANIC)
+      &&  TERRAIN_OCEAN_DEPTH_MINIMUM <= pterrain->property[MG_OCEAN_DEPTH]) {
+      int match = abs(depth - pterrain->property[MG_OCEAN_DEPTH]);
+
+      if (best_match > match) {
+	best_match = match;
+	best_terrain = pterrain;
+      }
+    }
+  } terrain_type_iterate_end;
+
+  return best_terrain;
+}
+
+/**************************************************************************
+  Makes a simple depth map for all ocean tiles based on their proximity
+  to any land tiles and reassignes ocean terrain types based on their
+  MG_OCEAN_DEPTH property values.
+
+  This is used by the island generator to regenerate shallow ocean areas
+  near the coast.
+
+  FIXME: Make the generated shallow areas more interesting, and take into
+  account map parameters. Remove the need for this function by making
+  the generator automatically create shallow ocean areas when islands
+  are created.
+**************************************************************************/
+void smooth_water_depth(void)
+{
+  struct terrain *ocean_type;
+  int num_ocean_types = 0, depth, i;
+  int *dmap;
+  const int dmap_max = 100;
+  const int ocean_max = TERRAIN_OCEAN_DEPTH_MAXIMUM;
+  const int ocean_min = TERRAIN_OCEAN_DEPTH_MINIMUM;
+  const int ocean_span = ocean_max - ocean_min;
+
+  /* Approximately controls how far out the shallow areas will go. */
+  const int spread = 2;
+
+  terrain_type_iterate(pterrain) {
+    if (pterrain->property[MG_OCEAN_DEPTH] > 0) {
+      num_ocean_types++;
+    }
+  } terrain_type_iterate_end;
+
+  if (num_ocean_types < 2) {
+    return;
+  }
+
+  dmap = fc_malloc(MAP_INDEX_SIZE * sizeof(int));
+
+  whole_map_iterate(ptile) {
+    /* The depth values are reversed so that the diffusion
+     * filter causes land to "flow" out into the ocean. */
+    dmap[tile_index(ptile)] = is_ocean_tile(ptile) ? 0 : dmap_max;
+  } whole_map_iterate_end;
+
+  for (i = 0; i < spread; i++) {
+    /* Use the gaussian diffusion filter to "spread"
+     * the height of the land into the ocean. */
+    smooth_int_map(dmap, TRUE);
+  }
+
+  whole_map_iterate(ptile) {
+    if (!is_ocean_tile(ptile)) {
+      continue;
+    }
+
+    depth = dmap[tile_index(ptile)];
+
+    /* Reverse the diffusion filter hack. */
+    depth = dmap_max - depth;
+
+    /* Scale the depth value from the interval [0, dmap_max]
+     * to [ocean_min, ocean_max]. */
+    depth = ocean_min + ocean_span * depth / dmap_max;
+
+    /* Make sure that depth value is something that the
+     * function pick_ocean can understand. */
+    depth = CLIP(ocean_min, depth, ocean_max);
+
+    ocean_type = pick_ocean(depth);
+    if (ocean_type) {
+      tile_set_terrain(ptile, ocean_type);
+    }
+  } whole_map_iterate_end;
+
+  free(dmap);
+}
diff --git a/server/generator/utilities.h b/server/generator/utilities.h
index 6d5470d..772a4cd 100644
--- a/server/generator/utilities.h
+++ b/server/generator/utilities.h
@@ -16,12 +16,14 @@
 typedef void (*tile_knowledge_cb)(struct tile *ptile);
 
 void regenerate_lakes(tile_knowledge_cb knowledge_cb);
+void smooth_water_depth(void);
 void assign_continent_numbers(void);
 int get_lake_surrounders(Continent_id cont);
 int get_continent_size(Continent_id id);
 int get_ocean_size(Continent_id id);
 
 struct terrain *most_shallow_ocean(void);
+struct terrain *pick_ocean(int depth);
 
 /* Provide a block to convert from native to map coordinates.  For instance
  *   do_in_map_pos(mx, my, xn, yn) {
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to