00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include <math.h>
00014 #include "clear_map.h"
00015 #include "void_map.h"
00016 #include "genworld.h"
00017 #include "core/alloc_func.hpp"
00018 #include "core/random_func.hpp"
00019 #include "landscape_type.h"
00020 #include "tgp.h"
00021 #include "debug.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00157 typedef int16 height_t;
00158 static const int height_decimal_bits = 4;
00159 static const height_t _invalid_height = -32768;
00160
00162 typedef int amplitude_t;
00163 static const int amplitude_decimal_bits = 10;
00164
00166 struct HeightMap
00167 {
00168 height_t *h;
00169 uint dim_x;
00170 uint total_size;
00171 uint size_x;
00172 uint size_y;
00173
00180 inline height_t &height(uint x, uint y)
00181 {
00182 return h[x + y * dim_x];
00183 }
00184 };
00185
00187 static HeightMap _height_map = {NULL, 0, 0, 0, 0};
00188
00190 #define I2H(i) ((i) << height_decimal_bits)
00191
00192 #define H2I(i) ((i) >> height_decimal_bits)
00193
00195 #define I2A(i) ((i) << amplitude_decimal_bits)
00196
00197 #define A2I(i) ((i) >> amplitude_decimal_bits)
00198
00200 #define A2H(a) ((a) >> (amplitude_decimal_bits - height_decimal_bits))
00201
00202
00204 #define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++)
00205
00213 static const amplitude_t _amplitudes_by_smoothness_and_frequency[7][TGP_FREQUENCY_MAX + 1] = {
00214
00215
00216 { 2143, 27832, 51429, 51657, 41657, 51429, 1597, 233, 37, 16},
00217
00218 { 6448, 911, 27832, 31131, 16511, 1427, 1597, 233, 29, 8},
00219
00220 {17657, 29832, 36832, 51429, 16511, 51429, 233, 1597, 1301, 16},
00221
00222 {17657, 6448, 36832, 51429, 16511, 17657, 233, 1597, 1301, 16},
00223
00224 { 17657, 31832, 39832, 29832, 16511, 43429, 233, 2597, 37, 16},
00225
00226 {25000, 10000, 8000, 24000, 12000, 2500, 250, 100, 80, 25},
00227
00228 {13511, 22739, 51429, 253, 421, 21131, 137, 7, 37, 261}
00229 };
00230
00238 static const int _smoothing_parameters[7][3] = {
00239 {3, 3, 8},
00240 {4, 3, 8},
00241 {2, 7, 8},
00242 {2, 4, 8},
00243 {2, 5, 8},
00244 {2, 6, 8},
00245 {2, 5, 4}
00246 };
00247
00249 static const amplitude_t _water_percent[4] = {70, 170, 270, 420};
00250
00269 static const int _max_height[7][9] = {
00270 {32, 48, 72, 170, 340, 680, 1360, 2720, 5440},
00271 {21, 40, 50, 64, 128, 380, 760, 1520, 3040},
00272 {16, 27, 38, 51, 102, 204, 408, 916, 1832},
00273 {12, 21, 30, 39, 60, 120, 240, 480, 960},
00274 {10, 13, 17, 20, 33, 66, 132, 264, 528},
00275 {9, 10, 11, 12, 13, 24, 48, 96, 192},
00276 {5, 6, 7, 7, 7, 12, 24, 48, 96}
00277 };
00278
00285 static inline bool IsValidXY(uint x, uint y)
00286 {
00287 return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
00288 }
00289
00294 static inline bool AllocHeightMap()
00295 {
00296 height_t *h;
00297
00298 _height_map.size_x = MapSizeX();
00299 _height_map.size_y = MapSizeY();
00300
00301
00302 _height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1);
00303 _height_map.dim_x = _height_map.size_x + 1;
00304 _height_map.h = CallocT<height_t>(_height_map.total_size);
00305
00306
00307 FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height;
00308
00309 return true;
00310 }
00311
00313 static inline void FreeHeightMap()
00314 {
00315 if (_height_map.h == NULL) return;
00316 free(_height_map.h);
00317 _height_map.h = NULL;
00318 }
00319
00325 static inline height_t RandomHeight(amplitude_t rMax)
00326 {
00327 amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
00328 height_t rh;
00329
00330 rh = A2H(ra % (2 * rMax + 1) - rMax);
00331 return rh;
00332 }
00333
00352 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
00353 {
00354 uint size_min = min(_height_map.size_x, _height_map.size_y);
00355 int step = size_min >> log_frequency;
00356 int x, y;
00357
00358 height_t* temp_height_map;
00359 temp_height_map = CallocT<height_t>(_height_map.total_size);
00360
00361
00362 assert(_height_map.h != NULL);
00363
00364
00365 if (step == 0) return false;
00366
00367 if (log_frequency == 0) {
00368
00369 for (y = 0; y <= (int)_height_map.size_y; y += step) {
00370 for (x = 0; x <= (int)_height_map.size_x; x += step) {
00371 height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
00372 _height_map.height(x, y) = height;
00373 }
00374 }
00375 return true;
00376 }
00377
00378
00379
00380 for (y = 0; y <= (int)_height_map.size_y; y += 2 * step) {
00381 for (x = 0; x < (int)_height_map.size_x; x += 2 * step) {
00382 height_t h00 = _height_map.height(x + 0 * step, y);
00383 height_t h02 = _height_map.height(x + 2 * step, y);
00384 height_t h01 = (h00 + h02) / 2;
00385 _height_map.height(x + 1 * step, y) = h01;
00386 }
00387 }
00388
00389
00390 for (y = 0; y < (int)_height_map.size_y; y += 2 * step) {
00391 for (x = 0; x <= (int)_height_map.size_x; x += step) {
00392 height_t h00 = _height_map.height(x, y + 0 * step);
00393 height_t h20 = _height_map.height(x, y + 2 * step);
00394 height_t h10 = (h00 + h20) / 2;
00395 _height_map.height(x, y + 1 * step) = h10;
00396 }
00397 }
00398
00399
00400 for (y = 0; y <= (int)_height_map.size_y; y += step) {
00401 for (x = 0; x <= (int)_height_map.size_x; x += step) {
00402 _height_map.height(x, y) += RandomHeight(amplitude);
00403 }
00404 }
00405
00406 return (step > 1);
00407 }
00408
00418 void Smooth(uint log_frequency, int radius, int weakness, int min_step)
00419 {
00420 uint size_min = min(_height_map.size_x, _height_map.size_y);
00421 int step = size_min >> log_frequency;
00422
00423 if(step < min_step) {
00424 return;
00425 } else {
00426 if(step < min_step * 2) {
00427 weakness += 4;
00428 }
00429 }
00430
00431 height_t* temp_height_map;
00432 temp_height_map = CallocT<height_t>(_height_map.total_size);
00433
00434 for (uint y = 0; y <= _height_map.size_y; y += step) {
00435 for (uint x = 0; x <= _height_map.size_x; x += step) {
00436 temp_height_map[x + y * _height_map.size_x] = _height_map.height(x, y);
00437 }
00438 }
00439
00440 for (uint y = 0; y <= _height_map.size_y; y += step) {
00441 for (uint x = 0; x <= _height_map.size_x; x += step) {
00442 height_t current = temp_height_map[x + y * _height_map.size_x];
00443 int sum = current * 100 * weakness;
00444 int weights = 100 * weakness;
00445
00446 for(int i = -radius; i <= radius; i++){
00447 for(int j = -radius; j <= radius; j++){
00448 if((i != 0 || j != 0) && x + i * step <= _height_map.size_x
00449 && x + i * step > 0 && y + j * step <= _height_map.size_y
00450 && y + j * step > 0) {
00451 int square = (int) sqrt((double)(i * i + j * j));
00452 sum += temp_height_map[x + i * step + (y + j * step) * _height_map.size_x] * 100 / square;
00453 weights += 100 / square;
00454 }
00455 }
00456 }
00457
00458 _height_map.height(x, y) = sum / weights;
00459 }
00460 }
00461 }
00462
00464 static void HeightMapGenerate()
00465 {
00466 uint size_min = min(_height_map.size_x, _height_map.size_y);
00467 uint iteration_round = 0;
00468 amplitude_t amplitude;
00469 bool continue_iteration;
00470 int log_size_min, log_frequency_min;
00471 int log_frequency;
00472
00473
00474 for (log_size_min = TGP_FREQUENCY_MAX; (1U << log_size_min) < size_min; log_size_min++) { }
00475 log_frequency_min = log_size_min - TGP_FREQUENCY_MAX;
00476
00477
00478 assert(log_frequency_min >= 0);
00479
00480
00481 do {
00482 log_frequency = iteration_round - log_frequency_min;
00483
00484 if (log_frequency >= 0) {
00485
00486 assert(log_frequency <= TGP_FREQUENCY_MAX);
00487 amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency];
00488 } else {
00489
00490 amplitude = 0;
00491 }
00492
00493 continue_iteration = ApplyNoise(iteration_round, amplitude);
00494
00495 if(amplitude > 0) {
00496
00497 Smooth(iteration_round, _smoothing_parameters[_settings_game.game_creation.tgen_smoothness][0],
00498 _smoothing_parameters[_settings_game.game_creation.tgen_smoothness][1],
00499 _smoothing_parameters[_settings_game.game_creation.tgen_smoothness][2]);
00500 }
00501
00502 iteration_round++;
00503
00504 } while (continue_iteration);
00505
00506 assert(log_frequency <= TGP_FREQUENCY_MAX);
00507
00508 if (log_frequency != TGP_FREQUENCY_MAX) {
00509 DEBUG(map, 0, "Frequency wrong: log_frequency = %i, TGP_FREQUENCY_MAX = %i",
00510 log_frequency, TGP_FREQUENCY_MAX);
00511 }
00512 }
00513
00515 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
00516 {
00517 height_t h_min, h_max, h_avg, *h;
00518 int64 h_accu = 0;
00519 h_min = h_max = _height_map.height(0, 0);
00520
00521
00522 FOR_ALL_TILES_IN_HEIGHT(h) {
00523 if (*h < h_min) h_min = *h;
00524 if (*h > h_max) h_max = *h;
00525 h_accu += *h;
00526 }
00527
00528
00529 h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y));
00530
00531
00532 if (min_ptr != NULL) *min_ptr = h_min;
00533 if (max_ptr != NULL) *max_ptr = h_max;
00534 if (avg_ptr != NULL) *avg_ptr = h_avg;
00535 }
00536
00538 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
00539 {
00540 int *hist = hist_buf - h_min;
00541 height_t *h;
00542
00543
00544 FOR_ALL_TILES_IN_HEIGHT(h) {
00545 assert(*h >= h_min);
00546 assert(*h <= h_max);
00547 hist[*h]++;
00548 }
00549 return hist;
00550 }
00551
00553 static void HeightMapSineTransform(height_t h_min, height_t h_max)
00554 {
00555 if ((_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_VERY_ROUGH)
00556 || (_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_CEREALLY_ROUGH)) {
00557
00558 return;
00559 }
00560
00561 height_t *h;
00562
00563 FOR_ALL_TILES_IN_HEIGHT(h) {
00564 double fheight;
00565
00566 if (*h < h_min) continue;
00567
00568
00569 fheight = (double)(*h - h_min) / (double)(h_max - h_min);
00570
00571 switch (_settings_game.game_creation.landscape) {
00572 case LT_TOYLAND:
00573 case LT_TEMPERATE:
00574 {
00575
00576 fheight = 2 * fheight - 1;
00577
00578 fheight = sin(fheight * M_PI_2);
00579
00580 fheight = 0.5 * (fheight + 1);
00581 }
00582 break;
00583
00584 case LT_ARCTIC:
00585 {
00586
00587
00588 double sine_upper_limit = 0.75;
00589 double linear_compression = 2;
00590 if (fheight >= sine_upper_limit) {
00591
00592 fheight = 1.0 - (1.0 - fheight) / linear_compression;
00593 } else {
00594 double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
00595
00596 fheight = 2.0 * fheight / sine_upper_limit - 1.0;
00597
00598 fheight = sin(fheight * M_PI_2);
00599
00600 fheight = 0.5 * (fheight + 1.0) * m;
00601 }
00602 }
00603 break;
00604
00605 case LT_TROPIC:
00606 {
00607
00608
00609 double sine_lower_limit = 0.5;
00610 double linear_compression = 2;
00611 if (fheight <= sine_lower_limit) {
00612
00613 fheight = fheight / linear_compression;
00614 } else {
00615 double m = sine_lower_limit / linear_compression;
00616
00617 fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
00618
00619 fheight = sin(fheight * M_PI_2);
00620
00621 fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
00622 }
00623 }
00624 break;
00625
00626 default:
00627 NOT_REACHED();
00628 break;
00629 }
00630
00631 *h = (height_t)(fheight * (h_max - h_min) + h_min);
00632 if (*h < 0) *h = I2H(0);
00633 if (*h >= h_max) *h = h_max - 1;
00634 }
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 struct control_point_t {
00655 height_t x;
00656 height_t y;
00657 };
00658
00659 struct control_point_list_t {
00660 size_t length;
00661 const control_point_t *list;
00662 };
00663
00664 static const control_point_t _curve_map_1[] = {
00665 { 0, 0 }, { 48, 24 }, { 192, 32 }, { 240, 96 }
00666 };
00667
00668 static const control_point_t _curve_map_2[] = {
00669 { 0, 0 }, { 16, 24 }, { 128, 32 }, { 192, 64 }, { 240, 144 }
00670 };
00671
00672 static const control_point_t _curve_map_3[] = {
00673 { 0, 0 }, { 16, 24 }, { 128, 64 }, { 192, 144 }, { 240, 192 }
00674 };
00675
00676 static const control_point_t _curve_map_4[] = {
00677 { 0, 0 }, { 16, 24 }, { 96, 72 }, { 160, 192 }, { 220, 239 }, { 240, 239 }
00678 };
00679
00680 static const control_point_list_t _curve_maps[] = {
00681 { lengthof(_curve_map_1), _curve_map_1 },
00682 { lengthof(_curve_map_2), _curve_map_2 },
00683 { lengthof(_curve_map_3), _curve_map_3 },
00684 { lengthof(_curve_map_4), _curve_map_4 },
00685 };
00686
00687 static void HeightMapCurves(uint level)
00688 {
00689 height_t ht[lengthof(_curve_maps)];
00690
00691
00692 uint sx = Clamp(1 << level, 2, 32);
00693 uint sy = Clamp(1 << level, 2, 32);
00694 byte *c = (byte *)alloca(sx * sy);
00695
00696 for (uint i = 0; i < sx * sy; i++) {
00697 c[i] = Random() % lengthof(_curve_maps);
00698 }
00699
00700
00701 for (uint x = 0; x < _height_map.size_x; x++) {
00702
00703
00704 float fx = (float)(sx * x) / _height_map.size_x + 0.5f;
00705 uint x1 = (uint)fx;
00706 uint x2 = x1;
00707 float xr = 2.0f * (fx - x1) - 1.0f;
00708 xr = sin(xr * M_PI_2);
00709 xr = sin(xr * M_PI_2);
00710 xr = 0.5f * (xr + 1.0f);
00711 float xri = 1.0f - xr;
00712
00713 if (x1 > 0) {
00714 x1--;
00715 if (x2 >= sx) x2--;
00716 }
00717
00718 for (uint y = 0; y < _height_map.size_y; y++) {
00719
00720
00721 float fy = (float)(sy * y) / _height_map.size_y + 0.5f;
00722 uint y1 = (uint)fy;
00723 uint y2 = y1;
00724 float yr = 2.0f * (fy - y1) - 1.0f;
00725 yr = sin(yr * M_PI_2);
00726 yr = sin(yr * M_PI_2);
00727 yr = 0.5f * (yr + 1.0f);
00728 float yri = 1.0f - yr;
00729
00730 if (y1 > 0) {
00731 y1--;
00732 if (y2 >= sy) y2--;
00733 }
00734
00735 uint corner_a = c[x1 + sx * y1];
00736 uint corner_b = c[x1 + sx * y2];
00737 uint corner_c = c[x2 + sx * y1];
00738 uint corner_d = c[x2 + sx * y2];
00739
00740
00741
00742 uint corner_bits = 0;
00743 corner_bits |= 1 << corner_a;
00744 corner_bits |= 1 << corner_b;
00745 corner_bits |= 1 << corner_c;
00746 corner_bits |= 1 << corner_d;
00747
00748 height_t *h = &_height_map.height(x, y);
00749
00750
00751 for (uint t = 0; t < lengthof(_curve_maps); t++) {
00752 if (!HasBit(corner_bits, t)) continue;
00753
00754 const control_point_t *cm = _curve_maps[t].list;
00755 for (uint i = 0; i < _curve_maps[t].length - 1; i++) {
00756 const control_point_t &p1 = cm[i];
00757 const control_point_t &p2 = cm[i + 1];
00758
00759 if (*h >= p1.x && *h < p2.x) {
00760 ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
00761 break;
00762 }
00763 }
00764 }
00765
00766
00767 *h = (height_t)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr);
00768 }
00769 }
00770 }
00771
00772
00773
00774
00775
00776
00777
00784 struct MHScontrol_point_t {
00785 height_t x;
00786 height_t y;
00787 };
00788
00789 static const MHScontrol_point_t _curve_map[] = {
00790 { 0, 0 }, { 48, 48 }, { 96, 72 }, { 160, 128 }, { 192, 160 }, { 240, 255}, { 255, 255 }
00791 };
00792
00793 static void MHSHeightMapCurves()
00794 {
00795 height_t h_min, h_max, h_avg, h_diff;
00796 HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
00797 h_diff = h_max - h_min;
00798
00799
00800 MHScontrol_point_t *cm = MallocT<MHScontrol_point_t>(lengthof(_curve_map));
00801 for (uint i = 0; i < lengthof(_curve_map); i++) {
00802 cm[i].x = _curve_map[i].x * h_diff / 255 + h_min;
00803 cm[i].y = _curve_map[i].y * h_diff / 255 + h_min;
00804 }
00805
00806
00807 height_t *h;
00808 FOR_ALL_TILES_IN_HEIGHT(h) {
00809 for (uint i = 0; i < lengthof(_curve_map) - 1; i++) {
00810 MHScontrol_point_t &p1 = cm[i];
00811 MHScontrol_point_t &p2 = cm[i + 1];
00812
00813 if (*h >= p1.x && *h <= p2.x) {
00814 *h = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
00815 break;
00816 }
00817 }
00818 }
00819
00820 free(cm);
00821 }
00822
00823
00824
00825
00826
00828 static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
00829 {
00830 height_t h_min, h_max, h_avg, h_water_level;
00831 int64 water_tiles, desired_water_tiles;
00832 height_t *h;
00833 int *hist;
00834
00835 HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
00836
00837
00838 int *hist_buf = CallocT<int>(h_max - h_min + 1);
00839
00840 hist = HeightMapMakeHistogram(h_min, h_max, hist_buf);
00841
00842
00843 desired_water_tiles = A2I(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y));
00844
00845
00846 for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
00847 water_tiles += hist[h_water_level];
00848 if (water_tiles >= desired_water_tiles) break;
00849 }
00850
00851
00852
00853
00854
00855
00856
00857 FOR_ALL_TILES_IN_HEIGHT(h) {
00858
00859 *h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1);
00860
00861 if (*h < 0) *h = I2H(0);
00862 if (*h >= h_max_new) *h = h_max_new - 1;
00863 }
00864
00865 free(hist_buf);
00866 }
00867
00868 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime);
00869
00892 static void HeightMapCoastLines(uint8 water_borders)
00893 {
00894 int smallest_size = min(_settings_game.game_creation.map_x, _settings_game.game_creation.map_y);
00895 const int margin = 4;
00896 uint y, x;
00897 double max_x;
00898 double max_y;
00899
00900
00901 for (y = 0; y <= _height_map.size_y; y++) {
00902 if (HasBit(water_borders, BORDER_NE)) {
00903
00904 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);
00905 max_x = max((smallest_size * smallest_size / 64) + max_x, (smallest_size * smallest_size / 64) + margin - max_x);
00906 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00907 for (x = 0; x < max_x; x++) {
00908 _height_map.height(x, y) = 0;
00909 }
00910 }
00911
00912 if (HasBit(water_borders, BORDER_SW)) {
00913
00914 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);
00915 max_x = max((smallest_size * smallest_size / 64) + max_x, (smallest_size * smallest_size / 64) + margin - max_x);
00916 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00917 for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
00918 _height_map.height(x, y) = 0;
00919 }
00920 }
00921 }
00922
00923
00924 for (x = 0; x <= _height_map.size_x; x++) {
00925 if (HasBit(water_borders, BORDER_NW)) {
00926
00927 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);
00928 max_y = max((smallest_size * smallest_size / 64) + max_y, (smallest_size * smallest_size / 64) + margin - max_y);
00929 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00930 for (y = 0; y < max_y; y++) {
00931 _height_map.height(x, y) = 0;
00932 }
00933 }
00934
00935 if (HasBit(water_borders, BORDER_SE)) {
00936
00937 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);
00938 max_y = max((smallest_size * smallest_size / 64) + max_y, (smallest_size * smallest_size / 64) + margin - max_y);
00939 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00940 for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
00941 _height_map.height(x, y) = 0;
00942 }
00943 }
00944 }
00945 }
00946
00952 static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
00953 {
00954 if ((_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_VERY_ROUGH)
00955 || (_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_CEREALLY_ROUGH)) {
00956
00957 return;
00958 }
00959
00960 const int max_coast_dist_from_edge = 35;
00961 const int max_coast_Smooth_depth = 35;
00962
00963 int x, y;
00964 int ed;
00965 int depth;
00966
00967 height_t h_prev = min(_height_map.size_x + 1, _height_map.size_y + 1) / TGP_HEIGHT_FACTOR;
00968 height_t h;
00969
00970 assert(IsValidXY(org_x, org_y));
00971
00972
00973 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++) {
00974
00975 if (_height_map.height(x, y) > (int)(min(_height_map.size_x + 1, _height_map.size_y + 1) / TGP_HEIGHT_FACTOR - 1)) break;
00976
00977
00978 if (IsValidXY(x + dir_y, y + dir_x) && _height_map.height(x + dir_y, y + dir_x) > 0) break;
00979
00980
00981 if (IsValidXY(x - dir_y, y - dir_x) && _height_map.height(x - dir_y, y - dir_x) > 0) break;
00982 }
00983
00984
00985
00986 for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) {
00987 h = _height_map.height(x, y);
00988 h = min(h, h_prev + (4 + depth));
00989 _height_map.height(x, y) = h;
00990 h_prev = h;
00991 }
00992 }
00993
00995 static void HeightMapSmoothCoasts(uint8 water_borders)
00996 {
00997 uint x, y;
00998
00999 for (x = 0; x < _height_map.size_x; x++) {
01000 if (HasBit(water_borders, BORDER_NW)) HeightMapSmoothCoastInDirection(x, 0, 0, 1);
01001 if (HasBit(water_borders, BORDER_SE)) HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1);
01002 }
01003
01004 for (y = 0; y < _height_map.size_y; y++) {
01005 if (HasBit(water_borders, BORDER_NE)) HeightMapSmoothCoastInDirection(0, y, 1, 0);
01006 if (HasBit(water_borders, BORDER_SW)) HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0);
01007 }
01008 }
01009
01017 static void HeightMapSmoothSlopes(height_t dh_max)
01018 {
01019 int x, y;
01020 for (y = 0; y <= (int)_height_map.size_y; y++) {
01021 for (x = 0; x <= (int)_height_map.size_x; x++) {
01022 height_t h_max = min(_height_map.height(x > 0 ? x - 1 : x, y), _height_map.height(x, y > 0 ? y - 1 : y)) + dh_max;
01023 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
01024 }
01025 }
01026 for (y = _height_map.size_y; y >= 0; y--) {
01027 for (x = _height_map.size_x; x >= 0; x--) {
01028 height_t h_max = min(_height_map.height((uint)x < _height_map.size_x ? x + 1 : x, y), _height_map.height(x, (uint)y < _height_map.size_y ? y + 1 : y)) + dh_max;
01029 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
01030 }
01031 }
01032 }
01033
01038 static int TGPGetMaxAllowedHeight()
01039 {
01040
01041
01042
01043 const int map_size_index_in_mh = min(MapLogX(), MapLogY()) - 6;
01044 const int mh = _max_height[_settings_game.difficulty.terrain_type][map_size_index_in_mh];
01045 const int retValue = I2H(min((min(_height_map.size_x + 1, _height_map.size_y + 1)) / mh, GetMaxTileHeight()));
01046 return retValue;
01047 }
01048
01056 static void HeightMapNormalize()
01057 {
01058 int sea_level_setting = _settings_game.difficulty.quantity_sea_lakes;
01059 const amplitude_t water_percent = sea_level_setting != (int)CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY ? _water_percent[sea_level_setting] : _settings_game.game_creation.custom_sea_level * 1024 / 100;
01060 const height_t h_max_new = TGPGetMaxAllowedHeight() + 1;
01061 const height_t roughness = 7 + 3 * _settings_game.game_creation.tgen_smoothness;
01062
01063 HeightMapAdjustWaterLevel(water_percent, h_max_new);
01064
01065 byte water_borders = _settings_game.construction.freeform_edges ? _settings_game.game_creation.water_borders : 0xF;
01066 if (water_borders == BORDERS_RANDOM) water_borders = GB(Random(), 0, 4);
01067
01068 HeightMapCoastLines(water_borders);
01069 HeightMapSmoothSlopes(roughness);
01070
01071 HeightMapSmoothCoasts(water_borders);
01072 HeightMapSmoothSlopes(roughness);
01073
01074 HeightMapSineTransform(12, h_max_new);
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 if ((_settings_game.game_creation.variety > 0) && (!AllowMoreHeightlevels()) && (_settings_game.game_creation.landscape == 1)) {
01085 HeightMapCurves(_settings_game.game_creation.variety);
01086 }
01087
01088 if ((_settings_game.game_creation.variety > 0) && (AllowMoreHeightlevels()) && (_settings_game.game_creation.landscape == 1)) {
01089 MHSHeightMapCurves();
01090 }
01091
01092
01093
01094
01095
01096
01097 HeightMapSmoothSlopes(16);
01098 }
01099
01107 static double int_noise(const long x, const long y, const int prime)
01108 {
01109 long n = x + y * prime + _settings_game.game_creation.generation_seed;
01110
01111 n = (n << 13) ^ n;
01112
01113
01114 return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
01115 }
01116
01117
01121 static inline double linear_interpolate(const double a, const double b, const double x)
01122 {
01123 return a + x * (b - a);
01124 }
01125
01126
01131 static double interpolated_noise(const double x, const double y, const int prime)
01132 {
01133 const int integer_X = (int)x;
01134 const int integer_Y = (int)y;
01135
01136 const double fractional_X = x - (double)integer_X;
01137 const double fractional_Y = y - (double)integer_Y;
01138
01139 const double v1 = int_noise(integer_X, integer_Y, prime);
01140 const double v2 = int_noise(integer_X + 1, integer_Y, prime);
01141 const double v3 = int_noise(integer_X, integer_Y + 1, prime);
01142 const double v4 = int_noise(integer_X + 1, integer_Y + 1, prime);
01143
01144 const double i1 = linear_interpolate(v1, v2, fractional_X);
01145 const double i2 = linear_interpolate(v3, v4, fractional_X);
01146
01147 return linear_interpolate(i1, i2, fractional_Y);
01148 }
01149
01150
01157 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime)
01158 {
01159 double total = 0.0;
01160 int i;
01161
01162 for (i = 0; i < 6; i++) {
01163 const double frequency = (double)(1 << i);
01164 const double amplitude = pow(p, (double)i);
01165
01166 total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude;
01167 }
01168
01169 return total;
01170 }
01171
01172
01174 static void TgenSetTileHeight(TileIndex tile, int height)
01175 {
01176 SetTileHeight(tile, height);
01177
01178
01179 if (TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY() &&
01180 (!_settings_game.construction.freeform_edges || (TileX(tile) != 0 && TileY(tile) != 0))) {
01181 MakeClear(tile, CLEAR_GRASS, 3);
01182 }
01183 }
01184
01192 void GenerateTerrainPerlin()
01193 {
01194 uint x, y;
01195
01196 if (!AllocHeightMap()) return;
01197 GenerateWorldSetAbortCallback(FreeHeightMap);
01198
01199 HeightMapGenerate();
01200
01201 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01202
01203 HeightMapNormalize();
01204
01205 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01206
01207
01208 if (_settings_game.construction.freeform_edges) {
01209 for (y = 0; y < _height_map.size_y - 1; y++) MakeVoid(_height_map.size_x * y);
01210 for (x = 0; x < _height_map.size_x; x++) MakeVoid(x);
01211 }
01212
01213 const int mh = H2I(TGPGetMaxAllowedHeight());
01214
01215
01216 for (y = 0; y < _height_map.size_y; y++) {
01217 for (x = 0; x < _height_map.size_x; x++) {
01218 int height = H2I(_height_map.height(x, y));
01219
01220 if (height < 0) {
01221 height = 0;
01222 }
01223
01224 if (height > mh - 1) {
01225 height = mh - 1;
01226 }
01227
01228 if (height > (int)GetMaxTileHeight()) {
01229 height = GetMaxTileHeight();
01230 }
01231
01232 TgenSetTileHeight(TileXY(x, y), height);
01233 }
01234 }
01235
01236 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01237
01238 FreeHeightMap();
01239 GenerateWorldSetAbortCallback(NULL);
01240 }