Index: src/tgp.cpp =================================================================== --- src/tgp.cpp (revision 13631) +++ src/tgp.cpp (working copy) @@ -1,4 +1,4 @@ -/* $Id: tgp.cpp 13325 2008-05-29 15:13:28Z rubidium $ */ +/* $Id: tgp.cpp 12986 2008-05-07 09:07:19Z rubidium $ */ /** @file tgp.cpp OTTD Perlin Noise Landscape Generator, aka TerraGenesis Perlin */ @@ -173,13 +173,18 @@ uint total_size; //< height map total size uint size_x; //< MapSizeX() uint size_y; //< MapSizeY() + + /* height map accessor */ + inline height_t &height(uint x, uint y) { + return h[x + y * dim_x]; + } }; /** Global height map instance */ static HeightMap _height_map = {NULL, 0, 0, 0, 0}; -/** Height map accessors */ -#define HeightMapXY(x, y) _height_map.h[(x) + (y) * _height_map.dim_x] +/* Global noise map instance */ +static HeightMap _noise_height_map={NULL, 0, 0, 0, 0}; /** Conversion: int to height_t */ #define I2H(i) ((i) << height_decimal_bits) @@ -196,7 +201,7 @@ /** Walk through all items of _height_map.h */ -#define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++) +#define FOR_ALL_TILES_IN_HEIGHT(h) for (h = height_map.h; h < &height_map.h[height_map.total_size]; h++) /** Noise amplitudes (multiplied by 1024) * - indexed by "smoothness setting" and log2(frequency) */ @@ -211,10 +216,10 @@ {1500, 1000, 1200, 1000, 500, 32, 20, 0, 0, 0, 0, 0}, }; -/** Desired water percentage (100% == 1024) - indexed by _settings_game.difficulty.quantity_sea_lakes */ +/** Desired water percentage (100% == 1024) - indexed by _opt.diff.quantity_sea_lakes */ static const amplitude_t _water_percent[4] = {20, 80, 250, 400}; -/** Desired maximum height - indexed by _settings_game.difficulty.terrain_type */ +/** Desired maximum height - indexed by _opt.diff.terrain_type */ static const int8 _max_height[4] = { 6, ///< Very flat 9, ///< Flat @@ -223,29 +228,30 @@ }; /** Check if a X/Y set are within the map. + * @param height_map height map to be the coord validated on * @param x coordinate x * @param y coordinate y * @return true if within the map */ -static inline bool IsValidXY(uint x, uint y) +static inline bool IsValidXY(HeightMap &height_map, uint x, uint y) { - return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y; + return ((int)x) >= 0 && x < height_map.size_x && ((int)y) >= 0 && y < height_map.size_y; } /** Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members */ -static inline bool AllocHeightMap() +static inline bool AllocHeightMap(HeightMap &height_map,uint width, uint height) { height_t *h; - _height_map.size_x = MapSizeX(); - _height_map.size_y = MapSizeY(); + height_map.size_x = width; + height_map.size_y = height; /* Allocate memory block for height map row pointers */ - _height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1); - _height_map.dim_x = _height_map.size_x + 1; - _height_map.h = CallocT(_height_map.total_size); - if (_height_map.h == NULL) return false; + height_map.total_size = (height_map.size_x + 1) * (height_map.size_y + 1); + height_map.dim_x = height_map.size_x + 1; + height_map.h = CallocT(height_map.total_size); + if (height_map.h == NULL) return false; /* Iterate through height map initialize values */ FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height; @@ -253,12 +259,14 @@ return true; } -/** Free height map */ +/** Free height maps */ static inline void FreeHeightMap() { if (_height_map.h == NULL) return; free(_height_map.h); + free(_noise_height_map.h); _height_map.h = NULL; + _noise_height_map.h = NULL; } /** RandomHeight() generator */ @@ -274,23 +282,23 @@ } /** One interpolation and noise round */ -static bool ApplyNoise(uint log_frequency, amplitude_t amplitude) +static bool ApplyNoise(HeightMap &height_map, uint log_frequency, amplitude_t amplitude) { - uint size_min = min(_height_map.size_x, _height_map.size_y); + uint size_min = min(height_map.size_x, height_map.size_y); uint step = size_min >> log_frequency; - uint x, y; - assert(_height_map.h != NULL); + /* Trying to apply noise to uninitialized height map */ + assert(height_map.h != NULL); /* Are we finished? */ if (step == 0) return false; if (log_frequency == 0) { /* This is first round, we need to establish base heights with step = size_min */ - for (y = 0; y <= _height_map.size_y; y += step) { - for (x = 0; x <= _height_map.size_x; x += step) { + for (uint y = 0; y <= height_map.size_y; y += step) { + for (uint x = 0; x <= height_map.size_x; x += step) { height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0; - HeightMapXY(x, y) = height; + height_map.height(x, y) = height; } } return true; @@ -298,37 +306,40 @@ /* It is regular iteration round. * Interpolate height values at odd x, even y tiles */ - for (y = 0; y <= _height_map.size_y; y += 2 * step) { - for (x = 0; x < _height_map.size_x; x += 2 * step) { - height_t h00 = HeightMapXY(x + 0 * step, y); - height_t h02 = HeightMapXY(x + 2 * step, y); + for (uint y = 0; y <= height_map.size_y; y += 2 * step) { + for (uint x = 0; x < height_map.size_x; x += 2 * step) { + height_t h00 = height_map.height(x + 0 * step, y); + height_t h02 = height_map.height(x + 2 * step, y); height_t h01 = (h00 + h02) / 2; - HeightMapXY(x + 1 * step, y) = h01; + height_map.height(x + 1 * step, y) = h01; } } /* Interpolate height values at odd y tiles */ - for (y = 0; y < _height_map.size_y; y += 2 * step) { - for (x = 0; x <= _height_map.size_x; x += step) { - height_t h00 = HeightMapXY(x, y + 0 * step); - height_t h20 = HeightMapXY(x, y + 2 * step); + for (uint y = 0; y < height_map.size_y; y += 2 * step) { + for (uint x = 0; x <= height_map.size_x; x += step) { + height_t h00 = height_map.height(x, y + 0 * step); + height_t h20 = height_map.height(x, y + 2 * step); height_t h10 = (h00 + h20) / 2; - HeightMapXY(x, y + 1 * step) = h10; + height_map.height(x, y + 1 * step) = h10; } } - for (y = 0; y <= _height_map.size_y; y += step) { - for (x = 0; x <= _height_map.size_x; x += step) { - HeightMapXY(x, y) += RandomHeight(amplitude); + /* Add some more smaller noise */ + for (uint y = 0; y <= height_map.size_y; y += step) { + for (uint x = 0; x <= height_map.size_x; x += step) { + height_map.height(x, y) += RandomHeight(amplitude); } } + + /* Return false if we are finished (reached the minimal step size) */ return (step > 1); } /** Base Perlin noise generator - fills height map with raw Perlin noise */ -static void HeightMapGenerate() +static void HeightMapGenerate(HeightMap &height_map, byte smoothness) { - uint size_min = min(_height_map.size_x, _height_map.size_y); + uint size_min = min(height_map.size_x, height_map.size_y); uint iteration_round = 0; amplitude_t amplitude; bool continue_iteration; @@ -339,26 +350,27 @@ for (log_size_min = 6; (1U << log_size_min) < size_min; log_size_min++) { } log_frequency_min = log_size_min - 6; + /* Keep increasing the frequence unitil wer reach the step size equal to one tile */ do { log_frequency = iteration_round - log_frequency_min; if (log_frequency >= 0) { - amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency]; + amplitude = _amplitudes_by_smoothness_and_frequency[smoothness][log_frequency]; } else { amplitude = 0; } - continue_iteration = ApplyNoise(iteration_round, amplitude); + continue_iteration = ApplyNoise(height_map, iteration_round, amplitude); iteration_round++; } while(continue_iteration); } /** Returns min, max and average height from height map */ -static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr) +static void HeightMapGetMinMaxAvg(HeightMap &height_map, height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr) { height_t h_min, h_max, h_avg, *h; int64 h_accu = 0; - h_min = h_max = HeightMapXY(0, 0); + h_min = h_max = height_map.height(0, 0); - /* Get h_min, h_max and accumulate heights into h_accu */ + /* Calculate the sum of all heights in the height map */ FOR_ALL_TILES_IN_HEIGHT(h) { if (*h < h_min) h_min = *h; if (*h > h_max) h_max = *h; @@ -366,7 +378,7 @@ } /* Get average height */ - h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y)); + h_avg = (height_t)(h_accu / (height_map.size_x * height_map.size_y)); /* Return required results */ if (min_ptr != NULL) *min_ptr = h_min; @@ -375,7 +387,7 @@ } /** Dill histogram and return pointer to its base point - to the count of zero heights */ -static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf) +static int *HeightMapMakeHistogram(HeightMap &height_map, height_t h_min, height_t h_max, int *hist_buf) { int *hist = hist_buf - h_min; height_t *h; @@ -390,7 +402,7 @@ } /** Applies sine wave redistribution onto height map */ -static void HeightMapSineTransform(height_t h_min, height_t h_max) +static void HeightMapSineTransform(HeightMap &height_map, height_t h_min, height_t h_max) { height_t *h; @@ -467,22 +479,22 @@ } /** Adjusts heights in height map to contain required amount of water tiles */ -static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new) +static void HeightMapAdjustWaterLevel(HeightMap &height_map,amplitude_t water_percent, height_t h_max_new) { height_t h_min, h_max, h_avg, h_water_level; int water_tiles, desired_water_tiles; height_t *h; int *hist; - HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg); + HeightMapGetMinMaxAvg(height_map, &h_min, &h_max, &h_avg); /* Allocate histogram buffer and clear its cells */ int *hist_buf = CallocT(h_max - h_min + 1); /* Fill histogram */ - hist = HeightMapMakeHistogram(h_min, h_max, hist_buf); + hist = HeightMapMakeHistogram(height_map, h_min, h_max, hist_buf); /* How many water tiles do we want? */ - desired_water_tiles = (int)(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)) >> amplitude_decimal_bits; + desired_water_tiles = (int)(((int64)water_percent) * (int64)(height_map.size_x * height_map.size_y)) >> amplitude_decimal_bits; /* Raise water_level and accumulate values from histogram until we reach required number of water tiles */ for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) { @@ -507,275 +519,103 @@ free(hist_buf); } -static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime); - /** - * This routine sculpts in from the edge a random amount, again a Perlin - * sequence, to avoid the rigid flat-edge slopes that were present before. The - * Perlin noise map doesnt know where we are going to slice across, and so we - * often cut straight through high terrain. the smoothing routine makes it - * legal, gradually increasing up from the edge to the original terrain height. - * By cutting parts of this away, it gives a far more irregular edge to the - * map-edge. Sometimes it works beautifully with the existing sea & lakes, and - * creates a very realistic coastline. Other times the variation is less, and - * the map-edge shows its cliff-like roots. - * - * This routine may be extended to randomly sculpt the height of the terrain - * near the edge. This will have the coast edge at low level (1-3), rising in - * smoothed steps inland to about 15 tiles in. This should make it look as - * though the map has been built for the map size, rather than a slice through - * a larger map. - * - * Please note that all the small numbers; 53, 101, 167, etc. are small primes - * to help give the perlin noise a bit more of a random feel. - */ -static void HeightMapCoastLines() -{ - int smallest_size = min(_settings_game.game_creation.map_x, _settings_game.game_creation.map_y); - const int margin = 4; - uint y, x; - double max_x; - double max_y; - - /* Lower to sea level */ - for (y = 0; y <= _height_map.size_y; y++) { - /* Top right */ - max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.9, 53) + 0.25) * 5 + (perlin_coast_noise_2D(y, y, 0.35, 179) + 1) * 12); - max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x); - if (smallest_size < 8 && max_x > 5) max_x /= 1.5; - for (x = 0; x < max_x; x++) { - HeightMapXY(x, y) = 0; - } - - /* Bottom left */ - max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.85, 101) + 0.3) * 6 + (perlin_coast_noise_2D(y, y, 0.45, 67) + 0.75) * 8); - max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x); - if (smallest_size < 8 && max_x > 5) max_x /= 1.5; - for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) { - HeightMapXY(x, y) = 0; - } - } - - /* Lower to sea level */ - for (x = 0; x <= _height_map.size_x; x++) { - /* Top left */ - max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 2, 0.9, 167) + 0.4) * 5 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.4, 211) + 0.7) * 9); - max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y); - if (smallest_size < 8 && max_y > 5) max_y /= 1.5; - for (y = 0; y < max_y; y++) { - HeightMapXY(x, y) = 0; - } - - - /* Bottom right */ - max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.85, 71) + 0.25) * 6 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.35, 193) + 0.75) * 12); - max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y); - if (smallest_size < 8 && max_y > 5) max_y /= 1.5; - for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) { - HeightMapXY(x, y) = 0; - } - } -} - -/** Start at given point, move in given direction, find and Smooth coast in that direction */ -static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y) -{ - const int max_coast_dist_from_edge = 35; - const int max_coast_Smooth_depth = 35; - - int x, y; - int ed; // coast distance from edge - int depth; - - height_t h_prev = 16; - height_t h; - - assert(IsValidXY(org_x, org_y)); - - /* Search for the coast (first non-water tile) */ - for (x = org_x, y = org_y, ed = 0; IsValidXY(x, y) && ed < max_coast_dist_from_edge; x += dir_x, y += dir_y, ed++) { - /* Coast found? */ - if (HeightMapXY(x, y) > 15) break; - - /* Coast found in the neighborhood? */ - if (IsValidXY(x + dir_y, y + dir_x) && HeightMapXY(x + dir_y, y + dir_x) > 0) break; - - /* Coast found in the neighborhood on the other side */ - if (IsValidXY(x - dir_y, y - dir_x) && HeightMapXY(x - dir_y, y - dir_x) > 0) break; - } - - /* Coast found or max_coast_dist_from_edge has been reached. - * Soften the coast slope */ - for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) { - h = HeightMapXY(x, y); - h = min(h, h_prev + (4 + depth)); // coast softening formula - HeightMapXY(x, y) = h; - h_prev = h; - } -} - -/** Smooth coasts by modulating height of tiles close to map edges with cosine of distance from edge */ -static void HeightMapSmoothCoasts() -{ - uint x, y; - /* First Smooth NW and SE coasts (y close to 0 and y close to size_y) */ - for (x = 0; x < _height_map.size_x; x++) { - HeightMapSmoothCoastInDirection(x, 0, 0, 1); - HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1); - } - /* First Smooth NE and SW coasts (x close to 0 and x close to size_x) */ - for (y = 0; y < _height_map.size_y; y++) { - HeightMapSmoothCoastInDirection(0, y, 1, 0); - HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0); - } -} - -/** * This routine provides the essential cleanup necessary before OTTD can * display the terrain. When generated, the terrain heights can jump more than * one level between tiles. This routine smooths out those differences so that * the most it can change is one level. When OTTD can support cliffs, this * routine may not be necessary. */ -static void HeightMapSmoothSlopes(height_t dh_max) +static void HeightMapSmoothSlopes(HeightMap &height_map, height_t dh_max) { - int x, y; - for (y = 1; y <= (int)_height_map.size_y; y++) { - for (x = 1; x <= (int)_height_map.size_x; x++) { - height_t h_max = min(HeightMapXY(x - 1, y), HeightMapXY(x, y - 1)) + dh_max; - if (HeightMapXY(x, y) > h_max) HeightMapXY(x, y) = h_max; + for (int y = 1; y <= (int)height_map.size_y; y++) { + for (uint x = 1; x <= (int)height_map.size_x; x++) { + height_t h_max = min(height_map.height(x - 1, y), height_map.height(x, y - 1)) + dh_max; + if (height_map.height(x, y) > h_max) height_map.height(x, y) = h_max; } } - for (y = _height_map.size_y - 1; y >= 0; y--) { - for (x = _height_map.size_x - 1; x >= 0; x--) { - height_t h_max = min(HeightMapXY(x + 1, y), HeightMapXY(x, y + 1)) + dh_max; - if (HeightMapXY(x, y) > h_max) HeightMapXY(x, y) = h_max; + for (int y = height_map.size_y - 1; y >= 0; y--) { + for (int x = height_map.size_x - 1; x >= 0; x--) { + height_t h_max = min(height_map.height(x + 1, y), height_map.height(x, y + 1)) + dh_max; + if (height_map.height(x, y) > h_max) height_map.height(x, y) = h_max; } } } +/** In map border areas substracts the given noise map from the existing terrain. */ +static void HeightMapApplyBorders(HeightMap &height_map, HeightMap &noise_map, byte smoothness){ + /* Calculate width of the outmost map zone. This will mostly be covered with water with only ocassional + * peninsulas and islands. Clamp this value between 11 (to prevent artifacts on very small maps) and 80 + * (to prevent the zone of water from being too wide) + */ + uint coast_free_length = max(18, min(min(height_map.size_x, height_map.size_y) / 10, 80)); + + /* Calculates the length of coastline slopes. The smoother the map, the gentlier the slopes will be. */ + uint slope_length = 32 + 12 * (3 - smoothness); + + /* Walk through all tiles and apply the noise map */ + for (uint y = 1; y <= height_map.size_y; y++) { + for (uint x = 1; x <= height_map.size_x; x++) { + /* Calculate the distance from edge. This is very simple, since we are in a square tile based matrix */ + uint distance_from_edge=min(min(x, y), min(height_map.size_x - 1 - x, height_map.size_y - 1 - y)); + + /* The first zone - the coastline itself is mostly defined now. We don't have to start from -256 since + * there are no that high hills to neutralize in the noise heightmap. + */ + if(distance_from_edge < coast_free_length){ + height_map.height(x, y) = min(height_map.height(x, y), - 144 * (1 - (double)distance_from_edge / (double)coast_free_length) + noise_map.height(x, y)); + } + /* the second zone - here are smoothed hills on the ground to fit the coastline*/ + else if(distance_from_edge < coast_free_length+slope_length){ + height_map.height(x, y) = min(height_map.height(x, y), 256 * ((double)(distance_from_edge - coast_free_length) / (double)slope_length) + noise_map.height(x, y)); + } + } + } + + /* Remove any potential double slopes */ + HeightMapSmoothSlopes(height_map, 16); +} + /** Height map terraform post processing: * - water level adjusting - * - coast Smoothing * - slope Smoothing * - height histogram redistribution by sine wave transform */ -static void HeightMapNormalize() -{ - const amplitude_t water_percent = _water_percent[_settings_game.difficulty.quantity_sea_lakes]; - const height_t h_max_new = I2H(_max_height[_settings_game.difficulty.terrain_type]); - const height_t roughness = 7 + 3 * _settings_game.game_creation.tgen_smoothness; - HeightMapAdjustWaterLevel(water_percent, h_max_new); - - HeightMapCoastLines(); - HeightMapSmoothSlopes(roughness); - - HeightMapSmoothCoasts(); - HeightMapSmoothSlopes(roughness); - - HeightMapSineTransform(12, h_max_new); - HeightMapSmoothSlopes(16); -} - -static inline int perlin_landXY(uint x, uint y) +static void HeightMapNormalize(HeightMap &height_map, byte sea_quantity, byte terrain_type, byte smoothness) { - return HeightMapXY(x, y); -} + const amplitude_t water_percent = _water_percent[sea_quantity]; + const height_t h_max_new = I2H(_max_height[terrain_type]); + const height_t roughness = 7 + 3 * smoothness; + HeightMapAdjustWaterLevel(height_map, water_percent, h_max_new); -/** - * The Perlin Noise calculation using large primes - * The initial number is adjusted by two values; the generation_seed, and the - * passed parameter; prime. - * prime is used to allow the perlin noise generator to create useful random - * numbers from slightly different series. - */ -static double int_noise(const long x, const long y, const int prime) -{ - long n = x + y * prime + _settings_game.game_creation.generation_seed; + HeightMapSmoothSlopes(height_map, roughness); - n = (n << 13) ^ n; + HeightMapSineTransform(height_map, 12, h_max_new); - /* Pseudo-random number generator, using several large primes */ - return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0; + HeightMapSmoothSlopes(height_map, 16); } +/** Creates the alternative noise map */ +static void CreateNoiseMap(HeightMap &height_map,HeightMap &noise_map, byte smoothness){ + /* Allocate and initialize noise height map */ + AllocHeightMap(noise_map,height_map.size_x,height_map.size_y); -/** - * Hj. Malthaner's routine included 2 different noise smoothing methods. - * We now use the "raw" int_noise one. - * However, it may be useful to move to the other routine in future. - * So it is included too. - */ -static double smoothed_noise(const int x, const int y, const int prime) -{ -#if 0 - /* A hilly world (four corner smooth) */ - const double sides = int_noise(x - 1, y) + int_noise(x + 1, y) + int_noise(x, y - 1) + int_noise(x, y + 1); - const double center = int_noise(x, y); - return (sides + sides + center * 4) / 8.0; -#endif + /* Make small height noise map siginificantly rougher to prevent long straight + * shores, which could be part of longer curves on larger maps, but look very + * bad on small maps + */ + if(min(height_map.size_x,height_map.size_y)<=128) smoothness=3; + else if(min(height_map.size_x,height_map.size_y)<=256) smoothness=2; - /* This gives very hilly world */ - return int_noise(x, y, prime); + /* Create the noise map landscape. Use mountainous map with very low water level. + * Smoothnes should be rough or very rough. Smooth or very smooth usually create too + * artificial shores + */ + HeightMapGenerate(noise_map,smoothness); + HeightMapNormalize(noise_map, 0, 1,2); } - -/** - * This routine determines the interpolated value between a and b - */ -static inline double linear_interpolate(const double a, const double b, const double x) -{ - return a + x * (b - a); -} - - -/** - * This routine returns the smoothed interpolated noise for an x and y, using - * the values from the surrounding positions. - */ -static double interpolated_noise(const double x, const double y, const int prime) -{ - const int integer_X = (int)x; - const int integer_Y = (int)y; - - const double fractional_X = x - (double)integer_X; - const double fractional_Y = y - (double)integer_Y; - - const double v1 = smoothed_noise(integer_X, integer_Y, prime); - const double v2 = smoothed_noise(integer_X + 1, integer_Y, prime); - const double v3 = smoothed_noise(integer_X, integer_Y + 1, prime); - const double v4 = smoothed_noise(integer_X + 1, integer_Y + 1, prime); - - const double i1 = linear_interpolate(v1, v2, fractional_X); - const double i2 = linear_interpolate(v3, v4, fractional_X); - - return linear_interpolate(i1, i2, fractional_Y); -} - - -/** - * This is a similar function to the main perlin noise calculation, but uses - * the value p passed as a parameter rather than selected from the predefined - * sequences. as you can guess by its title, i use this to create the indented - * coastline, which is just another perlin sequence. - */ -static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime) -{ - double total = 0.0; - int i; - - for (i = 0; i < 6; i++) { - const double frequency = (double)(1 << i); - const double amplitude = pow(p, (double)i); - - total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude; - } - - return total; -} - - /** A small helper function */ static void TgenSetTileHeight(TileIndex tile, int height) { @@ -794,21 +634,35 @@ { uint x, y; - if (!AllocHeightMap()) return; + if (!AllocHeightMap(_height_map,MapSizeX(),MapSizeY())) return; GenerateWorldSetAbortCallback(FreeHeightMap); - HeightMapGenerate(); + /* Generate the main terrain. Apply user defined smoothness */ + HeightMapGenerate(_height_map, _settings_game.game_creation.tgen_smoothness); IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); + + /* Generate the additional noise which would be used to make shores look more naturally. + * Override Very Smooth smoothness setting, it creates way too smooth coastlines + */ + CreateNoiseMap(_height_map, _noise_height_map,max((byte)1, _settings_game.game_creation.tgen_smoothness)); - HeightMapNormalize(); + IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); + /* Adjust water level, apply sine transformation. Map borders are no longer created in this function */ + HeightMapNormalize(_height_map, _settings_game.difficulty.quantity_sea_lakes, _settings_game.difficulty.terrain_type, _settings_game.game_creation.tgen_smoothness); + IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); + + /* Create the outer coastlines */ + HeightMapApplyBorders(_height_map, _noise_height_map, _settings_game.game_creation.tgen_smoothness); + IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); + /* Transfer height map into OTTD map */ for (y = 2; y < _height_map.size_y - 2; y++) { for (x = 2; x < _height_map.size_x - 2; x++) { - int height = H2I(HeightMapXY(x, y)); + int height = H2I(_height_map.h[(x) + (y) * _height_map.dim_x]); if (height < 0) height = 0; if (height > 15) height = 15; TgenSetTileHeight(TileXY(x, y), height); Index: src/unmovable_cmd.cpp =================================================================== --- src/unmovable_cmd.cpp (revision 13631) +++ src/unmovable_cmd.cpp (working copy) @@ -419,7 +419,8 @@ case DIAGDIR_NW: tile = TileXY(r % maxx, maxy); break; } - for (int j = 0; j < 20; j++) { + /* Walk through up to 60 tiles from the border to find a suitable land tile to put a lighthouse on */ + for (int j = 0; j < 60; j++) { uint h; if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == SLOPE_FLAT && h <= TILE_HEIGHT * 2 && !IsBridgeAbove(tile)) { MakeLighthouse(tile);