* Calculate what height would be needed to cover N% of the landmass. * * The function allows both snow and desert/tropic line to be calculated. It * tries to find the closest height which covers N% of the landmass; it can * be below or above it. * * Tropic has a mechanism where water and tropic tiles in mountains grow * inside the desert. To better approximate the requested coverage, this i
| 1519 | * @return The estimated best height to use to cover N% of the landmass. |
| 1520 | */ |
| 1521 | static uint CalculateCoverageLine(uint coverage, uint edge_multiplier) |
| 1522 | { |
| 1523 | /* Histogram of how many tiles per height level exist. */ |
| 1524 | std::array<int, MAX_TILE_HEIGHT + 1> histogram = {}; |
| 1525 | /* Histogram of how many neighbour tiles are lower than the tiles of the height level. */ |
| 1526 | std::array<int, MAX_TILE_HEIGHT + 1> edge_histogram = {}; |
| 1527 | |
| 1528 | /* Build a histogram of the map height. */ |
| 1529 | for (const auto tile : Map::Iterate()) { |
| 1530 | uint h = TileHeight(tile); |
| 1531 | histogram[h]++; |
| 1532 | |
| 1533 | if (edge_multiplier != 0) { |
| 1534 | /* Check if any of our neighbours is below us. */ |
| 1535 | for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) { |
| 1536 | TileIndex neighbour_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(dir)); |
| 1537 | if (IsValidTile(neighbour_tile) && TileHeight(neighbour_tile) < h) { |
| 1538 | edge_histogram[h]++; |
| 1539 | } |
| 1540 | } |
| 1541 | } |
| 1542 | } |
| 1543 | |
| 1544 | /* The amount of land we have is the map size minus the first (sea) layer. */ |
| 1545 | uint land_tiles = Map::Size() - histogram[0]; |
| 1546 | int best_score = land_tiles; |
| 1547 | |
| 1548 | /* Our goal is the coverage amount of the land-mass. */ |
| 1549 | int goal_tiles = land_tiles * coverage / 100; |
| 1550 | |
| 1551 | /* We scan from top to bottom. */ |
| 1552 | uint h = MAX_TILE_HEIGHT; |
| 1553 | uint best_h = h; |
| 1554 | |
| 1555 | int current_tiles = 0; |
| 1556 | for (; h > 0; h--) { |
| 1557 | current_tiles += histogram[h]; |
| 1558 | int current_score = goal_tiles - current_tiles; |
| 1559 | |
| 1560 | /* Tropic grows from water and mountains into the desert. This is a |
| 1561 | * great visual, but it also means we* need to take into account how |
| 1562 | * much less desert tiles are being created if we are on this |
| 1563 | * height-level. We estimate this based on how many neighbouring |
| 1564 | * tiles are below us for a given length, assuming that is where |
| 1565 | * tropic is growing from. |
| 1566 | */ |
| 1567 | if (edge_multiplier != 0 && h > 1) { |
| 1568 | /* From water tropic tiles grow for a few tiles land inward. */ |
| 1569 | current_score -= edge_histogram[1] * edge_multiplier; |
| 1570 | /* Tropic tiles grow into the desert for a few tiles. */ |
| 1571 | current_score -= edge_histogram[h] * edge_multiplier; |
| 1572 | } |
| 1573 | |
| 1574 | if (std::abs(current_score) < std::abs(best_score)) { |
| 1575 | best_score = current_score; |
| 1576 | best_h = h; |
| 1577 | } |
| 1578 |
no test coverage detected