Author: cazfi
Date: Sat Jun 25 09:36:10 2016
New Revision: 33020

URL: http://svn.gna.org/viewcvs/freeciv?rev=33020&view=rev
Log:
Added fracture map genarator

Patch by Robert Finch <robfinch> and myself

See patch #6882

Added:
    trunk/server/generator/fracture_map.c
    trunk/server/generator/fracture_map.h
Modified:
    trunk/common/map_types.h
    trunk/server/generator/Makefile.am
    trunk/server/generator/mapgen.c
    trunk/server/settings.c

Modified: trunk/common/map_types.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/map_types.h?rev=33020&r1=33019&r2=33020&view=diff
==============================================================================
--- trunk/common/map_types.h    (original)
+++ trunk/common/map_types.h    Sat Jun 25 09:36:10 2016
@@ -42,7 +42,8 @@
   MAPGEN_RANDOM,
   MAPGEN_FRACTAL,
   MAPGEN_ISLAND,
-  MAPGEN_FAIR
+  MAPGEN_FAIR,
+  MAPGEN_FRACTURE
 };
 
 enum map_startpos {

Modified: trunk/server/generator/Makefile.am
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/generator/Makefile.am?rev=33020&r1=33019&r2=33020&view=diff
==============================================================================
--- trunk/server/generator/Makefile.am  (original)
+++ trunk/server/generator/Makefile.am  Sat Jun 25 09:36:10 2016
@@ -16,6 +16,8 @@
        mapgen_topology.h \
        utilities.c \
        utilities.h \
+       fracture_map.c \
+       fracture_map.h \
        height_map.c \
        height_map.h \
        startpos.c \

Added: trunk/server/generator/fracture_map.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/generator/fracture_map.c?rev=33020&view=auto
==============================================================================
--- trunk/server/generator/fracture_map.c       (added)
+++ trunk/server/generator/fracture_map.c       Sat Jun 25 09:36:10 2016
@@ -0,0 +1,362 @@
+/***********************************************************************
+ Freeciv - Copyright (C) 1996-2016 - The Freeciv Project
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <fc_config.h>
+#endif
+
+/* utility */
+#include "rand.h"
+
+/* common */
+#include "map.h"
+
+/* server/generator */
+#include "height_map.h"
+#include "mapgen_topology.h"
+#include "utilities.h"
+
+#include "fracture_map.h"
+
+static void circle_bresenham(int xc, int yc, int r, int nn);
+static void fmfill(int x, int y, int c, int r);
+static int local_ave_elevation(struct tile *ptile);
+
+extern int *height_map;
+int num_landmass = 50;
+
+typedef struct {
+  int x;
+  int y;
+} map_point;
+
+typedef struct {
+  int minX, minY;
+  int maxX, maxY;
+  int elevation;
+} map_landmass;
+
+/* Landmass: a chunk of rock with common properties */
+static map_landmass *landmass;
+static map_point *fracture_points;
+
+/**************************************************************************
+  Fracture map generator
+**************************************************************************/
+void make_fracture_map(void)
+{
+  int nn, mm;
+  int rad;
+  int x,y;
+  struct tile *ptile1;
+
+  /* Calculate the mountain level.  map.server.mountains specifies the
+   * percentage of land that is turned into hills and mountains. */
+  hmap_mountain_level = (((hmap_max_level - hmap_shore_level)
+                          * (100 - game.map.server.steepness))
+                         / 100 + hmap_shore_level);
+
+  /* For larger maps, increase the number of landmasses - makes the map more 
interesting */
+  num_landmass = 20 + 15 * get_sqsize();
+  landmass = (map_landmass *)fc_malloc((game.map.xsize / 2 + game.map.ysize / 
2 + num_landmass) * sizeof(map_landmass));
+  fracture_points = (map_point *)fc_malloc((game.map.xsize / 2 + 
game.map.ysize / 2 + num_landmass) * sizeof(map_point));
+  height_map = fc_malloc(sizeof(*height_map) * MAP_INDEX_SIZE);
+
+  /* Setup a whole bunch of landmasses along the view bordere. These will be 
sunken
+     to create ocean terrain.*/
+  nn = 0;
+  for (x = 3; x < game.map.xsize; x += 5, nn++) {
+    fracture_points[nn].x = x;
+    fracture_points[nn].y = 3;
+  }
+  for (x = 3; x < game.map.xsize; x += 5, nn++) {
+    fracture_points[nn].x = x;
+    fracture_points[nn].y = game.map.ysize - 3;
+  }
+  for (y = 3; y < game.map.ysize; y += 5, nn++) {
+    fracture_points[nn].x = 3;
+    fracture_points[nn].y = y;
+  }
+  for (y = 3; y < game.map.ysize; y += 5, nn++) {
+    fracture_points[nn].x = game.map.xsize - 3;
+    fracture_points[nn].y = y;
+  }
+
+  /* pick remaining points randomly */
+  mm = nn;
+  for (; nn < mm + num_landmass; nn++) {
+    fracture_points[nn].x = fc_rand(game.map.xsize - 6) + 3;
+    fracture_points[nn].y = fc_rand(game.map.ysize - 6) + 3;
+  }
+  for (nn = 0; nn < mm + num_landmass; nn++) {
+    landmass[nn].minX = game.map.xsize-1;
+    landmass[nn].minY = game.map.ysize-1;
+    landmass[nn].maxX = 0;
+    landmass[nn].maxY = 0;
+    x = fracture_points[nn].x;
+    y = fracture_points[nn].y;
+    ptile1 = native_pos_to_tile(x,y);
+    ptile1->continent = nn+1;
+  }
+
+  /* Assign a base elevation to the landmass */
+  for (nn = 0; nn < mm + num_landmass; nn++) {
+    if (nn < mm) { /* sink the border masses */
+      landmass[nn].elevation = 0;
+    } else {
+      landmass[nn].elevation = fc_rand(1000);
+    }
+  }
+
+  /* Assign cells to landmass. Gradually expand the radius of the 
+     fracture point. */
+  for (rad = 1; rad < (game.map.xsize >> 1); rad++) {
+    for (nn = 0; nn < mm + num_landmass; nn++) {
+      circle_bresenham(fracture_points[nn].x, fracture_points[nn].y, rad, 
nn+1);
+    }
+  }
+
+  /* put in some random fuzz */
+  whole_map_iterate(ptile) {
+    if (hmap(ptile) > hmap_shore_level) {
+      hmap(ptile) = hmap(ptile) + fc_rand(4) - 2;
+    }
+    if (hmap(ptile) <= hmap_shore_level) {
+      hmap(ptile) = hmap_shore_level + 1;
+    }
+  } whole_map_iterate_end;
+
+  adjust_int_map(height_map, hmap_max_level);
+  free(landmass);
+  free(fracture_points);
+}
+
+/**************************************************************************
+  An expanding circle from the fracture point is used to determine the
+   midpoint between fractures. The cells must be assigned to landmasses
+   anyway.
+**************************************************************************/
+static void circle_bresenham(int xc, int yc, int r, int nn)
+{
+  int x = 0; 
+  int y = r; 
+  int p = 3 - 2 * r;
+
+  if (!r) {
+    return;
+  }
+
+  while (y >= x) { /* only formulate 1/8 of circle */
+    fmfill(xc-x, yc-y, nn, r); /* upper left left */
+    fmfill(xc-y, yc-x, nn, r); /* upper upper left */
+    fmfill(xc+y, yc-x, nn, r); /* upper upper right */
+    fmfill(xc+x, yc-y, nn, r); /* upper right right */
+    fmfill(xc-x, yc+y, nn, r); /* lower left left */
+    fmfill(xc-y, yc+x, nn, r); /* lower lower left */
+    fmfill(xc+y, yc+x, nn, r); /* lower lower right */
+    fmfill(xc+x, yc+y, nn, r); /* lower right right */
+    if (p < 0) {
+      p += 4 * x++ + 6;
+    } else {
+      p += 4 * (x++ - y--) + 10;
+    }
+  }
+}
+
+/**************************************************************************
+   Assign landmass in 3x3 area increments to avoid "holes" created by the
+   circle algorithm.
+**************************************************************************/
+static void fmfill(int x, int y, int c, int r)
+{
+  int x1,x2,y1,y2;
+  struct tile *ptileXY;
+  struct tile *ptileX2Y;
+  struct tile *ptileX1Y;
+  struct tile *ptileXY2;
+  struct tile *ptileXY1;
+  struct tile *ptileX2Y1;
+  struct tile *ptileX2Y2;
+  struct tile *ptileX1Y2;
+  struct tile *ptileX1Y1;
+
+  if (x < 0) {
+    x = game.map.xsize+x;
+  } else if (x > game.map.xsize) {
+    x = x-game.map.xsize;
+  }
+  x1 = x - 1;
+  if (x1 < 0) {
+    x1 = game.map.xsize - 1;
+  }
+  x2 = x + 1;
+  if (x2 >= game.map.xsize) {
+    x2 = 0;
+  }
+  y1 = y - 1;
+  if (y1 < 0) {
+    y1 = game.map.ysize - 1;
+  }
+  y2 = y + 1;
+  if (y2 >= game.map.ysize) {
+    y2 = 0;
+  }
+
+  if (y >= 0 && y < game.map.ysize) {
+    ptileXY = native_pos_to_tile(x,y);
+    ptileX2Y = native_pos_to_tile(x2,y);
+    ptileX1Y = native_pos_to_tile(x1,y);
+    ptileXY2 = native_pos_to_tile(x,y2);
+    ptileXY1 = native_pos_to_tile(x,y1);
+    ptileX2Y1 = native_pos_to_tile(x2,y1);
+    ptileX2Y2 = native_pos_to_tile(x2,y2);
+    ptileX1Y2 = native_pos_to_tile(x1,y2);
+    ptileX1Y1 = native_pos_to_tile(x1,y1);
+
+    if (ptileXY->continent == 0 ) {
+      ptileXY->continent = c;
+      ptileX2Y->continent = c;
+      ptileX1Y->continent = c;
+      ptileXY2->continent = c;
+      ptileXY1->continent = c;
+      ptileX2Y2->continent = c;
+      ptileX2Y1->continent = c;
+      ptileX1Y2->continent = c;
+      ptileX1Y1->continent = c;
+      hmap(ptileXY) = landmass[c-1].elevation;
+      hmap(ptileX2Y) = landmass[c-1].elevation;
+      hmap(ptileX1Y) = landmass[c-1].elevation;
+      hmap(ptileXY2) = landmass[c-1].elevation;
+      hmap(ptileXY1) = landmass[c-1].elevation;
+      hmap(ptileX2Y1) = landmass[c-1].elevation;
+      hmap(ptileX2Y2) = landmass[c-1].elevation;
+      hmap(ptileX1Y2) = landmass[c-1].elevation;
+      hmap(ptileX1Y1) = landmass[c-1].elevation;
+      /* This bit of code could track the maximum and minimum extent
+         of the landmass. */
+      if (x < landmass[c-1].minX) {
+        landmass[c-1].minX = x;
+      }
+      if (x > landmass[c-1].maxX) {
+        landmass[c-1].maxX = x;
+      }
+      if (y < landmass[c-1].minY) {
+        landmass[c-1].minY = y;
+      }
+      if (y > landmass[c-1].maxY) {
+        landmass[c-1].maxY = y;
+      }
+    }
+  }
+}
+
+/**************************************************************************
+    Determine the local average elevation. Used to determine where hills
+    and mountains are. 
+**************************************************************************/
+static int local_ave_elevation(struct tile *ptile)
+{
+  int ele;
+  int n;
+
+  n = ele = 0;
+  square_iterate(ptile, 3, tile2) {
+    ele = ele + hmap(tile2);
+    n++;
+  } square_iterate_end;
+  ele /= n;
+
+  return ele;
+}
+
+/**************************************************************************
+  make_fracture_relief() Goes through a couple of iterations.
+  The first iteration chooses mountains and hills based on how much the
+  tile exceeds the elevation of the surrounding tiles. This will typically
+  causes hills and mountains to be placed along the edges of landmasses.
+  It can generate mountain ranges where there a differences in elevation
+  between landmasses.
+**************************************************************************/
+void make_fracture_relief(void)
+{
+  int choose_mountain;
+  int choose_hill;
+  int landarea;
+  int total_mtns;
+  int iter;
+
+  /* compute the land area */
+  landarea = 0;
+  whole_map_iterate(ptile) {
+    if (hmap(ptile) > hmap_shore_level) {
+      landarea++;
+    }
+  } whole_map_iterate_end;
+
+  /* Iteration 1
+     Choose hills and mountains based on local elevation.
+  */
+  total_mtns = 0;
+  whole_map_iterate(ptile) {
+    if (not_placed(ptile) && hmap(ptile) > hmap_shore_level) {  /* place on 
land only */
+      /* mountains */
+      choose_mountain = (hmap(ptile) > local_ave_elevation(ptile) * 1.20)
+        || (area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)) * 
(fc_rand(10) < 4));
+
+      choose_hill = (hmap(ptile) > local_ave_elevation(ptile) * 1.10)
+        || (area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)) * 
(fc_rand(10) < 4));
+      /* The following avoids hills and mountains directly along the coast. */
+      if (count_terrain_class_near_tile(ptile, TRUE, TRUE, TC_OCEAN) > 0) {
+        choose_mountain = 0;
+        choose_hill = 0;
+      }
+      if (choose_mountain) {
+        total_mtns++;
+        tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_UNUSED, 
MG_GREEN));
+        map_set_placed(ptile);
+      } else if (choose_hill) {
+        /* hills */
+        total_mtns++;
+        tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_GREEN, 
MG_UNUSED));
+        map_set_placed(ptile);
+      }
+    }
+  } whole_map_iterate_end;
+
+  /* Iteration 2
+     Make sure the map has at least the minimum number of mountains according 
to the
+     map steepness setting.
+     The iteration limit is a failsafe to prevent the iteration from taking 
forever.
+  */
+  for (iter = 0; total_mtns < (landarea * game.map.server.steepness) / 100 && 
iter < 50;
+       iter++) {
+    whole_map_iterate(ptile) {
+      if (not_placed(ptile) && hmap(ptile) > hmap_shore_level) {  /* place on 
land only */
+        choose_mountain = fc_rand(10000) < 10;
+        choose_hill = fc_rand(10000) < 10;
+        if (choose_mountain) {
+          total_mtns++;
+          tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_UNUSED, 
MG_GREEN));
+          map_set_placed(ptile);
+        } else if (choose_hill) {
+          /* hills */
+          total_mtns++;
+          tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_GREEN, 
MG_UNUSED));
+          map_set_placed(ptile);
+        }
+      }
+      if (total_mtns >= landarea * game.map.server.steepness / 100) {
+        break;
+      }
+    } whole_map_iterate_end;
+  }
+}

