diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 908da1883f..08be51cd9e 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -498,6 +498,7 @@ Starting location(s): [param] = Continent: [param] ([amount] tiles) = Change map to fit selected ruleset? = Area: [amount] tiles, [amount2] continents/islands = +Area: [amount] tiles, [amount2]% water, [amount3] continents/islands = Do you want to leave without saving the recent changes? = Do you want to load another map without saving the recent changes? = Invalid map: Area ([area]) does not match saved dimensions ([dimensions]). = diff --git a/core/src/com/unciv/MainMenuScreen.kt b/core/src/com/unciv/MainMenuScreen.kt index 67d1f65dfe..86c7f5f9df 100644 --- a/core/src/com/unciv/MainMenuScreen.kt +++ b/core/src/com/unciv/MainMenuScreen.kt @@ -75,7 +75,11 @@ class MainMenuScreen: BaseScreen() { crashHandlingThread(name = "ShowMapBackground") { val newMap = MapGenerator(RulesetCache.getVanillaRuleset()) - .generateMap(MapParameters().apply { mapSize = MapSizeNew(MapSize.Small); type = MapType.default }) + .generateMap(MapParameters().apply { + mapSize = MapSizeNew(MapSize.Small) + type = MapType.default + waterThreshold = -0.055f // Gives the same level as when waterThreshold was unused in MapType.default + }) postCrashHandlingRunnable { // for GL context ImageGetter.setNewRuleset(RulesetCache.getVanillaRuleset()) val mapHolder = EditorMapHolder(this, newMap) {} diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index e1df5f8ee8..e4c308b862 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -2,10 +2,10 @@ package com.unciv.logic.map import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.math.Vector2 -import com.unciv.Constants import com.unciv.logic.GameInfo import com.unciv.logic.HexMath import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.map.mapgenerator.MapLandmassGenerator import com.unciv.models.metadata.Player import com.unciv.models.ruleset.Nation import com.unciv.models.ruleset.Ruleset @@ -95,7 +95,7 @@ class TileMap { /** creates a hexagonal map of given radius (filled with grassland) */ constructor(radius: Int, ruleset: Ruleset, worldWrap: Boolean = false) { startingLocations.clear() - val firstAvailableLandTerrain = getInitializationTerrain(ruleset) + val firstAvailableLandTerrain = MapLandmassGenerator.getInitializationTerrain(ruleset, TerrainType.Land) for (vector in HexMath.getVectorsInDistance(Vector2.Zero, radius, worldWrap)) tileList.add(TileInfo().apply { position = vector; baseTerrain = firstAvailableLandTerrain }) setTransients(ruleset) @@ -104,7 +104,7 @@ class TileMap { /** creates a rectangular map of given width and height (filled with grassland) */ constructor(width: Int, height: Int, ruleset: Ruleset, worldWrap: Boolean = false) { startingLocations.clear() - val firstAvailableLandTerrain = getInitializationTerrain(ruleset) + val firstAvailableLandTerrain = MapLandmassGenerator.getInitializationTerrain(ruleset, TerrainType.Land) // world-wrap maps must always have an even width, so round down val wrapAdjustedWidth = if (worldWrap && width % 2 != 0) width -1 else width @@ -121,10 +121,6 @@ class TileMap { setTransients(ruleset) } - private fun getInitializationTerrain(ruleset: Ruleset) = - ruleset.terrains.values.firstOrNull { it.type == TerrainType.Land }?.name - ?: throw Exception("Cannot create map - no land terrains found!") - //endregion //region Operators and Standards diff --git a/core/src/com/unciv/logic/map/mapgenerator/MapLandmassGenerator.kt b/core/src/com/unciv/logic/map/mapgenerator/MapLandmassGenerator.kt index 872730a7ba..3ce0b7ef0b 100644 --- a/core/src/com/unciv/logic/map/mapgenerator/MapLandmassGenerator.kt +++ b/core/src/com/unciv/logic/map/mapgenerator/MapLandmassGenerator.kt @@ -1,6 +1,5 @@ package com.unciv.logic.map.mapgenerator -import com.unciv.Constants import com.unciv.logic.HexMath import com.unciv.logic.map.* import com.unciv.models.ruleset.Ruleset @@ -11,18 +10,28 @@ import kotlin.math.pow class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRandomness) { //region _Fields - private val firstLandTerrain = ruleset.terrains.values.first { it.type==TerrainType.Land } - private val landTerrainName = firstLandTerrain.name - private val firstWaterTerrain = ruleset.terrains.values.firstOrNull { it.type==TerrainType.Water } - private val waterTerrainName = firstWaterTerrain?.name ?: "" + private val landTerrainName = getInitializationTerrain(ruleset, TerrainType.Land) + private val waterTerrainName: String = try { + getInitializationTerrain(ruleset, TerrainType.Water) + } catch (_: Exception) { + landTerrainName + } + private val landOnlyMod: Boolean = waterTerrainName == landTerrainName private var waterThreshold = 0.0 //endregion + companion object { + // this is called from TileMap constructors as well + internal fun getInitializationTerrain(ruleset: Ruleset, type: TerrainType) = + ruleset.terrains.values.firstOrNull { it.type == type }?.name + ?: throw Exception("Cannot create map - no $type terrains found!") + } + fun generateLand(tileMap: TileMap) { // This is to accommodate land-only mods - if (firstWaterTerrain==null) { + if (landOnlyMod) { for (tile in tileMap.values) - tile.baseTerrain = firstLandTerrain.name + tile.baseTerrain = landTerrainName return } @@ -53,11 +62,11 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa if (randomness.RNG.nextFloat() > threshold) continue - val numberOfLandNeighbors = tileInfo.neighbors.count { it.baseTerrain == Constants.grassland } + val numberOfLandNeighbors = tileInfo.neighbors.count { it.baseTerrain == landTerrainName } if (numberOfLandNeighbors > 3) - tileInfo.baseTerrain = Constants.grassland + tileInfo.baseTerrain = landTerrainName else if (numberOfLandNeighbors < 3) - tileInfo.baseTerrain = Constants.ocean + tileInfo.baseTerrain = waterTerrainName } } @@ -189,14 +198,15 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa } private fun generateLandCellularAutomata(tileMap: TileMap) { + // Empiric nice looking range: 0.37..0.72 giving ~15%-85% water + // The old code had 0.55 (inverted) hard-coded, so to get the same we need waterThreshold = -0.055 for the MainMenu background. + waterThreshold = 0.545 + 1.75 * waterThreshold for (tile in tileMap.values) { - tile.baseTerrain = - if (randomness.RNG.nextDouble() < 0.55) Constants.grassland else Constants.ocean - + spawnLandOrWater(tile, randomness.RNG.nextDouble()) tile.setTransients() } smoothen(tileMap) } -} \ No newline at end of file +} diff --git a/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt b/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt index 93dab7dfa6..11620af4de 100644 --- a/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt +++ b/core/src/com/unciv/ui/mapeditor/EditorMapHolder.kt @@ -216,6 +216,11 @@ class EditorMapHolder( val positionalCoords = tileGroupMap.getPositionalVector(stageCoords) val hexPosition = HexMath.world2HexCoords(positionalCoords) val rounded = HexMath.roundHexCoords(hexPosition) - return tileMap.getOrNull(rounded) + + if (!tileMap.mapParameters.worldWrap) + return tileMap.getOrNull(rounded) + val wrapped = HexMath.getUnwrappedNearestTo(rounded, Vector2.Zero, tileMap.maxLongitude) + //todo this works, but means getUnwrappedNearestTo fails - on the x-y == maxLongitude vertical + return tileMap.getOrNull(wrapped) ?: tileMap.getOrNull(rounded) } } diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorGenerateTab.kt b/core/src/com/unciv/ui/mapeditor/MapEditorGenerateTab.kt index d3c380462f..13bb6ca897 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorGenerateTab.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorGenerateTab.kt @@ -109,8 +109,10 @@ class MapEditorGenerateTab( when (step) { MapGeneratorSteps.All -> { val generatedMap = generator!!.generateMap(mapParameters) + val savedScale = editorScreen.mapHolder.scaleX Gdx.app.postRunnable { freshMapCompleted(generatedMap, mapParameters, newRuleset!!, selectPage = 0) + editorScreen.mapHolder.zoom(savedScale) } } MapGeneratorSteps.Landmass -> { diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt index a40a64dd27..970e956910 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt @@ -20,6 +20,7 @@ import com.unciv.ui.utils.* //todo normalize properly +//todo Remove "Area: [amount] tiles, [amount2] continents/islands = " after 2022-07-01 //todo Direct Strategic Resource abundance control //todo functional Tab for Units (empty Tab is prepared but commented out in MapEditorEditTab.AllEditSubTabs) //todo copy/paste tile areas? (As tool tab, brush sized, floodfill forbidden, tab displays copied area) diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorViewTab.kt b/core/src/com/unciv/ui/mapeditor/MapEditorViewTab.kt index 050003d7e8..e7e2999e1b 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorViewTab.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorViewTab.kt @@ -76,7 +76,10 @@ class MapEditorViewTab( ToastPopup("Error assigning continents: ${ex.message}", editorScreen) } - val statsText = "Area: [${tileMap.values.size}] tiles, [${tileMap.continentSizes.size}] continents/islands" + val area = tileMap.values.size + val waterPercent = (tileMap.values.count { it.isWater } * 100f / area).toInt() + val continents = tileMap.continentSizes.size + val statsText = "Area: [$area] tiles, $waterPercent% water, [$continents] continents/islands" val statsLabel = WrappableLabel(statsText, labelWidth) add(statsLabel.apply { wrap = true }).row()