Allow generation of "Default" Deciv redux maps (#6821)

This commit is contained in:
SomeTroglodyte
2022-05-16 12:03:06 +02:00
committed by GitHub
parent 68a0e25c9e
commit 8329d56131
8 changed files with 46 additions and 24 deletions

View File

@ -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]). =

View File

@ -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) {}

View File

@ -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

View File

@ -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)
}
}
}

View File

@ -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)
}
}

View File

@ -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 -> {

View File

@ -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)

View File

@ -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()