Added: trunk/server/generator/fracture_map.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/generator/fracture_map.h?rev=33020&view=auto
==============================================================================
--- trunk/server/generator/fracture_map.h       (added)
+++ trunk/server/generator/fracture_map.h       Sat Jun 25 09:36:10 2016
@@ -0,0 +1,34 @@
+/***********************************************************************
+ Freeciv - Copyright (C) 1996-2007 - The Freeciv Project
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+#ifndef FC__FRACTURE_MAP_H
+#define FC__FRACTURE_MAP_H
+
+/*
+ * Height map information
+ *
+ *   height_map[] stores the height of each tile
+ *   hmap_max_level is the maximum height (heights will range from
+ *     [0,hmap_max_level).
+ *   hmap_shore_level is the level of ocean.  Any tile at this height or
+ *     above is land; anything below is ocean.
+ *   hmap_mount_level is the level of mountains and hills.  Any tile above
+ *     this height will usually be a mountain or hill.
+ */
+extern int *height_map;
+extern int hmap_shore_level, hmap_mountain_level;
+
+void make_fracture_map(void);
+void make_fracture_relief(void);
+#define MG_UNUSED mapgen_terrain_property_invalid()
+
+#endif  /* FC__FRACTURE__MAP_H */

Modified: trunk/server/generator/mapgen.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/generator/mapgen.c?rev=33020&r1=33019&r2=33020&view=diff
==============================================================================
--- trunk/server/generator/mapgen.c     (original)
+++ trunk/server/generator/mapgen.c     Sat Jun 25 09:36:10 2016
@@ -35,6 +35,7 @@
 #include "road.h"
 
 /* server/generator */
