<URL: http://bugs.freeciv.org/Ticket/Display.html?id=15947 >
Better fix this if 2.1 is ever to be released I suppose... The problem was in the function below, in 2.08 there was no T_UNKNOWN check. I assume every tile is T_UNKNOWN when the map generator is generating a map causing it to make no rivers. --------common/map.c---------- bool is_water_adjacent_to_tile(const struct tile *ptile) { if (ptile->terrain != T_UNKNOWN ... ----------------------------- So I fixed fill_island_rivers(..) as best I could with my rusty programming skills. ### Fixes / Removals * if ((i * 3 > k * 2 --- don't know what that was trying to do, seems to be cut and pasted from the terrain placing code. * not_placed(ptile) --- doesn't seem to do anything, another copy from terrain placing code, there is already a check if the tile belongs to the current island's isleindex. * Didn't have a check if the tile it's evaluating already has a river. This could cause it place a river twice in one tile, reducing the amount by around 30% on average. Possibly all the way down to 1 tile worst case when it placed a mouth that had nowhere to grow, given the 0.5% chance of creating a second river. *2.08 hex topology island river generation used to create river loops. ### Improvements * River mouths can now only be surrounded by 2 ocean tiles, only 1 of which is cardinal. This gets rid of the hideous corner / peninsular 2 or 3 mouthed river outlets. Makes it look more natural too, especially when they start from an inlet or landlocked lake. Also ensures ~90% of the time there are 2 directions the river can go from the mouth, pushing the river further inland and usually making it more than 1 tile long. * Increased the amount of river tiles generated by 75% for the island generator. I figure rivers will be more important now the capital gets corruption and a 75% production bonus under despotism. High production tiles that still produce trade are best in this situation. Also in gen1 most inland tiles are mountains / hills, it's a lot harder to irrigate inland gen3 islands with random terrain placement. I really wish rivers were still a pregame option instead of having to turn the world into swamp and jungle. * Increased the rivers aversion to ocean, and reduced it's windiness and tendency to fork. This makes it go further inland and windy forking rivers ain't as useful for unit movement / irrigation. * Changed all the cardinal / percent - TRUE's & FALSE's into constants so the code is more readable. Just picked the m_ prefix out of thin air for map.h . Should I of used #DEFINES or just commented every line like the generator1 river function instead ?. * Split some checks into helper functions making the code more readable. ### Problems * Doesn't generate proper rivers for the hex2t tileset. Although that tileset doesn't create proper coastlines either and uses a different hex layout to isophex so I'll assume my code isn't at fault. --- Yautja
Index: common/map.h =================================================================== --- common/map.h (revision 12345) +++ common/map.h (working copy) @@ -80,6 +80,11 @@ TF_HEX = 8 }; +static const bool m_adjacent = FALSE; +static const bool m_cardinal = TRUE; +static const bool m_number = FALSE; +static const bool m_percent = TRUE; + #define MAP_IS_ISOMETRIC (topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX)) #define CURRENT_TOPOLOGY (map.topology_id) Index: server/generator/mapgen.c =================================================================== --- server/generator/mapgen.c (revision 12345) +++ server/generator/mapgen.c (working copy) @@ -1470,6 +1470,35 @@ } /************************************************************************** + returns true if ptile is suitable for a river mouth +**************************************************************************/ +static bool island_river_mouth_suitability( struct tile *ptile ) +{ + return(count_ocean_near_tile(ptile, m_cardinal, m_number) == 1 + && count_ocean_near_tile(ptile, m_adjacent, m_percent) <= 35 + && count_special_near_tile(ptile, + m_adjacent, m_number, S_RIVER) == 0); +} + + +/************************************************************************** + returns true if river cardinal and tile is suitable for extending it +**************************************************************************/ +static bool island_river_suitability( struct tile *ptile ) +{ + return((count_special_near_tile(ptile, m_cardinal, m_number, S_RIVER) == 1 + && count_ocean_near_tile(ptile, m_cardinal, m_number) == 0) + && count_ocean_near_tile(ptile, m_adjacent, m_percent) < 20 + && count_special_near_tile(ptile, + m_adjacent, m_percent, S_RIVER) < 35 + /* helps with straightness, ocean avoidance and reduces forking */ + && ((count_special_near_tile(ptile, + m_adjacent, m_percent, S_RIVER) + + count_ocean_near_tile(ptile, m_adjacent, m_percent) * 2) + < myrand(25) + 25)); +} + +/************************************************************************** fill an island with rivers **************************************************************************/ static void fill_island_rivers(int coast, long int *bucket, @@ -1485,30 +1514,25 @@ i = *bucket / capac; i++; *bucket -= i * capac; - + + /* generate 75% more rivers than generator 1 */ + i = (i * 175) / 100; + k = i; - failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w); + failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w) * 5; if (failsafe < 0) { failsafe = -failsafe; } - + while (i > 0 && (failsafe--) > 0) { struct tile *ptile = get_random_map_position_from_state(pstate); if (tile_get_continent(ptile) == pstate->isleindex - && not_placed(ptile)) { - - /* the first condition helps make terrain more contiguous, - the second lets it avoid the coast: */ - if ((i * 3 > k * 2 - || count_special_near_tile(ptile, FALSE, TRUE, S_RIVER) > 0 - || myrand(100) < 50) - && (!is_cardinally_adj_to_ocean(ptile) || myrand(100) < coast)) { - if (is_water_adjacent_to_tile(ptile) - && count_ocean_near_tile(ptile, FALSE, TRUE) < 50 - && count_special_near_tile(ptile, FALSE, TRUE, S_RIVER) < 35) { - tile_set_special(ptile, S_RIVER); - i--; - } + && !tile_has_special(ptile, S_RIVER)) { + if ((island_river_mouth_suitability( ptile ) + && (myrand(100) < coast || i == k )) + || island_river_suitability( ptile )) { + tile_set_special(ptile, S_RIVER); + i--; } } }
_______________________________________________ Freeciv-dev mailing list Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev