Better generation for all map types

Removed 'smoothed random'
This commit is contained in:
Yair Morgenstern 2023-01-19 18:33:32 +02:00
parent 4a3ef08324
commit 508ce0681d
5 changed files with 10 additions and 48 deletions

View File

@ -353,7 +353,6 @@ Map Generation Type =
Enabled Map Generation Types = Enabled Map Generation Types =
Default = Default =
Pangaea = Pangaea =
Smoothed Random =
Continent and Islands = Continent and Islands =
Two Continents = Two Continents =
Three Continents = Three Continents =

View File

@ -1,9 +1,9 @@
package com.unciv.logic.map package com.unciv.logic.map
import com.unciv.logic.IsPartOfGameInfoSerialization
import com.unciv.logic.map.HexMath.getEquivalentHexagonalRadius import com.unciv.logic.map.HexMath.getEquivalentHexagonalRadius
import com.unciv.logic.map.HexMath.getEquivalentRectangularSize import com.unciv.logic.map.HexMath.getEquivalentRectangularSize
import com.unciv.logic.map.HexMath.getNumberOfTilesInHexagon import com.unciv.logic.map.HexMath.getNumberOfTilesInHexagon
import com.unciv.logic.IsPartOfGameInfoSerialization
import com.unciv.models.metadata.BaseRuleset import com.unciv.models.metadata.BaseRuleset
@ -147,9 +147,6 @@ object MapType : IsPartOfGameInfoSerialization {
const val archipelago = "Archipelago" const val archipelago = "Archipelago"
const val innerSea = "Inner Sea" const val innerSea = "Inner Sea"
// Cellular automata style
const val smoothedRandom = "Smoothed Random"
// All ocean tiles // All ocean tiles
const val empty = "Empty" const val empty = "Empty"
} }
@ -230,10 +227,7 @@ class MapParameters : IsPartOfGameInfoSerialization {
vegetationRichness = 0.4f vegetationRichness = 0.4f
rareFeaturesRichness = 0.05f rareFeaturesRichness = 0.05f
resourceRichness = 0.1f resourceRichness = 0.1f
waterThreshold = if (type == MapType.smoothedRandom) waterThreshold = 0f
-0.05f // make world about 55% land
else
0f
} }
fun getArea() = when { fun getArea() = when {

View File

@ -2,8 +2,8 @@ package com.unciv.logic.map.mapgenerator
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.map.HexMath
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.HexMath
import com.unciv.logic.map.MapParameters import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.MapShape import com.unciv.logic.map.MapShape
import com.unciv.logic.map.MapType import com.unciv.logic.map.MapType
@ -903,7 +903,7 @@ class MapGenerationRandomness {
nOctaves: Int = 6, nOctaves: Int = 6,
persistence: Double = 0.5, persistence: Double = 0.5,
lacunarity: Double = 2.0, lacunarity: Double = 2.0,
scale: Double = 10.0 scale: Double = 30.0
): Double { ): Double {
val worldCoords = HexMath.hex2WorldCoords(tile.position) val worldCoords = HexMath.hex2WorldCoords(tile.position)
return Perlin.noise3d(worldCoords.x.toDouble(), worldCoords.y.toDouble(), seed, nOctaves, persistence, lacunarity, scale) return Perlin.noise3d(worldCoords.x.toDouble(), worldCoords.y.toDouble(), seed, nOctaves, persistence, lacunarity, scale)

View File

@ -49,7 +49,6 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
MapType.twoContinents -> createTwoContinents(tileMap) MapType.twoContinents -> createTwoContinents(tileMap)
MapType.threeContinents -> createThreeContinents(tileMap) MapType.threeContinents -> createThreeContinents(tileMap)
MapType.fourCorners -> createFourCorners(tileMap) MapType.fourCorners -> createFourCorners(tileMap)
MapType.smoothedRandom -> generateLandCellularAutomata(tileMap)
MapType.archipelago -> createArchipelago(tileMap) MapType.archipelago -> createArchipelago(tileMap)
MapType.default -> createPerlin(tileMap) MapType.default -> createPerlin(tileMap)
} }
@ -89,24 +88,6 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
tile.baseTerrain = if (elevation < waterThreshold) waterTerrainName else landTerrainName tile.baseTerrain = if (elevation < waterThreshold) waterTerrainName else landTerrainName
} }
/**
* Smoothen the map by clustering landmass and oceans with probability [threshold].
* [TileInfo]s with more than 3 land neighbours are converted to land.
* [TileInfo]s with more than 3 water neighbours are converted to water.
*/
private fun smoothen(tileMap: TileMap, threshold: Double = 1.0) {
for (tileInfo in tileMap.values) {
if (randomness.RNG.nextFloat() > threshold)
continue
val numberOfLandNeighbors = tileInfo.neighbors.count { it.baseTerrain == landTerrainName }
if (numberOfLandNeighbors > 3)
tileInfo.baseTerrain = landTerrainName
else if (numberOfLandNeighbors < 3)
tileInfo.baseTerrain = waterTerrainName
}
}
private fun createPerlin(tileMap: TileMap) { private fun createPerlin(tileMap: TileMap) {
val elevationSeed = randomness.RNG.nextInt().toDouble() val elevationSeed = randomness.RNG.nextInt().toDouble()
for (tile in tileMap.values) { for (tile in tileMap.values) {
@ -127,7 +108,7 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
private fun createPangaea(tileMap: TileMap) { private fun createPangaea(tileMap: TileMap) {
val elevationSeed = randomness.RNG.nextInt().toDouble() val elevationSeed = randomness.RNG.nextInt().toDouble()
for (tile in tileMap.values) { for (tile in tileMap.values) {
var elevation = randomness.getPerlinNoise(tile, elevationSeed, scale=30.0) var elevation = randomness.getPerlinNoise(tile, elevationSeed)
elevation = elevation*(3/4f) + getEllipticContinent(tile, tileMap) / 4 elevation = elevation*(3/4f) + getEllipticContinent(tile, tileMap) / 4
spawnLandOrWater(tile, elevation) spawnLandOrWater(tile, elevation)
} }
@ -190,7 +171,7 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
val elevationSeed = randomness.RNG.nextInt().toDouble() val elevationSeed = randomness.RNG.nextInt().toDouble()
for (tile in tileMap.values) { for (tile in tileMap.values) {
var elevation = randomness.getPerlinNoise(tile, elevationSeed) var elevation = randomness.getPerlinNoise(tile, elevationSeed)
elevation = (elevation + getFourCornersTransform(tile, tileMap)) / 2.0 elevation = elevation/2 + getFourCornersTransform(tile, tileMap)/2
spawnLandOrWater(tile, elevation) spawnLandOrWater(tile, elevation)
} }
} }
@ -248,7 +229,7 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
// So what we do it create a line of water in the middle - where latitude or longitude is close to 0. // So what we do it create a line of water in the middle - where latitude or longitude is close to 0.
val randomScale = randomness.RNG.nextDouble() val randomScale = randomness.RNG.nextDouble()
val latitudeFactor = abs(tileInfo.latitude) / tileMap.maxLatitude val latitudeFactor = abs(tileInfo.latitude) / tileMap.maxLatitude
var longitudeFactor = abs(tileInfo.longitude) / tileMap.maxLongitude val longitudeFactor = abs(tileInfo.longitude) / tileMap.maxLongitude
var factor = if (isLatitude) latitudeFactor else longitudeFactor var factor = if (isLatitude) latitudeFactor else longitudeFactor
@ -317,9 +298,11 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
) * 1.5f ) * 1.5f
} }
val shouldBeWater = 1-factor
// there's nothing magical about this, it's just what we got from playing around with a lot of different options - // there's nothing magical about this, it's just what we got from playing around with a lot of different options -
// the numbers can be changed if you find that something else creates better looking continents // the numbers can be changed if you find that something else creates better looking continents
return min(0.2, -1.0 + (5.0 * factor.pow(0.5f) + randomScale) / 3.0) return 1.0 - (5.0 * shouldBeWater*shouldBeWater + randomScale) / 3.0
} }
/** /**
@ -333,17 +316,4 @@ class MapLandmassGenerator(val ruleset: Ruleset, val randomness: MapGenerationRa
val worldCoords = HexMath.hex2WorldCoords(tile.position) val worldCoords = HexMath.hex2WorldCoords(tile.position)
return Perlin.ridgedNoise3d(worldCoords.x.toDouble(), worldCoords.y.toDouble(), seed, nOctaves, persistence, lacunarity, scale) return Perlin.ridgedNoise3d(worldCoords.x.toDouble(), worldCoords.y.toDouble(), seed, nOctaves, persistence, lacunarity, scale)
} }
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) {
spawnLandOrWater(tile, randomness.RNG.nextDouble()) // RNG is [0.0, 1.0]
tile.setTransients()
}
smoothen(tileMap)
}
} }

View File

@ -123,7 +123,6 @@ class MapParametersTable(
MapType.twoContinents, MapType.twoContinents,
MapType.threeContinents, MapType.threeContinents,
MapType.fourCorners, MapType.fourCorners,
MapType.smoothedRandom,
MapType.archipelago, MapType.archipelago,
MapType.innerSea, MapType.innerSea,
if (forMapEditor && mapGeneratedMainType != MapGeneratedMainType.randomGenerated) MapType.empty else null if (forMapEditor && mapGeneratedMainType != MapGeneratedMainType.randomGenerated) MapType.empty else null