Solve continentSizes serialization by removing it (#5403)

This commit is contained in:
SomeTroglodyte 2021-10-05 14:30:32 +02:00 committed by GitHub
parent c9f23b644a
commit 4c6f1ecfb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 7 deletions

View File

@ -84,7 +84,7 @@ object GameStarter {
if (tileMap.continentSizes.isEmpty()) // Probably saved map without continent data if (tileMap.continentSizes.isEmpty()) // Probably saved map without continent data
runAndMeasure("assignContinents") { runAndMeasure("assignContinents") {
tileMap.assignContinents() tileMap.assignContinents(TileMap.AssignContinentsMode.Ensure)
} }
runAndMeasure("addCivStartingUnits") { runAndMeasure("addCivStartingUnits") {
@ -353,7 +353,7 @@ object GameStarter {
tileMap: TileMap, tileMap: TileMap,
startScores: HashMap<TileInfo, Float> startScores: HashMap<TileInfo, Float>
): Map<TileInfo, Float> { ): Map<TileInfo, Float> {
if (tileMap.continentSizes.isEmpty()) tileMap.assignContinents() tileMap.assignContinents(TileMap.AssignContinentsMode.Ensure)
// We want to distribute starting locations fairly, and thus not place anybody on a small island // We want to distribute starting locations fairly, and thus not place anybody on a small island
// - unless necessary. Old code would only consider landmasses >= 20 tiles. // - unless necessary. Old code would only consider landmasses >= 20 tiles.

View File

@ -33,6 +33,7 @@ object MapSaver {
} }
} }
fun mapToSavedString(tileMap: TileMap): String { fun mapToSavedString(tileMap: TileMap): String {
tileMap.assignContinents(TileMap.AssignContinentsMode.Reassign)
val mapJson = json().toJson(tileMap) val mapJson = json().toJson(tileMap)
return if (saveZipped) Gzip.zip(mapJson) else mapJson return if (saveZipped) Gzip.zip(mapJson) else mapJson
} }

View File

@ -804,5 +804,8 @@ open class TileInfo {
this.continent = continent this.continent = continent
} }
/** Clear continent ID, for map editor */
fun clearContinent() { continent = -1 }
//endregion //endregion
} }

View File

@ -34,7 +34,6 @@ class TileMap {
var mapParameters = MapParameters() var mapParameters = MapParameters()
private var tileList = ArrayList<TileInfo>() private var tileList = ArrayList<TileInfo>()
val continentSizes = HashMap<Int, Int>() // Continent ID, Continent size
/** Structure geared for simple serialization by Gdx.Json (which is a little blind to kotlin collections, especially HashSet) /** Structure geared for simple serialization by Gdx.Json (which is a little blind to kotlin collections, especially HashSet)
* @param position [Vector2] of the location * @param position [Vector2] of the location
@ -79,6 +78,9 @@ class TileMap {
@Transient @Transient
val startingLocationsByNation = HashMap<String,HashSet<TileInfo>>() val startingLocationsByNation = HashMap<String,HashSet<TileInfo>>()
@Transient
val continentSizes = HashMap<Int, Int>() // Continent ID, Continent size
//endregion //endregion
//region Constructors //region Constructors
@ -124,7 +126,6 @@ class TileMap {
toReturn.startingLocations.clear() toReturn.startingLocations.clear()
toReturn.startingLocations.ensureCapacity(startingLocations.size) toReturn.startingLocations.ensureCapacity(startingLocations.size)
toReturn.startingLocations.addAll(startingLocations) toReturn.startingLocations.addAll(startingLocations)
toReturn.continentSizes.putAll(continentSizes)
return toReturn return toReturn
} }
@ -347,6 +348,7 @@ class TileMap {
} }
fun isWaterMap(): Boolean { fun isWaterMap(): Boolean {
assignContinents(AssignContinentsMode.Ensure)
val bigIslands = continentSizes.count { it.value > 20 } val bigIslands = continentSizes.count { it.value > 20 }
val players = gameInfo.gameParameters.players.count() val players = gameInfo.gameParameters.players.count()
return bigIslands >= players return bigIslands >= players
@ -558,13 +560,41 @@ class TileMap {
startingLocationsByNation.clear() startingLocationsByNation.clear()
} }
/** Behaviour of [assignContinents] */
enum class AssignContinentsMode { Assign, Reassign, Ensure, Clear }
/** Set a continent id for each tile, so we can quickly see which tiles are connected. /** Set a continent id for each tile, so we can quickly see which tiles are connected.
* Can also be called on saved maps. * Can also be called on saved maps.
* @throws Exception when any land tile already has a continent ID * @param mode As follows:
* [Assign][AssignContinentsMode.Assign] = initial assign, throw if tiles have continents.
* [Reassign][AssignContinentsMode.Reassign] = clear continent data and redo for map editor.
* [Ensure][AssignContinentsMode.Ensure] = regenerate continent sizes from tile data, and if that is empty, Assign.
* @throws Exception when `mode==Assign` and any land tile already has a continent ID
* @return A map of continent sizes (continent ID to tile count)
*/ */
fun assignContinents() { fun assignContinents(mode: AssignContinentsMode) {
if (mode == AssignContinentsMode.Clear) {
values.forEach { it.clearContinent() }
continentSizes.clear()
return
}
if (mode == AssignContinentsMode.Ensure) {
if (continentSizes.isNotEmpty()) return
for (tile in values) {
val continent = tile.getContinent()
if (continent == -1) continue
continentSizes[continent] = 1 + (continentSizes[continent] ?: 0)
}
if (continentSizes.isNotEmpty()) return
}
var landTiles = values.filter { it.isLand && !it.isImpassible() } var landTiles = values.filter { it.isLand && !it.isImpassible() }
var currentContinent = 0 var currentContinent = 0
continentSizes.clear()
if (mode == AssignContinentsMode.Reassign)
values.forEach { it.clearContinent() }
while (landTiles.any()) { while (landTiles.any()) {
val bfs = BFS(landTiles.random()) { it.isLand && !it.isImpassible() } val bfs = BFS(landTiles.random()) { it.isLand && !it.isImpassible() }

View File

@ -74,7 +74,7 @@ class MapGenerator(val ruleset: Ruleset) {
spawnIce(map) spawnIce(map)
} }
runAndMeasure("assignContinents") { runAndMeasure("assignContinents") {
map.assignContinents() map.assignContinents(TileMap.AssignContinentsMode.Assign)
} }
runAndMeasure("NaturalWonderGenerator") { runAndMeasure("NaturalWonderGenerator") {
NaturalWonderGenerator(ruleset, randomness).spawnNaturalWonders(map) NaturalWonderGenerator(ruleset, randomness).spawnNaturalWonders(map)

View File

@ -184,6 +184,7 @@ class TileGroupIcons(val tileGroup: TileGroup) {
// different stacking order of the same nations in the same editing session // different stacking order of the same nations in the same editing session
val nations = tileInfo.tileMap.startingLocationsByNation.asSequence() val nations = tileInfo.tileMap.startingLocationsByNation.asSequence()
.filter { tileInfo in it.value } .filter { tileInfo in it.value }
.filter { it.key in tileInfo.tileMap.ruleset!!.nations } // Ignore missing nations
.map { it.key to tileInfo.tileMap.ruleset!!.nations[it.key]!! } .map { it.key to tileInfo.tileMap.ruleset!!.nations[it.key]!! }
.sortedWith(compareBy({ it.second.isCityState() }, { it.first })) .sortedWith(compareBy({ it.second.isCityState() }, { it.first }))
.toList() .toList()