+#include "fracture_map.h"
 #include "height_map.h"
 #include "mapgen_topology.h"
 #include "startpos.h"
@@ -1126,7 +1127,11 @@
 
   create_placed_map(); /* here it means land terrains to be placed */
   set_all_ocean_tiles_placed();
-  make_relief(); /* base relief on map */
+  if (MAPGEN_FRACTURE == game.map.server.generator) {
+    make_fracture_relief();
+  } else {
+    make_relief(); /* base relief on map */
+  }
   make_terrains(); /* place all exept mountains and hill */
   destroy_placed_map();
 
@@ -1334,9 +1339,15 @@
                               ? player_count() / 4 : 0)));
     }
 
+    if (MAPGEN_FRACTURE == game.map.server.generator) {
+      make_fracture_map();
+    }
+
     /* if hmap only generator make anything else */
     if (MAPGEN_RANDOM == game.map.server.generator
-        || MAPGEN_FRACTAL == game.map.server.generator) {
+        || MAPGEN_FRACTAL == game.map.server.generator
+        || MAPGEN_FRACTURE == game.map.server.generator) {
+
       make_land();
       free(height_map);
       height_map = NULL;
@@ -1385,6 +1396,7 @@
                     "start positions!");
     case MAPGEN_SCENARIO:
     case MAPGEN_RANDOM:
+    case MAPGEN_FRACTURE:
       mode = game.map.server.startpos;
       break;
     case MAPGEN_FRACTAL:

Modified: trunk/server/settings.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/settings.c?rev=33020&r1=33019&r2=33020&view=diff
==============================================================================
--- trunk/server/settings.c     (original)
+++ trunk/server/settings.c     Sat Jun 25 09:36:10 2016
@@ -253,6 +253,7 @@
   NAME_CASE(MAPGEN_FRACTAL, "FRACTAL", N_("Pseudo-fractal height"));
   NAME_CASE(MAPGEN_ISLAND, "ISLAND", N_("Island-based"));
   NAME_CASE(MAPGEN_FAIR, "FAIR", N_("Fair islands"));
+  NAME_CASE(MAPGEN_FRACTURE, "FRACTURE", N_("Fracture map"));
   }
   return NULL;
 }
@@ -1417,6 +1418,9 @@
               "each player gets their own island.\n"
               "- \"Fair islands\" (FAIR): generates the exact copy of the "
               "same island for every player or every team.\n"
+              "- \"Fracture map\" (FRACTURE): generates maps from a fracture "
+              "patttern. Tends to place hills and mountains along the edges "
+              "of the continents.\n"
               "If the requested generator is incompatible with other server "
               "settings, the server may fall back to another generator."),
            NULL, generator_validate, NULL, generator_name, 
MAP_DEFAULT_GENERATOR)


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to