Skip to content

Commit

Permalink
Feature: setting to indicate desert coverage for tropic climate
Browse files Browse the repository at this point in the history
This is an indication value; the game tries to get as close as it
can, but due to the complex tropic rules, that is unlikely to be
exact.

In the end, it picks a height-level to base the desert/tropic
line on. This is strictly seen not needed, as we can convert any
tile to either. But it is the simplest way to get started with
this without redoing all related functions.
  • Loading branch information
TrueBrain committed Mar 26, 2021
1 parent cafe4ee commit 70bc55c
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 33 deletions.
90 changes: 78 additions & 12 deletions src/genworld_gui.cpp
Expand Up @@ -111,7 +111,10 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = {
NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_MAX_HEIGHTLEVEL, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SNOW_COVERAGE, STR_NULL), SetFill(1, 1),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GL_CLIMATE_SEL_LABEL),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SNOW_COVERAGE, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_DESERT_COVERAGE, STR_NULL), SetFill(1, 1),
EndContainer(),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_DATE, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SMOOTHNESS, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_QUANTITY_OF_RIVERS, STR_NULL), SetFill(1, 1),
Expand All @@ -124,11 +127,19 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = {
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_MAX_HEIGHTLEVEL_TEXT), SetDataTip(STR_BLACK_INT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_MAX_HEIGHTLEVEL_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_MAX_HEIGHTLEVEL_UP), SetFill(0, 1),
EndContainer(),
/* Snow line. */
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_MAPGEN_SNOW_COVERAGE_DOWN), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_TEXT), SetDataTip(STR_MAPGEN_SNOW_COVERAGE_TEXT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_SNOW_COVERAGE_UP), SetFill(0, 1),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GL_CLIMATE_SEL_SELECTOR),
/* Snow coverage. */
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_MAPGEN_SNOW_COVERAGE_DOWN), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_TEXT), SetDataTip(STR_MAPGEN_SNOW_COVERAGE_TEXT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_SNOW_COVERAGE_UP), SetFill(0, 1),
EndContainer(),
/* Desert coverage. */
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_DESERT_COVERAGE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_MAPGEN_DESERT_COVERAGE_DOWN), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_DESERT_COVERAGE_TEXT), SetDataTip(STR_MAPGEN_DESERT_COVERAGE_TEXT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_DESERT_COVERAGE_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_DESERT_COVERAGE_UP), SetFill(0, 1),
EndContainer(),
EndContainer(),
/* Starting date. */
NWidget(NWID_HORIZONTAL),
Expand Down Expand Up @@ -228,7 +239,10 @@ static const NWidgetPart _nested_heightmap_load_widgets[] = {
NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_MAX_HEIGHTLEVEL, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SNOW_COVERAGE, STR_NULL), SetFill(1, 1),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GL_CLIMATE_SEL_LABEL),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SNOW_COVERAGE, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_DESERT_COVERAGE, STR_NULL), SetFill(1, 1),
EndContainer(),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_DATE, STR_NULL), SetFill(1, 1),
NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL), SetFill(1, 1),
EndContainer(),
Expand All @@ -238,10 +252,17 @@ static const NWidgetPart _nested_heightmap_load_widgets[] = {
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_MAX_HEIGHTLEVEL_TEXT), SetDataTip(STR_BLACK_INT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_MAX_HEIGHTLEVEL_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_MAX_HEIGHTLEVEL_UP), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_MAPGEN_SNOW_COVERAGE_DOWN), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_TEXT), SetDataTip(STR_BLACK_INT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_SNOW_COVERAGE_UP), SetFill(0, 1),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GL_CLIMATE_SEL_SELECTOR),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_MAPGEN_SNOW_COVERAGE_DOWN), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_TEXT), SetDataTip(STR_MAPGEN_SNOW_COVERAGE_TEXT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_SNOW_COVERAGE_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_SNOW_COVERAGE_UP), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_DESERT_COVERAGE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_MAPGEN_DESERT_COVERAGE_DOWN), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_DESERT_COVERAGE_TEXT), SetDataTip(STR_MAPGEN_DESERT_COVERAGE_TEXT, STR_NULL), SetFill(1, 0),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_DESERT_COVERAGE_UP), SetDataTip(SPR_ARROW_UP, STR_MAPGEN_DESERT_COVERAGE_UP), SetFill(0, 1),
EndContainer(),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_IMGBTN, COLOUR_ORANGE, WID_GL_START_DATE_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD), SetFill(0, 1),
Expand Down Expand Up @@ -367,6 +388,7 @@ struct GenerateLandscapeWindow : public Window {
case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break;
case WID_GL_MAX_HEIGHTLEVEL_TEXT: SetDParam(0, _settings_newgame.construction.max_heightlevel); break;
case WID_GL_SNOW_COVERAGE_TEXT: SetDParam(0, _settings_newgame.game_creation.snow_coverage); break;
case WID_GL_DESERT_COVERAGE_TEXT: SetDParam(0, _settings_newgame.game_creation.desert_coverage); break;

case WID_GL_TOWN_PULLDOWN:
if (_game_mode == GM_EDITOR) {
Expand Down Expand Up @@ -458,6 +480,19 @@ struct GenerateLandscapeWindow : public Window {

/* Disable snowline if not arctic */
this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_TEXT, _settings_newgame.game_creation.landscape != LT_ARCTIC);
/* Disable desert if not tropic */
this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_TEXT, _settings_newgame.game_creation.landscape != LT_TROPIC);

/* Set snow/rainforest selections */
int climate_plane = 0;
switch (_settings_newgame.game_creation.landscape) {
case LT_TEMPERATE: climate_plane = SZSP_VERTICAL; break;
case LT_ARCTIC: climate_plane = 0; break;
case LT_TROPIC: climate_plane = 1; break;
case LT_TOYLAND: climate_plane = SZSP_VERTICAL; break;
}
this->GetWidget<NWidgetStacked>(WID_GL_CLIMATE_SEL_LABEL)->SetDisplayedPlane(climate_plane);
this->GetWidget<NWidgetStacked>(WID_GL_CLIMATE_SEL_SELECTOR)->SetDisplayedPlane(climate_plane);

/* Update availability of decreasing / increasing start date and snow level */
this->SetWidgetDisabledState(WID_GL_MAX_HEIGHTLEVEL_DOWN, _settings_newgame.construction.max_heightlevel <= MIN_MAX_HEIGHTLEVEL);
Expand All @@ -466,6 +501,8 @@ struct GenerateLandscapeWindow : public Window {
this->SetWidgetDisabledState(WID_GL_START_DATE_UP, _settings_newgame.game_creation.starting_year >= MAX_YEAR);
this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_DOWN, _settings_newgame.game_creation.snow_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_ARCTIC);
this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_UP, _settings_newgame.game_creation.snow_coverage >= 100 || _settings_newgame.game_creation.landscape != LT_ARCTIC);
this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_DOWN, _settings_newgame.game_creation.desert_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_TROPIC);
this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_UP, _settings_newgame.game_creation.desert_coverage >= 100 || _settings_newgame.game_creation.landscape != LT_TROPIC);

