From: Josh Cogliati Have you ever wished that you could get into the action sooner in a freeciv game? Ever get tired of spending fifteen minutes playing freeciv solitary before you meet the other players? Well, this patch (http://rt.freeciv.org/Ticket/Display.html?id=3489) is the patch for you. It adds a new generator 6 that creates a world that looks about like this (# = roads, + = player starting positions, * = land): ************************ ######################## **#** ***** ****** *#* *+** *+** *#* **#** *+* *+** **#* ***** ***** ######################## ************************ Basically it generates a central sea surrounded by peninsula's for each of the players, a isthmus to connect the north and south poles, and handy prebuilt roads to speed your troops and settlers around the globe For your patching pleasure (generated against cvs from just minutes ago) here it is: (slightly modified by Sam Trenholme to cleanly patch against a stock 1.14.0 FreeCiv release) - Sam diff -ur freeciv-1.14.0/common/map.h freeciv-1.14.0-mapgen6/common/map.h --- freeciv-1.14.0/common/map.h Fri Oct 11 16:35:13 2002 +++ freeciv-1.14.0-mapgen6/common/map.h Wed Mar 19 22:16:40 2003 @@ -619,7 +619,7 @@ #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 diff -ur freeciv-1.14.0/server/mapgen.c freeciv-1.14.0-mapgen6/server/mapgen.c --- freeciv-1.14.0/server/mapgen.c Fri Oct 11 16:35:50 2002 +++ freeciv-1.14.0-mapgen6/server/mapgen.c Wed Mar 19 22:25:47 2003 @@ -41,6 +41,7 @@ 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); @@ -1196,6 +1197,8 @@ 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 ) @@ -2212,3 +2215,267 @@ free(height_map); height_map = NULL; } + +static int is_ocean(int l) +{ + return (l == T_OCEAN); +} + +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) = 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) { + for (y = polar_height; y < map.ysize/2; y++) { + 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; + } + } + } + + for (y = map.ysize - polar_height - 1; y >= map.ysize/2; y--) { + 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 */ + 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); + +} diff -ur freeciv-1.14.0/server/stdinhand.c freeciv-1.14.0-mapgen6/server/stdinhand.c --- freeciv-1.14.0/server/stdinhand.c Fri Nov 15 19:14:22 2002 +++ freeciv-1.14.0-mapgen6/server/stdinhand.c Wed Mar 19 22:16:40 2003 @@ -239,7 +239,9 @@ "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)