Convert 'camps' vectorhashmap to 'encampments' arraylist (#9374)

This commit is contained in:
Yair Morgenstern
2023-05-11 16:51:29 +03:00
committed by GitHub
parent 9a0ba7dcd8
commit dde3732383
4 changed files with 33 additions and 41 deletions

View File

@ -1,14 +1,13 @@
package com.unciv.logic package com.unciv.logic
import com.unciv.Constants import com.unciv.Constants
import com.unciv.logic.automation.civilization.BarbarianManager
import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.CityConstructions
import com.unciv.models.ruleset.PerpetualConstruction
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.civilization.diplomacy.DiplomacyManager import com.unciv.logic.civilization.diplomacy.DiplomacyManager
import com.unciv.logic.civilization.managers.TechManager import com.unciv.logic.civilization.managers.TechManager
import com.unciv.logic.map.tile.RoadStatus import com.unciv.logic.map.tile.RoadStatus
import com.unciv.models.ruleset.ModOptions import com.unciv.models.ruleset.ModOptions
import com.unciv.models.ruleset.PerpetualConstruction
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
/** /**
@ -161,7 +160,6 @@ object BackwardCompatibility {
fun ModOptions.updateDeprecations() { fun ModOptions.updateDeprecations() {
} }
/** Convert from Fortify X to Fortify and save off X */ /** Convert from Fortify X to Fortify and save off X */
fun GameInfo.convertFortify() { fun GameInfo.convertFortify() {
val reg = Regex("""^Fortify\s+(\d+)([\w\s]*)""") val reg = Regex("""^Fortify\s+(\d+)([\w\s]*)""")
@ -176,16 +174,11 @@ object BackwardCompatibility {
} }
} }
private fun isOldFormat(manager: BarbarianManager): Boolean { fun GameInfo.convertEncampmentData(){
val keys = manager.camps.keys as Set<Any> if (barbarians.camps.isNotEmpty()){
val iterator = keys.iterator() barbarians.encampments.addAll(barbarians.camps.values)
while (iterator.hasNext()) { barbarians.camps.clear()
val key = iterator.next()
if (key is String) {
return true
}
} }
return false
} }
fun GameInfo.migrateToTileHistory() { fun GameInfo.migrateToTileHistory() {

View File

@ -3,6 +3,7 @@ package com.unciv.logic
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.UncivGame.Version import com.unciv.UncivGame.Version
import com.unciv.logic.BackwardCompatibility.convertEncampmentData
import com.unciv.logic.BackwardCompatibility.convertFortify import com.unciv.logic.BackwardCompatibility.convertFortify
import com.unciv.logic.BackwardCompatibility.guaranteeUnitPromotions import com.unciv.logic.BackwardCompatibility.guaranteeUnitPromotions
import com.unciv.logic.BackwardCompatibility.migrateToTileHistory import com.unciv.logic.BackwardCompatibility.migrateToTileHistory
@ -35,9 +36,7 @@ import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.utils.DebugUtils import com.unciv.utils.DebugUtils
import com.unciv.utils.debug import com.unciv.utils.debug
import java.util.UUID import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
/** /**
@ -611,6 +610,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
.flatMap { it.getResourceRequirementsPerTurn().keys }) .flatMap { it.getResourceRequirementsPerTurn().keys })
spaceResources.addAll(ruleset.victories.values.flatMap { it.requiredSpaceshipParts }) spaceResources.addAll(ruleset.victories.values.flatMap { it.requiredSpaceshipParts })
convertEncampmentData()
barbarians.setTransients(this) barbarians.setTransients(this)
cityDistances.game = this cityDistances.game = this

View File

@ -25,7 +25,7 @@ class BarbarianAutomation(val civInfo: Civilization) {
// 1 - Stay on current encampment // 1 - Stay on current encampment
if (unit.currentTile.improvement == Constants.barbarianEncampment) return if (unit.currentTile.improvement == Constants.barbarianEncampment) return
val campTiles = unit.civ.gameInfo.barbarians.camps.map { unit.civ.gameInfo.tileMap[it.key] } val campTiles = unit.civ.gameInfo.barbarians.encampments.map { unit.civ.gameInfo.tileMap[it.position] }
.sortedBy { unit.currentTile.aerialDistanceTo(it) } .sortedBy { unit.currentTile.aerialDistanceTo(it) }
val bestCamp = campTiles.firstOrNull { it.civilianUnit == null && unit.movement.canReach(it)} val bestCamp = campTiles.firstOrNull { it.civilianUnit == null && unit.movement.canReach(it)}
if (bestCamp != null) if (bestCamp != null)

View File

@ -7,8 +7,8 @@ import com.unciv.logic.GameInfo
import com.unciv.logic.IsPartOfGameInfoSerialization import com.unciv.logic.IsPartOfGameInfoSerialization
import com.unciv.logic.civilization.NotificationCategory import com.unciv.logic.civilization.NotificationCategory
import com.unciv.logic.civilization.NotificationIcon import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.map.tile.Tile
import com.unciv.logic.map.TileMap import com.unciv.logic.map.TileMap
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.components.extensions.randomWeighted import com.unciv.ui.components.extensions.randomWeighted
import java.util.* import java.util.*
@ -17,8 +17,12 @@ import kotlin.math.min
import kotlin.math.pow import kotlin.math.pow
class BarbarianManager : IsPartOfGameInfoSerialization { class BarbarianManager : IsPartOfGameInfoSerialization {
/** Deprecated */
@Deprecated("by 4.6.12 due to serialization containing exact class location - replaced by encampments")
val camps = HashMapVector2<Encampment>() val camps = HashMapVector2<Encampment>()
val encampments = ArrayList<Encampment>()
@Transient @Transient
lateinit var gameInfo: GameInfo lateinit var gameInfo: GameInfo
@ -27,8 +31,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
fun clone(): BarbarianManager { fun clone(): BarbarianManager {
val toReturn = BarbarianManager() val toReturn = BarbarianManager()
for (camp in camps.values.map { it.clone() }) toReturn.encampments.addAll(encampments.map { it.clone() })
toReturn.camps[camp.position] = camp
return toReturn return toReturn
} }
@ -37,44 +40,40 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
this.tileMap = gameInfo.tileMap this.tileMap = gameInfo.tileMap
// Add any preexisting camps as Encampment objects // Add any preexisting camps as Encampment objects
val existingEncampmentLocations = encampments.asSequence().map { it.position }.toHashSet()
for (tile in tileMap.values) { for (tile in tileMap.values) {
if (tile.improvement == Constants.barbarianEncampment if (tile.improvement == Constants.barbarianEncampment
&& camps[tile.position] == null) { && !existingEncampmentLocations.contains(tile.position)) {
val newCamp = Encampment(tile.position) encampments.add(Encampment(tile.position))
camps[newCamp.position] = newCamp
} }
} }
for (camp in camps.values) for (camp in encampments)
camp.gameInfo = gameInfo camp.gameInfo = gameInfo
} }
fun updateEncampments() { fun updateEncampments() {
// Check if camps were destroyed // Check if camps were destroyed
val positionsToRemove = ArrayList<Vector2>() for (encampment in encampments.toList()) { // tolist to avoid concurrent modification
for ((position, camp) in camps) { if (tileMap[encampment.position].improvement != Constants.barbarianEncampment) {
if (tileMap[position].improvement != Constants.barbarianEncampment) { encampment.wasDestroyed()
camp.wasDestroyed()
} }
// Check if the ghosts are ready to depart // Check if the ghosts are ready to depart
if (camp.destroyed && camp.countdown == 0) if (encampment.destroyed && encampment.countdown == 0)
positionsToRemove.add(position) encampments.remove(encampment)
} }
for (position in positionsToRemove)
camps.remove(position)
// Possibly place a new encampment // Possibly place a new encampment
placeBarbarianEncampment() placeBarbarianEncampment()
// Update all existing camps for (encampment in encampments) encampment.update()
for (camp in camps.values) {
camp.update()
}
} }
/** Called when an encampment was attacked, will speed up time to next spawn */ /** Called when an encampment was attacked, will speed up time to next spawn */
fun campAttacked(position: Vector2) { fun campAttacked(position: Vector2) {
camps[position]?.wasAttacked() encampments.firstOrNull { it.position == position }?.wasAttacked()
} }
fun placeBarbarianEncampment() { fun placeBarbarianEncampment() {
@ -90,7 +89,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
val fogTilesPerCamp = (tileMap.values.size.toFloat().pow(0.4f)).toInt() // Approximately val fogTilesPerCamp = (tileMap.values.size.toFloat().pow(0.4f)).toInt() // Approximately
// Check if we have more room // Check if we have more room
var campsToAdd = (fogTiles.size / fogTilesPerCamp) - camps.count { !it.value.destroyed } var campsToAdd = (fogTiles.size / fogTilesPerCamp) - encampments.count { !it.destroyed }
// First turn of the game add 1/3 of all possible camps // First turn of the game add 1/3 of all possible camps
if (gameInfo.turns == 1) { if (gameInfo.turns == 1) {
@ -104,9 +103,9 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
// Camps can't spawn within 7 tiles of each other or within 4 tiles of major civ capitals // Camps can't spawn within 7 tiles of each other or within 4 tiles of major civ capitals
val tooCloseToCapitals = gameInfo.civilizations.filterNot { it.isBarbarian() || it.isSpectator() || it.cities.isEmpty() || it.isCityState() || it.getCapital() == null } val tooCloseToCapitals = gameInfo.civilizations.filterNot { it.isBarbarian() || it.isSpectator() || it.cities.isEmpty() || it.isCityState() || it.getCapital() == null }
.flatMap { it.getCapital()!!.getCenterTile().getTilesInDistance(4) }.toSet() .flatMap { it.getCapital()!!.getCenterTile().getTilesInDistance(4) }.toSet()
val tooCloseToCamps = camps val tooCloseToCamps = encampments
.flatMap { tileMap[it.key].getTilesInDistance( .flatMap { tileMap[it.position].getTilesInDistance(
if (it.value.destroyed) 4 else 7 if (it.destroyed) 4 else 7
) }.toSet() ) }.toSet()
val viableTiles = fogTiles.filter { val viableTiles = fogTiles.filter {
@ -138,7 +137,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
tile.changeImprovement(Constants.barbarianEncampment) tile.changeImprovement(Constants.barbarianEncampment)
val newCamp = Encampment(tile.position) val newCamp = Encampment(tile.position)
newCamp.gameInfo = gameInfo newCamp.gameInfo = gameInfo
camps[newCamp.position] = newCamp encampments.add(newCamp)
notifyCivsOfBarbarianEncampment(tile) notifyCivsOfBarbarianEncampment(tile)
addedCamps++ addedCamps++