/* Do not allow a custom sea level with the original land generator. */
if (_settings_newgame.game_creation.land_generator == LG_ORIGINAL &&
Expand Down Expand Up @@ -500,6 +537,11 @@ struct GenerateLandscapeWindow : public Window {
*size = maxdim(*size, GetStringBoundingBox(STR_MAPGEN_SNOW_COVERAGE_TEXT));
break;

case WID_GL_DESERT_COVERAGE_TEXT:
SetDParamMaxValue(0, MAX_TILE_HEIGHT);
*size = maxdim(*size, GetStringBoundingBox(STR_MAPGEN_DESERT_COVERAGE_TEXT));
break;

case WID_GL_HEIGHTMAP_SIZE_TEXT:
SetDParam(0, this->x);
SetDParam(1, this->y);
Expand Down Expand Up @@ -674,6 +716,24 @@ struct GenerateLandscapeWindow : public Window {
ShowQueryString(STR_JUST_INT, STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
break;

case WID_GL_DESERT_COVERAGE_DOWN:
case WID_GL_DESERT_COVERAGE_UP: // Desert coverage buttons
/* Don't allow too fast scrolling */
if (!(this->flags & WF_TIMEOUT) || this->timeout_timer <= 1) {
this->HandleButtonClick(widget);

_settings_newgame.game_creation.desert_coverage = Clamp(_settings_newgame.game_creation.desert_coverage + (widget - WID_GL_DESERT_COVERAGE_TEXT) * 10, 0, 100);
this->InvalidateData();
}
_left_button_clicked = false;
break;

case WID_GL_DESERT_COVERAGE_TEXT: // Desert line text
this->widget_id = WID_GL_DESERT_COVERAGE_TEXT;
SetDParam(0, _settings_newgame.game_creation.desert_coverage);
ShowQueryString(STR_JUST_INT, STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
break;

case WID_GL_LANDSCAPE_PULLDOWN: // Landscape generator
ShowDropDownMenu(this, _landscape, _settings_newgame.game_creation.land_generator, WID_GL_LANDSCAPE_PULLDOWN, 0, 0);
break;
Expand Down Expand Up @@ -739,7 +799,7 @@ struct GenerateLandscapeWindow : public Window {

void OnTimeout() override
{
static const int raise_widgets[] = {WID_GL_MAX_HEIGHTLEVEL_DOWN, WID_GL_MAX_HEIGHTLEVEL_UP, WID_GL_START_DATE_DOWN, WID_GL_START_DATE_UP, WID_GL_SNOW_COVERAGE_UP, WID_GL_SNOW_COVERAGE_DOWN, WIDGET_LIST_END};
static const int raise_widgets[] = {WID_GL_MAX_HEIGHTLEVEL_DOWN, WID_GL_MAX_HEIGHTLEVEL_UP, WID_GL_START_DATE_DOWN, WID_GL_START_DATE_UP, WID_GL_SNOW_COVERAGE_UP, WID_GL_SNOW_COVERAGE_DOWN, WID_GL_DESERT_COVERAGE_UP, WID_GL_DESERT_COVERAGE_DOWN, WIDGET_LIST_END};
for (const int *widget = raise_widgets; *widget != WIDGET_LIST_END; widget++) {
if (this->IsWidgetLowered(*widget)) {
this->RaiseWidget(*widget);
Expand Down Expand Up @@ -812,6 +872,7 @@ struct GenerateLandscapeWindow : public Window {
case WID_GL_MAX_HEIGHTLEVEL_TEXT: value = DEF_MAX_HEIGHTLEVEL; break;
case WID_GL_START_DATE_TEXT: value = DEF_START_YEAR; break;
case WID_GL_SNOW_COVERAGE_TEXT: value = DEF_SNOW_COVERAGE; break;
case WID_GL_DESERT_COVERAGE_TEXT: value = DEF_DESERT_COVERAGE; break;
case WID_GL_TOWN_PULLDOWN: value = 1; break;
case WID_GL_WATER_PULLDOWN: value = CUSTOM_SEA_LEVEL_MIN_PERCENTAGE; break;
default: NOT_REACHED();
Expand All @@ -834,6 +895,11 @@ struct GenerateLandscapeWindow : public Window {
_settings_newgame.game_creation.snow_coverage = Clamp(value, 0, 100);
break;

case WID_GL_DESERT_COVERAGE_TEXT:
this->SetWidgetDirty(WID_GL_DESERT_COVERAGE_TEXT);
_settings_newgame.game_creation.desert_coverage = Clamp(value, 0, 100);
break;

case WID_GL_TOWN_PULLDOWN:
_settings_newgame.game_creation.custom_town_number = Clamp(value, 1, CUSTOM_TOWN_MAX_NUMBER);
break;
Expand Down
93 changes: 83 additions & 10 deletions src/landscape.cpp
Expand Up @@ -968,11 +968,10 @@ static void GenerateTerrain(int type, uint flag)

#include "table/genland.h"

static void CreateDesertOrRainForest()
static void CreateDesertOrRainForest(uint desert_tropic_line)
{
TileIndex update_freq = MapSize() / 4;
const TileIndexDiffC *data;
uint max_desert_height = CeilDiv(_settings_game.construction.max_heightlevel, 4);

for (TileIndex tile = 0; tile != MapSize(); ++tile) {
if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
Expand All @@ -982,7 +981,7 @@ static void CreateDesertOrRainForest()
for (data = _make_desert_or_rainforest_data;
data != endof(_make_desert_or_rainforest_data); ++data) {
TileIndex t = AddTileIndexDiffCWrap(tile, *data);
if (t != INVALID_TILE && (TileHeight(t) >= max_desert_height || IsTileType(t, MP_WATER))) break;
if (t != INVALID_TILE && (TileHeight(t) >= desert_tropic_line || IsTileType(t, MP_WATER))) break;
}
if (data == endof(_make_desert_or_rainforest_data)) {
SetTropicZone(tile, TROPICZONE_DESERT);
Expand Down Expand Up @@ -1296,23 +1295,58 @@ static void CreateRivers()
}

/**
* Calculate the line from which snow begins.
* 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 closests 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 is
* taken into account via an edge histogram, which tells how many neighbouring
* tiles are lower than the tiles of that height. The multiplier indicates how
* severe this has to be taken into account.
*
* @param coverage A value between 0 and 100 indicating a percentage of landmass that should be covered.
* @param edge_multiplier How much effect neighbouring tiles that are of a lower height level have on the score.
* @return The estimated best height to use to cover N% of the landmass.
*/
static void CalculateSnowLine()
static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
{
/* Build a histogram of the map height. */
const DiagDirection neighbour_dir[] = {
DIAGDIR_NE,
DIAGDIR_SE,
DIAGDIR_SW,
DIAGDIR_NW,
};

/* Histogram of how many tiles per height level exist. */
std::array<int, MAX_TILE_HEIGHT + 1> histogram = {};
/* Histogram of how many neighbour tiles are lower than the tiles of the height level. */
std::array<int, MAX_TILE_HEIGHT + 1> edge_histogram = {};

/* Build a histogram of the map height. */
for (TileIndex tile = 0; tile < MapSize(); tile++) {
uint h = TileHeight(tile);
histogram[h]++;

if (edge_multiplier != 0) {
/* Check if any of our neighbours is below us. */
for (auto dir : neighbour_dir) {
TileIndex neighbour_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(dir));
if (IsValidTile(neighbour_tile) && TileHeight(neighbour_tile) < h) {
edge_histogram[h]++;
}
}
}
}

/* The amount of land we have is the map size minus the first (sea) layer. */
uint land_tiles = MapSizeX() * MapSizeY() - histogram[0];
int best_score = land_tiles;

/* Our goal is the coverage amount of the land-mass. */
int goal_tiles = land_tiles * _settings_game.game_creation.snow_coverage / 100;
int goal_tiles = land_tiles * coverage / 100;

/* We scan from top to bottom. */
uint h = MAX_TILE_HEIGHT;
Expand All @@ -1323,13 +1357,50 @@ static void CalculateSnowLine()
current_tiles += histogram[h];
int current_score = goal_tiles - current_tiles;

/* Tropic grows from water and mountains into the desert. This is a
* great visual, but it also means we* need to take into account how
* much less desert tiles are being created if we are on this
* height-level. We estimate this based on how many neighbouring
* tiles are below us for a given length, assuming that is where
* tropic is growing from.
*/
if (edge_multiplier != 0 && h > 1) {
/* From water tropic tiles grow for a few tiles land inward. */
current_score -= edge_histogram[1] * edge_multiplier;
/* Tropic tiles grow into the desert for a few tiles. */
current_score -= edge_histogram[h] * edge_multiplier;
}

if (std::abs(current_score) < std::abs(best_score)) {
best_score = current_score;
best_h = h;
}

/* Always scan all height-levels, as h == 1 might give a better
* score than any before. This is true for example with 0% desert
* coverage. */
}

_settings_game.game_creation.snow_line_height = std::max(best_h, 2u);
return best_h;
}

/**
* Calculate the line from which snow begins.
*/
static void CalculateSnowLine()
{
/* We do not have snow sprites on coastal tiles, so never allow "1" as height. */
_settings_game.game_creation.snow_line_height = std::max(CalculateCoverageLine(_settings_game.game_creation.snow_coverage, 0), 2u);
}

/**
* Calculate the line (in height) between desert and tropic.
* @return The height of the line between desert and tropic.
*/
static uint8 CalculateDesertLine()
{
/* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */
return _settings_game.game_creation.snow_line_height = CalculateCoverageLine(100 - _settings_game.game_creation.desert_coverage, 4);
}

void GenerateLandscape(byte mode)
Expand Down Expand Up @@ -1421,9 +1492,11 @@ void GenerateLandscape(byte mode)
CalculateSnowLine();
break;

case LT_TROPIC:
CreateDesertOrRainForest();
case LT_TROPIC: {
uint desert_tropic_line = CalculateDesertLine();
CreateDesertOrRainForest(desert_tropic_line);
break;
}

default:
break;
Expand Down

0 comments on commit 70bc55c

Please sign in to comment.