Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2003:
[Freeciv-Dev] Re: (PR#3489) Patch to add new generator
Home

[Freeciv-Dev] Re: (PR#3489) Patch to add new generator

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] Re: (PR#3489) Patch to add new generator
From: "jjc@xxxxxxxxxxxxxxxxxx" <jjc@xxxxxxxxxxxxxxxxxx>
Date: Thu, 27 Mar 2003 15:32:37 -0800
Reply-to: rt@xxxxxxxxxxxxxx

I humbly submit what I hope is the last version of my patch to add a new 
generator 6. This patch fixes some problems with generating too many mountains
in the player's peninsula.  It also removes one of  the isthmus loop 
so it is a little shorter.  

It is generated in relation to cvs.  I think it is ready for committing into 
cvs.  

-- 
Josh Cogliati
jjc@xxxxxxxxxxxxxxxxxx


Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.141
diff -U9 -r1.141 map.h
--- common/map.h        2003/03/11 17:59:26     1.141
+++ common/map.h        2003/03/27 23:13:56
@@ -629,19 +629,19 @@
 #define MAP_MIN_RIVERS           0
 #define MAP_MAX_RIVERS           100
 
 #define MAP_DEFAULT_FORESTS      20
 #define MAP_MIN_FORESTS          0
 #define MAP_MAX_FORESTS          100
 
 #define MAP_DEFAULT_GENERATOR    1
 #define MAP_MIN_GENERATOR        1
-#define MAP_MAX_GENERATOR        5
+#define MAP_MAX_GENERATOR        6
 
 #define MAP_DEFAULT_TINYISLES    FALSE
 #define MAP_MIN_TINYISLES        FALSE
 #define MAP_MAX_TINYISLES        TRUE
 
 #define MAP_DEFAULT_SEPARATE_POLES   TRUE
 #define MAP_MIN_SEPARATE_POLES       FALSE
 #define MAP_MAX_SEPARATE_POLES       TRUE
 
Index: server/mapgen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/mapgen.c,v
retrieving revision 1.110
diff -U9 -r1.110 mapgen.c
--- server/mapgen.c     2003/02/20 09:45:22     1.110
+++ server/mapgen.c     2003/03/27 23:14:35
@@ -36,18 +36,19 @@
 #define rmap(x, y) (river_map[map_pos_to_index(x, y)])
 
 static void make_huts(int number);
 static void add_specials(int prob);
 static void mapgenerator1(void);
 static void mapgenerator2(void);
 static void mapgenerator3(void);
 static void mapgenerator4(void);
 static void mapgenerator5(void);
+static void mapgenerator6(void);
 static void smooth_map(void);
 static void adjust_map(int minval);
 
 #define RIVERS_MAXTRIES 32767
 enum river_map_type {RS_BLOCKED = 0, RS_RIVER = 1};
 
 /* Array needed to mark tiles as blocked to prevent a river from
    falling into itself, and for storing rivers temporarly.
    A value of 1 means blocked.
@@ -1151,18 +1152,20 @@
 
   mysrand(map.seed);
   
   /* don't generate tiles with mapgen==0 as we've loaded them from file */
   /* also, don't delete (the handcrafted!) tiny islands in a scenario */
   if (map.generator != 0) {
     map_allocate();
     /* if one mapgenerator fails, it will choose another mapgenerator */
     /* with a lower number to try again */
+    if (map.generator == 6 )
+      mapgenerator6();
     if (map.generator == 5 )
       mapgenerator5();
     if (map.generator == 4 )
       mapgenerator4();
     if (map.generator == 3 )
       mapgenerator3();
     if( map.generator == 2 )
       mapgenerator2();
     if( map.generator == 1 )
@@ -2134,9 +2137,261 @@
       minval = hmap(x, y);
   } whole_map_iterate_end;
   maxval -= minval;
   adjust_map(minval);
   
   make_land();
   free(height_map);
   height_map = NULL;
 }
+
+static int land_terrain(int x, int y)
+{
+  return !is_ocean(map_get_terrain(x,y));
+}
+
+static int border_score(int x, int y)
+{
+  int adj_score = 2;
+  int diag_score = 1;
+  int score = 0;
+  score += land_terrain(x-1,y) ? adj_score : 0;
+  score += land_terrain(x+1,y) ? adj_score : 0;
+  score += land_terrain(x,y-1) ? adj_score : 0;
+  score += land_terrain(x,y+1) ? adj_score : 0;
+  score += land_terrain(x-1,y-1) ? diag_score : 0;
+  score += land_terrain(x+1,y-1) ? diag_score : 0;
+  score += land_terrain(x-1,y+1) ? diag_score : 0;
+  score += land_terrain(x+1,y+1) ? diag_score : 0;
+  return score;
+}
+
+static int random_new_land(int x, int y)
+{
+  int score;
+  int random;
+  if(land_terrain(x, y)) {
+    return T_PLAINS;
+  }
+  score = border_score(x, y);
+  random = myrand(4*2+4*1);
+  return random + 1 > score  ? T_OCEAN : T_GRASSLAND;
+  
+}
+
+/* Creates a peninsula and put the player's starting position
+   on it */
+static void create_peninsula(int x, int y,int player_number,
+                            int width, int height,int direction,
+                            int remaining_count)
+{
+  int cx, cy;
+
+  cx = x+width/2;
+  for(cy = y; cy != y + (height + 1)*direction; 
+      cy += direction) {
+    map_set_terrain(cx, cy, T_GRASSLAND);
+    map_set_continent(cx, cy, 1);
+  }
+  remaining_count -= height; /* account for the already added strip */
+  cy = y;
+  for(cx = x + width/2 - 2; cx <= x + width/2 + 2; cx ++) {
+    map_set_terrain(cx, cy, T_GRASSLAND);
+    map_set_continent(cx, cy, 1);    
+  }
+  remaining_count -= 4; /* account for extra 4 (not 5 because that would 
+                       double count the one already done by height strip.*/
+  
+  while (remaining_count > 0) {
+    for(cx = x; cx < x+width; cx++) {
+      for(cy = y; cy != y + (height + 1)*direction; cy += direction) {
+       int new_terrain = random_new_land(cx, cy);
+       if(new_terrain == T_GRASSLAND){
+         remaining_count--;
+         map_set_terrain(cx, cy, T_GRASSLAND);
+         map_set_continent(cx, cy, 1);
+         hmap(cx, cy) = myrand(7000) - 2000;
+                 /*hmap(cx, cy) = 20 * (cx - x) * (width - (cx - x)) + 
myrand(80) - 40;*/
+       }
+       if(remaining_count <= 0) {
+         goto done_with_peninsula;
+       }
+      }
+    }
+  }
+
+ done_with_peninsula:
+
+  map.start_positions[player_number].x = x+width/2;
+  map.start_positions[player_number].y = y;
+}
+
+/* This generator creates a map with one penisula for each 
+   player and an isthmus between.  It creates a central
+   ocean and puts the peninsulas around the edges.  It is 
+   intented for quicker games. Should look something like this:
+   *****************************
+   **  *****  *****  *****    ** 
+   *    ***    ***    ***      *
+   *                           *
+   *                           *
+   *    ***    ***             *
+   **  *****  *****           **
+   *****************************
+ */
+static void mapgenerator6(void)
+{
+  int peninsulas = game.nplayers;
+  int peninsulas_on_one_side = (peninsulas + 1)/2;
+  int isthmus_width = 10;
+  int peninsula_separation = 5;
+  int peninsula_width = 
+    (map.xsize - isthmus_width - peninsula_separation)
+      /(peninsulas_on_one_side) - peninsula_separation;
+  /* if landpercent <= 50, then make shorter peninsulas */
+  int peninsula_height = (map.landpercent <= 50) 
+    ? map.ysize/3
+      : (map.ysize*2)/5;
+  int continent_percent = (map.landpercent <= 50) 
+    ? (map.landpercent * 3)/2 
+      : (map.landpercent * 5)/4;
+  int i, x, y;
+  int polar_height = 3;
+  int remaining_count = 
+    MIN(isthmus_width * (map.ysize - polar_height*2),
+       ((isthmus_width+peninsula_separation) * (map.ysize - polar_height*2) 
+        * continent_percent)/100);
+ 
+  height_map = fc_malloc(sizeof(int) * map.xsize * map.ysize);
+
+  /* initialize everything to ocean */
+  for (y = 0 ; y < map.ysize ; y++) 
+    for (x = 0 ; x < map.xsize ; x++) {
+      map_set_terrain(x, y, T_OCEAN);
+      map_set_continent(x, y, 0);
+      hmap(x, y) = 0;
+    }
+
+  /* create polar regions */
+  for (x = 0 ; x < map.xsize; x++) {
+    for (y = 0; y < polar_height; y++) {
+      int rand_num = myrand(9);
+      map_set_terrain(x, y, rand_num > 7 ? T_ARCTIC :
+                     (rand_num < 2 ? T_MOUNTAINS : T_TUNDRA));
+      map_set_continent(x, y, 1);
+      rand_num = myrand(9);
+      map_set_terrain(x, map.ysize-1-y, rand_num > 7 ? T_ARCTIC :
+                     (rand_num < 2 ? T_MOUNTAINS : T_TUNDRA));
+      map_set_continent(x, map.ysize-1-y, 1);
+    }
+  }
+  
+  /* build polar regions road */
+  for (x = 0 ; x < map.xsize; x++) {
+    y = polar_height-1;
+    if(map_build_road_time(x,y-1) < map_build_road_time(x,y)) {
+      map_set_special(x,y-1,S_ROAD);
+    } else {
+      map_set_special(x,y,S_ROAD);
+    }
+    y = map.ysize-polar_height;
+    if(map_build_road_time(x,y+1) < map_build_road_time(x,y)) {
+      map_set_special(x,y+1,S_ROAD);
+    } else {
+      map_set_special(x,y,S_ROAD);
+    }
+  }
+
+  map.num_continents = 1;
+
+  /* create isthmus centeral strip */
+  x = isthmus_width/2;
+  for (y = polar_height; y < map.ysize - polar_height; y++) {
+    map_set_terrain(x, y, T_GRASSLAND);
+    map_set_continent(x, y, 1);
+    hmap(x, y) = 100 * x * (isthmus_width - x) + (myrand(400) - 200);
+  }
+
+  remaining_count -= (map.ysize - 2*polar_height) * 1;
+
+  /* add additional isthmus area randomly */
+  while(remaining_count > 0) {
+    int low  = polar_height;
+    int high = map.ysize - polar_height - 1;
+    int direction;
+    for (direction = -1; direction < 2; direction += 2) {
+      int start = (direction == 1) ? low : high;
+      int end = (direction == 1) ? high : low;
+      for (y = start; y != end + direction; y += direction) {
+       for (x = 0; x < isthmus_width; x++) {
+         int new_terrain = random_new_land(x, y);
+         if(new_terrain == T_GRASSLAND){
+           remaining_count--;
+           map_set_terrain(x, y, T_GRASSLAND);
+           map_set_continent(x, y, 1);
+           hmap(x, y) = 100 * x * (isthmus_width - x) + (myrand(400) - 200);
+         }
+         if(remaining_count <= 0) {
+           goto done_with_isthmus;
+         }
+       }
+      }
+    }
+  }
+ done_with_isthmus:
+  
+  /* setup peninsulas */
+  for(i = 0; i < game.nplayers; i++) {
+    /* direction is the direction to increment from the x and y location */
+    int direction = (i < peninsulas_on_one_side) ? -1 : 1;
+    int index = (direction == -1) ? i : i - peninsulas_on_one_side;
+    int width = (continent_percent < 95) 
+      ? peninsula_width
+       : peninsula_width + peninsula_separation - 1;/*Give more room */
+    int height = peninsula_height-polar_height;
+    int peninsula_remaining_count = 
+      MIN(width*height,
+         ((width+peninsula_separation)*height*continent_percent)/100);
+    x = index * (peninsula_width + peninsula_separation) 
+      + isthmus_width + peninsula_separation;
+    y = (direction == -1) 
+      ? peninsula_height 
+       : map.ysize - 1 - peninsula_height;
+    create_peninsula(x,y,i,width,height,direction,peninsula_remaining_count);
+  }
+
+  map.num_start_positions = game.nplayers;
+  
+  /* setup terrain */
+  smooth_map();
+  make_mountains(1600);
+  make_swamps();
+  make_forests();
+  make_deserts();
+  make_plains();
+  make_fair();
+  make_rivers();
+
+  /* create isthmus road */
+  {
+    int last_x, middle_x = isthmus_width/2;
+    last_x = middle_x;
+    for (y = polar_height - 1; y < map.ysize - polar_height + 1; y++) {
+      int best_x = middle_x;
+      int min_build = 100;
+      for(x = MAX(last_x - 1, middle_x - 1);
+         x != MIN(last_x + 1,middle_x + 1) + 1; x++) {
+       if(land_terrain(x,y) && map_build_road_time(x,y) < min_build) {
+         best_x = x;
+         min_build = map_build_road_time(x,y);
+       }
+      }
+      map_set_special(best_x,y,S_ROAD);
+      last_x = best_x;
+    }
+  }
+  
+
+  free(height_map);
+       
+}
+  
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.273
diff -U9 -r1.273 stdinhand.c
--- server/stdinhand.c  2003/03/24 22:20:58     1.273
+++ server/stdinhand.c  2003/03/27 23:14:59
@@ -236,19 +236,21 @@
        "3 = equally sized large islands with one player each, and "
        "a number of other\n"
        "    islands of similar size;\n"
        "4 = equally sized large islands with two players on every "
        "island (or one\n"
        "    with three players for an odd number of players), and "
        "additional\n"
        "    smaller islands.\n"
        "5 = one or more large earthlike continents with some scatter.\n"
-       "Note: values 2,3 and 4 generate \"fairer\" (but more boring) "
+       "6 = equally sized peninsulas with one player each surrounding  \n"
+       "    an inland sea.\n"
+       "Note: values 2,3,4 and 6 generate \"fairer\" (but more boring) "
        "maps.\n"
        "(Zero indicates a scenario map.)"), NULL,
          MAP_MIN_GENERATOR, MAP_MAX_GENERATOR, MAP_DEFAULT_GENERATOR)
 
   GEN_BOOL("tinyisles", map.tinyisles, SSET_MAP_GEN, SSET_TO_CLIENT,
           N_("Presence or absence of 1x1 islands"),
           N_("0 = no 1x1 islands; 1 = some 1x1 islands"), NULL,
           MAP_DEFAULT_TINYISLES)
 

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