diff --git a/buildSrc/src/main/kotlin/BuildConfig.kt b/buildSrc/src/main/kotlin/BuildConfig.kt index 0ea86d45da..7c1bfbdf21 100644 --- a/buildSrc/src/main/kotlin/BuildConfig.kt +++ b/buildSrc/src/main/kotlin/BuildConfig.kt @@ -3,8 +3,8 @@ package com.unciv.build object BuildConfig { const val kotlinVersion = "1.3.71" const val appName = "Unciv" - const val appCodeNumber = 512 - const val appVersion = "3.12.2" + const val appCodeNumber = 513 + const val appVersion = "3.12.2-patch1" const val gdxVersion = "1.9.12" const val roboVMVersion = "2.3.1" diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index 5f6a8d8c4a..3839837cd1 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -22,21 +22,27 @@ import kotlin.collections.ArrayList class UncivShowableException(missingMods: String) : Exception(missingMods) class GameInfo { - @Transient lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn - @Transient lateinit var currentPlayerCiv:CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time + @Transient + lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn + @Transient + lateinit var currentPlayerCiv: CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time + /** This is used in multiplayer games, where I may have a saved game state on my phone * that is inconsistent with the saved game on the cloud */ - @Transient var isUpToDate=false - @Transient lateinit var ruleSet:Ruleset + @Transient + var isUpToDate = false + @Transient + lateinit var ruleSet: Ruleset var civilizations = mutableListOf() - var difficulty="Chieftain" // difficulty is game-wide, think what would happen if 2 human players could play on different difficulties? + var difficulty = "Chieftain" // difficulty is game-wide, think what would happen if 2 human players could play on different difficulties? var tileMap: TileMap = TileMap() - var gameParameters= GameParameters() + var gameParameters = GameParameters() var turns = 0 - var oneMoreTurnMode=false - var currentPlayer="" + var oneMoreTurnMode = false + var currentPlayer = "" var gameId = UUID.randomUUID().toString() // random string + @Volatile var customSaveLocation: String? = null @@ -53,9 +59,9 @@ class GameInfo { val toReturn = GameInfo() toReturn.tileMap = tileMap.clone() toReturn.civilizations.addAll(civilizations.map { it.clone() }) - toReturn.currentPlayer=currentPlayer + toReturn.currentPlayer = currentPlayer toReturn.turns = turns - toReturn.difficulty=difficulty + toReturn.difficulty = difficulty toReturn.gameParameters = gameParameters toReturn.gameId = gameId toReturn.oneMoreTurnMode = oneMoreTurnMode @@ -66,11 +72,11 @@ class GameInfo { fun getPlayerToViewAs(): CivilizationInfo { if (!gameParameters.isOnlineMultiplayer) return currentPlayerCiv // non-online, play as human player val userId = UncivGame.Current.settings.userId - if (civilizations.any { it.playerId == userId}) return civilizations.first { it.playerId == userId } + if (civilizations.any { it.playerId == userId }) return civilizations.first { it.playerId == userId } else return getBarbarianCivilization()// you aren't anyone. How did you even get this game? Can you spectate? } - fun getCivilization(civName:String) = civilizations.first { it.civName==civName } + fun getCivilization(civName: String) = civilizations.first { it.civName == civName } fun getCurrentPlayerCivilization() = currentPlayerCiv fun getBarbarianCivilization() = getCivilization(Constants.barbarians) fun getDifficulty() = difficultyObject @@ -85,10 +91,10 @@ class GameInfo { var currentPlayerIndex = civilizations.indexOf(thisPlayer) - fun switchTurn(){ + fun switchTurn() { thisPlayer.endTurn() - currentPlayerIndex = (currentPlayerIndex+1) % civilizations.size - if(currentPlayerIndex==0){ + currentPlayerIndex = (currentPlayerIndex + 1) % civilizations.size + if (currentPlayerIndex == 0) { turns++ } thisPlayer = civilizations[currentPlayerIndex] @@ -98,7 +104,7 @@ class GameInfo { switchTurn() while (thisPlayer.playerType == PlayerType.AI - || turns < UncivGame.Current.simulateUntilTurnForDebug + || turns < UncivGame.Current.simulateUntilTurnForDebug || turns < simulateMaxTurns && simulateUntilWin // For multiplayer, if there are 3+ players and one is defeated or spectator, // we'll want to skip over their turn @@ -160,8 +166,7 @@ class GameInfo { val unitName = tile.militaryUnit!!.name thisPlayer.addNotification("An enemy [$unitName] was spotted $inOrNear our territory", tile.position, Color.RED) } - } - else { + } else { val positions = tiles.map { it.position } thisPlayer.addNotification("[${positions.size}] enemy units were spotted $inOrNear our territory", Color.RED, LocationAction(positions)) } @@ -216,15 +221,15 @@ class GameInfo { val barbarianCiv = getBarbarianCivilization() barbarianCiv.tech.techsResearched = allResearchedTechs.toHashSet() val unitList = ruleSet.units.values - .filter { !it.unitType.isCivilian()} + .filter { !it.unitType.isCivilian() } .filter { it.isBuildable(barbarianCiv) } val landUnits = unitList.filter { it.unitType.isLandUnit() } val waterUnits = unitList.filter { it.unitType.isWaterUnit() } - val unit:String - if(waterUnits.isNotEmpty() && tileToPlace.isCoastalTile() && Random().nextBoolean()) - unit=waterUnits.random().name + val unit: String + if (waterUnits.isNotEmpty() && tileToPlace.isCoastalTile() && Random().nextBoolean()) + unit = waterUnits.random().name else unit = landUnits.random().name tileMap.placeUnitNearTile(tileToPlace.position, unit, getBarbarianCivilization()) @@ -235,8 +240,10 @@ class GameInfo { * adopted Honor policy and have explored the [tile] where the Barbarian Encampent has spawned. */ fun notifyCivsOfBarbarianEncampment(tile: TileInfo) { - civilizations.filter { it.hasUnique("Notified of new Barbarian encampments") - && it.exploredTiles.contains(tile.position) } + civilizations.filter { + it.hasUnique("Notified of new Barbarian encampments") + && it.exploredTiles.contains(tile.position) + } .forEach { it.addNotification("A new barbarian encampment has spawned!", tile.position, Color.RED) } } @@ -345,10 +352,10 @@ class GameInfo { cityConstructions.builtBuildings.remove(oldBuildingName) cityConstructions.builtBuildings.add(newBuildingName) } - cityConstructions.constructionQueue.replaceAll { if(it==oldBuildingName) newBuildingName else it } + cityConstructions.constructionQueue.replaceAll { if (it == oldBuildingName) newBuildingName else it } if (cityConstructions.inProgressConstructions.containsKey(oldBuildingName)) { cityConstructions.inProgressConstructions[newBuildingName] = cityConstructions.inProgressConstructions[oldBuildingName]!! cityConstructions.inProgressConstructions.remove(oldBuildingName) } } -} +} \ No newline at end of file diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index 971139982d..1c800aad5a 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -26,9 +26,7 @@ object GameStarter { gameInfo.tileMap = MapSaver.loadScenario(gameSetupInfo.mapParameters.name).tileMap else if (gameSetupInfo.mapParameters.name != "") { gameInfo.tileMap = MapSaver.loadMap(gameSetupInfo.mapFile!!) - } - - else gameInfo.tileMap = MapGenerator(ruleset).generateMap(gameSetupInfo.mapParameters) + } else gameInfo.tileMap = MapGenerator(ruleset).generateMap(gameSetupInfo.mapParameters) gameInfo.tileMap.mapParameters = gameSetupInfo.mapParameters gameInfo.tileMap.gameInfo = gameInfo // need to set this transient before placing units in the map @@ -75,7 +73,7 @@ object GameStarter { civInfo.tech.addTechnology(tech) // generic start with technology unique - for(unique in civInfo.getMatchingUniques("Starts with []")) { + for (unique in civInfo.getMatchingUniques("Starts with []")) { // get the parameter from the unique val techName = unique.params[0] @@ -106,7 +104,7 @@ object GameStarter { availableCivNames.removeAll(newGameParameters.players.map { it.chosenCiv }) availableCivNames.remove(Constants.barbarians) - if(!newGameParameters.noBarbarians && ruleset.nations.containsKey(Constants.barbarians)) { + if (!newGameParameters.noBarbarians && ruleset.nations.containsKey(Constants.barbarians)) { val barbarianCivilization = CivilizationInfo(Constants.barbarians) gameInfo.civilizations.add(barbarianCivilization) } @@ -138,7 +136,7 @@ object GameStarter { val civ = CivilizationInfo(cityStateName) civ.cityStatePersonality = CityStatePersonality.values().random() gameInfo.civilizations.add(civ) - for(tech in ruleset.technologies.values.filter { it.uniques.contains("Starting tech") }) + for (tech in ruleset.technologies.values.filter { it.uniques.contains("Starting tech") }) civ.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet } } @@ -168,13 +166,14 @@ object GameStarter { fun placeNearStartingPosition(unitName: String) { civ.placeUnitNearTile(startingLocation.position, unitName) } + val warriorEquivalent = getWarriorEquivalent(civ) val startingUnits = when { civ.isPlayerCivilization() -> gameInfo.getDifficulty().startingUnits civ.isMajorCiv() -> gameInfo.getDifficulty().aiMajorCivStartingUnits else -> gameInfo.getDifficulty().aiCityStateStartingUnits } - + for (unit in startingUnits) { val unitToAdd = if (unit == "Warrior") warriorEquivalent else unit if (unitToAdd != null) placeNearStartingPosition(unitToAdd) @@ -185,7 +184,7 @@ object GameStarter { private fun getStartingLocations(civs: List, tileMap: TileMap): HashMap { var landTiles = tileMap.values // Games starting on snow might as well start over... - .filter { it.isLand && !it.isImpassible() && it.baseTerrain!=Constants.snow } + .filter { it.isLand && !it.isImpassible() && it.baseTerrain != Constants.snow } val landTilesInBigEnoughGroup = ArrayList() while (landTiles.any()) { diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index d06fda5d37..5f17377b9b 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -32,12 +32,18 @@ import kotlin.math.min import kotlin.math.roundToInt class CityInfo { - @Transient lateinit var civInfo: CivilizationInfo - @Transient lateinit private var centerTileInfo:TileInfo // cached for better performance - @Transient val range = 2 - @Transient lateinit var tileMap: TileMap - @Transient lateinit var tilesInRange:HashSet - @Transient var hasJustBeenConquered = false // this is so that military units can enter the city, even before we decide what to do with it + @Transient + lateinit var civInfo: CivilizationInfo + @Transient + lateinit private var centerTileInfo: TileInfo // cached for better performance + @Transient + val range = 2 + @Transient + lateinit var tileMap: TileMap + @Transient + lateinit var tilesInRange: HashSet + @Transient + var hasJustBeenConquered = false // this is so that military units can enter the city, even before we decide what to do with it var location: Vector2 = Vector2.Zero var id: String = UUID.randomUUID().toString() @@ -55,14 +61,17 @@ class CityInfo { /** All tiles that this city controls */ var tiles = HashSet() + /** Tiles that have population assigned to them */ var workedTiles = HashSet() + /** Tiles that the population in them won't be reassigned */ var lockedTiles = HashSet() var isBeingRazed = false var attackedThisTurn = false var hasSoldBuildingThisTurn = false var isPuppet = false + /** The very first found city is the _original_ capital, * while the _current_ capital can be any other city after the original one is captured. * It is important to distinct them since the original cannot be razed and defines the Domination Victory. */ @@ -91,7 +100,7 @@ class CityInfo { for (unique in civInfo.getMatchingUniques("Gain a free [] []")) { val freeBuildingName = unique.params[0] val cityFilter = unique.params[1] - if (cityFilter == "in every city" || (cityFilter == "in every coastal city" && getCenterTile().isCoastalTile()) ) { + if (cityFilter == "in every city" || (cityFilter == "in every coastal city" && getCenterTile().isCoastalTile())) { if (!cityConstructions.isBuilt(freeBuildingName)) cityConstructions.addBuilding(freeBuildingName) } @@ -154,7 +163,6 @@ class CityInfo { } - fun getCenterTile(): TileInfo = centerTileInfo fun getTiles(): Sequence = tiles.asSequence().map { tileMap[it] } fun getWorkableTiles() = tilesInRange.asSequence().filter { it.getOwner() == civInfo } @@ -163,10 +171,11 @@ class CityInfo { fun isCapital(): Boolean = cityConstructions.builtBuildings.contains(capitalCityIndicator()) fun capitalCityIndicator(): String = getRuleset().buildings.values.first { it.uniques.contains("Indicates the capital city") }.name - fun isConnectedToCapital(connectionTypePredicate: (Set) -> Boolean = {true}): Boolean { + fun isConnectedToCapital(connectionTypePredicate: (Set) -> Boolean = { true }): Boolean { val mediumTypes = civInfo.citiesConnectedToCapitalToMediums[this] ?: return false return connectionTypePredicate(mediumTypes) } + fun isInResistance() = resistanceCounter > 0 @@ -193,10 +202,11 @@ class CityInfo { val resource = getRuleset().tileResources[building.requiredResource]!! cityResources.add(resource, -1, "Buildings") } - for(unique in cityConstructions.builtBuildingUniqueMap.getUniques("Provides [] []")) { // E.G "Provides [1] [Iron]" + for (unique in cityConstructions.builtBuildingUniqueMap.getUniques("Provides [] []")) { // E.G "Provides [1] [Iron]" val resource = getRuleset().tileResources[unique.params[1]] - if(resource!=null){ - cityResources.add(resource, unique.params[0].toInt() * civInfo.getResourceModifier(resource), "Tiles") } + if (resource != null) { + cityResources.add(resource, unique.params[0].toInt() * civInfo.getResourceModifier(resource), "Tiles") + } } return cityResources @@ -205,17 +215,17 @@ class CityInfo { fun getTileResourceAmount(tileInfo: TileInfo): Int { if (tileInfo.resource == null) return 0 val resource = tileInfo.getTileResource() - if (resource.revealedBy!=null && !civInfo.tech.isResearched(resource.revealedBy!!)) return 0 + if (resource.revealedBy != null && !civInfo.tech.isResearched(resource.revealedBy!!)) return 0 // Even if the improvement exists (we conquered an enemy city or somesuch) or we have a city on it, we won't get the resource until the correct tech is researched - if (resource.improvement!=null) { + if (resource.improvement != null) { val improvement = getRuleset().tileImprovements[resource.improvement!!]!! if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!)) return 0 } if (resource.improvement == tileInfo.improvement || tileInfo.isCityCenter() // Per https://gaming.stackexchange.com/questions/53155/do-manufactories-and-customs-houses-sacrifice-the-strategic-or-luxury-resources - || (resource.resourceType==ResourceType.Strategic && tileInfo.containsGreatImprovement())) { + || (resource.resourceType == ResourceType.Strategic && tileInfo.containsGreatImprovement())) { var amountToAdd = 1 if (resource.resourceType == ResourceType.Strategic) { amountToAdd = 2 @@ -240,7 +250,7 @@ class CityInfo { if (!isGrowing()) return null val roundedFoodPerTurn = foodForNextTurn().toFloat() val remainingFood = population.getFoodToNextPopulation() - population.foodStored - var turnsToGrowth = ceil( remainingFood / roundedFoodPerTurn).toInt() + var turnsToGrowth = ceil(remainingFood / roundedFoodPerTurn).toInt() if (turnsToGrowth < 1) turnsToGrowth = 1 return turnsToGrowth } @@ -251,11 +261,11 @@ class CityInfo { return population.foodStored / -foodForNextTurn() + 1 } - fun containsBuildingUnique(unique:String) = cityConstructions.getBuiltBuildings().any { it.uniques.contains(unique) } + fun containsBuildingUnique(unique: String) = cityConstructions.getBuiltBuildings().any { it.uniques.contains(unique) } - fun getGreatPersonMap():StatMap { + fun getGreatPersonMap(): StatMap { val stats = StatMap() - for((specialist, amount) in population.getNewSpecialists()) + for ((specialist, amount) in population.getNewSpecialists()) if (getRuleset().specialists.containsKey(specialist)) // To solve problems in total remake mods stats.add("Specialists", getRuleset().specialists[specialist]!!.greatPersonPoints.times(amount)) @@ -275,7 +285,7 @@ class CityInfo { val statName = greatUnitUnique.getPlaceholderParameters()[0] val stat = Stat.values().firstOrNull { it.name == statName } // this is not very efficient, and if it causes problems we can try and think of a way of improving it - if (stat != null) entry.value.add(stat, entry.value.get(stat) * unique.params[1].toFloat()/100) + if (stat != null) entry.value.add(stat, entry.value.get(stat) * unique.params[1].toFloat() / 100) } for (unique in civInfo.getMatchingUniques("+[]% great person generation in all cities") @@ -297,7 +307,9 @@ class CityInfo { return 200 + cityConstructions.getBuiltBuildings().sumBy { it.cityHealth } } - override fun toString(): String {return name} // for debug + override fun toString(): String { + return name + } // for debug //endregion //region state-changing functions @@ -313,7 +325,7 @@ class CityInfo { cityConstructions.setTransients() } - fun startTurn(){ + fun startTurn() { // Construct units at the beginning of the turn, // so they won't be generated out in the open and vulnerable to enemy attacks before you can control them cityConstructions.constructIfEnough() @@ -439,7 +451,7 @@ class CityInfo { // How can you conquer a city but not know the civ you conquered it from?! // I don't know either, but some of our players have managed this, and crashed their game! - if(!conqueringCiv.knows(oldCiv)) + if (!conqueringCiv.knows(oldCiv)) conqueringCiv.meetCivilization(oldCiv) oldCiv.getDiplomacyManager(conqueringCiv) @@ -498,10 +510,10 @@ class CityInfo { val respecForLiberatingOurCity = 10f + percentageOfCivPopulationInThatCity.roundToInt() // In order to get "plus points" in Diplomacy, you have to establish diplomatic relations if you haven't yet - if(!conqueringCiv.knows(foundingCiv)) + if (!conqueringCiv.knows(foundingCiv)) conqueringCiv.meetCivilization(foundingCiv) - if(foundingCiv.isMajorCiv()) { + if (foundingCiv.isMajorCiv()) { foundingCiv.getDiplomacyManager(conqueringCiv) .addModifier(DiplomaticModifiers.CapturedOurCities, respecForLiberatingOurCity) } else { @@ -570,23 +582,21 @@ class CityInfo { tryUpdateRoadStatus() } - private fun tryUpdateRoadStatus(){ - if(getCenterTile().roadStatus==RoadStatus.None){ + private fun tryUpdateRoadStatus() { + if (getCenterTile().roadStatus == RoadStatus.None) { val roadImprovement = getRuleset().tileImprovements["Road"] - if(roadImprovement!=null && roadImprovement.techRequired in civInfo.tech.techsResearched) - getCenterTile().roadStatus=RoadStatus.Road - } - - else if (getCenterTile().roadStatus != RoadStatus.Railroad) { + if (roadImprovement != null && roadImprovement.techRequired in civInfo.tech.techsResearched) + getCenterTile().roadStatus = RoadStatus.Road + } else if (getCenterTile().roadStatus != RoadStatus.Railroad) { val railroadImprovement = getRuleset().tileImprovements["Railroad"] if (railroadImprovement != null && railroadImprovement.techRequired in civInfo.tech.techsResearched) getCenterTile().roadStatus = RoadStatus.Railroad } } - fun getGoldForSellingBuilding(buildingName:String) = getRuleset().buildings[buildingName]!!.cost / 10 + fun getGoldForSellingBuilding(buildingName: String) = getRuleset().buildings[buildingName]!!.cost / 10 - fun sellBuilding(buildingName:String) { + fun sellBuilding(buildingName: String) { cityConstructions.removeBuilding(buildingName) civInfo.gold += getGoldForSellingBuilding(buildingName) hasSoldBuildingThisTurn = true @@ -617,19 +627,18 @@ class CityInfo { But if they don't keep their promise they get a -20 that will only fully disappear in 160 turns. There's a lot of triggering going on here. */ - private fun triggerCitiesSettledNearOtherCiv(){ - val citiesWithin6Tiles = civInfo.gameInfo.civilizations.filter { it.isMajorCiv() && it!=civInfo } + private fun triggerCitiesSettledNearOtherCiv() { + val citiesWithin6Tiles = civInfo.gameInfo.civilizations.filter { it.isMajorCiv() && it != civInfo } .flatMap { it.cities } .filter { it.getCenterTile().aerialDistanceTo(getCenterTile()) <= 6 } val civsWithCloseCities = citiesWithin6Tiles.map { it.civInfo }.distinct() .filter { it.knows(civInfo) && it.exploredTiles.contains(location) } - for(otherCiv in civsWithCloseCities) - otherCiv.getDiplomacyManager(civInfo).setFlag(DiplomacyFlags.SettledCitiesNearUs,30) + for (otherCiv in civsWithCloseCities) + otherCiv.getDiplomacyManager(civInfo).setFlag(DiplomacyFlags.SettledCitiesNearUs, 30) } - fun canPurchase(construction : IConstruction) : Boolean { - if (construction is BaseUnit) - { + fun canPurchase(construction: IConstruction): Boolean { + if (construction is BaseUnit) { val tile = getCenterTile() if (construction.unitType.isCivilian()) return tile.civilianUnit == null @@ -640,4 +649,4 @@ class CityInfo { return true } //endregion -} +} \ No newline at end of file diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 7383b0484b..c0b9e67210 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -32,28 +32,40 @@ import kotlin.math.roundToInt class CivilizationInfo { - @Transient lateinit var gameInfo: GameInfo - @Transient lateinit var nation:Nation + @Transient + lateinit var gameInfo: GameInfo + @Transient + lateinit var nation: Nation + /** * We never add or remove from here directly, could cause comodification problems. * Instead, we create a copy list with the change, and replace this list. * The other solution, casting toList() every "get", has a performance cost */ - @Transient private var units = listOf() - @Transient var viewableTiles = setOf() - @Transient var viewableInvisibleUnitsTiles = setOf() + @Transient + private var units = listOf() + @Transient + var viewableTiles = setOf() + @Transient + var viewableInvisibleUnitsTiles = setOf() /** Contains mapping of cities to travel mediums from ALL civilizations connected by trade routes to the capital */ - @Transient var citiesConnectedToCapitalToMediums = mapOf>() + @Transient + var citiesConnectedToCapitalToMediums = mapOf>() /** This is for performance since every movement calculation depends on this, see MapUnit comment */ - @Transient var hasActiveGreatWall = false - @Transient var statsForNextTurn = Stats() - @Transient var happinessForNextTurn = 0 - @Transient var detailedCivResources = ResourceSupplyList() + @Transient + var hasActiveGreatWall = false + @Transient + var statsForNextTurn = Stats() + @Transient + var happinessForNextTurn = 0 + @Transient + var detailedCivResources = ResourceSupplyList() var playerType = PlayerType.AI - /** Used in online multiplayer for human players */ var playerId = "" + /** Used in online multiplayer for human players */ + var playerId = "" var gold = 0 var civName = "" var tech = TechManager() @@ -61,7 +73,7 @@ class CivilizationInfo { var questManager = QuestManager() var goldenAges = GoldenAgeManager() var greatPeople = GreatPersonManager() - var victoryManager=VictoryManager() + var victoryManager = VictoryManager() var diplomacy = HashMap() var notifications = ArrayList() val popupAlerts = ArrayList() @@ -115,24 +127,27 @@ class CivilizationInfo { } //region pure functions - fun getDifficulty():Difficulty { + fun getDifficulty(): Difficulty { if (isPlayerCivilization()) return gameInfo.getDifficulty() return gameInfo.ruleSet.difficulties["Chieftain"]!! } + fun getDiplomacyManager(civInfo: CivilizationInfo) = getDiplomacyManager(civInfo.civName) fun getDiplomacyManager(civName: String) = diplomacy[civName]!! + /** Returns only undefeated civs, aka the ones we care about */ fun getKnownCivs() = diplomacy.values.map { it.otherCiv() }.filter { !it.isDefeated() } fun knows(otherCivName: String) = diplomacy.containsKey(otherCivName) fun knows(otherCiv: CivilizationInfo) = knows(otherCiv.civName) - fun getCapital()= cities.first { it.isCapital() } - fun isPlayerCivilization() = playerType==PlayerType.Human + fun getCapital() = cities.first { it.isCapital() } + fun isPlayerCivilization() = playerType == PlayerType.Human fun isOneCityChallenger() = ( - playerType==PlayerType.Human && - gameInfo.gameParameters.oneCityChallenge) - fun isCurrentPlayer() = gameInfo.getCurrentPlayerCivilization()==this - fun isBarbarian() = nation.isBarbarian() + playerType == PlayerType.Human && + gameInfo.gameParameters.oneCityChallenge) + + fun isCurrentPlayer() = gameInfo.getCurrentPlayerCivilization() == this + fun isBarbarian() = nation.isBarbarian() fun isSpectator() = nation.isSpectator() fun isCityState(): Boolean = nation.isCityState() val cityStateType: CityStateType get() = nation.cityStateType!! @@ -144,10 +159,10 @@ class CivilizationInfo { fun getCivTerritory() = cities.asSequence().flatMap { it.tiles.asSequence() } fun victoryType(): VictoryType { - if(gameInfo.gameParameters.victoryTypes.size==1) + if (gameInfo.gameParameters.victoryTypes.size == 1) return gameInfo.gameParameters.victoryTypes.first() // That is the most relevant one val victoryType = nation.preferredVictoryType - if(gameInfo.gameParameters.victoryTypes.contains(victoryType)) return victoryType + if (gameInfo.gameParameters.victoryTypes.contains(victoryType)) return victoryType else return VictoryType.Neutral } @@ -163,9 +178,9 @@ class CivilizationInfo { fun getCivResources(): ResourceSupplyList { - val newResourceSupplyList=ResourceSupplyList() - for(resourceSupply in detailedCivResources) - newResourceSupplyList.add(resourceSupply.resource,resourceSupply.amount,"All") + val newResourceSupplyList = ResourceSupplyList() + for (resourceSupply in detailedCivResources) + newResourceSupplyList.add(resourceSupply.resource, resourceSupply.amount, "All") return newResourceSupplyList } @@ -179,10 +194,10 @@ class CivilizationInfo { /** * Returns a dictionary of ALL resource names, and the amount that the civ has of each */ - fun getCivResourcesByName():HashMap { - val hashMap = HashMap(gameInfo.ruleSet.tileResources.size) - for(resource in gameInfo.ruleSet.tileResources.keys) hashMap[resource]=0 - for(entry in getCivResources()) + fun getCivResourcesByName(): HashMap { + val hashMap = HashMap(gameInfo.ruleSet.tileResources.size) + for (resource in gameInfo.ruleSet.tileResources.keys) hashMap[resource] = 0 + for (entry in getCivResources()) hashMap[entry.resource.name] = entry.amount return hashMap } @@ -199,11 +214,11 @@ class CivilizationInfo { return resourceModifier } - fun hasResource(resourceName:String): Boolean = getCivResourcesByName()[resourceName]!!>0 + fun hasResource(resourceName: String): Boolean = getCivResourcesByName()[resourceName]!! > 0 fun getBuildingUniques(): Sequence = cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getAllUniques() } - fun hasUnique(unique:String) = getMatchingUniques(unique).any() + fun hasUnique(unique: String) = getMatchingUniques(unique).any() fun getMatchingUniques(uniqueTemplate: String): Sequence { return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } + @@ -215,12 +230,12 @@ class CivilizationInfo { fun getCivUnits(): Sequence = units.asSequence() fun getCivGreatPeople(): Sequence = getCivUnits().filter { mapUnit -> mapUnit.hasUnique("Great Person - []") } - fun addUnit(mapUnit: MapUnit, updateCivInfo:Boolean=true){ + fun addUnit(mapUnit: MapUnit, updateCivInfo: Boolean = true) { val newList = ArrayList(units) newList.add(mapUnit) - units=newList + units = newList - if(updateCivInfo) { + if (updateCivInfo) { // Not relevant when updating tileinfo transients, since some info of the civ itself isn't yet available, // and in any case it'll be updated once civ info transients are updateStatsForNextTurn() // unit upkeep @@ -244,7 +259,7 @@ class CivilizationInfo { fun getNextDueUnit(): MapUnit? { val dueUnits = getDueUnits() - if(dueUnits.any()) { + if (dueUnits.any()) { val unit = dueUnits.first() unit.due = false return unit @@ -260,17 +275,16 @@ class CivilizationInfo { } - - fun getEquivalentBuilding(buildingName:String): Building { + fun getEquivalentBuilding(buildingName: String): Building { val baseBuilding = gameInfo.ruleSet.buildings[buildingName]!!.getBaseBuilding(gameInfo.ruleSet) - for(building in gameInfo.ruleSet.buildings.values) - if(building.replaces==baseBuilding.name && building.uniqueTo==civName) + for (building in gameInfo.ruleSet.buildings.values) + if (building.replaces == baseBuilding.name && building.uniqueTo == civName) return building return baseBuilding } - fun getEquivalentUnit(baseUnitName:String):BaseUnit { + fun getEquivalentUnit(baseUnitName: String): BaseUnit { for (unit in gameInfo.ruleSet.units.values) if (unit.replaces == baseUnitName && unit.uniqueTo == civName) return unit @@ -283,22 +297,23 @@ class CivilizationInfo { diplomacy[otherCiv.civName] = DiplomacyManager(this, otherCiv.civName) .apply { diplomaticStatus = DiplomaticStatus.Peace } - otherCiv.popupAlerts.add(PopupAlert(AlertType.FirstContact,civName)) + otherCiv.popupAlerts.add(PopupAlert(AlertType.FirstContact, civName)) otherCiv.diplomacy[civName] = DiplomacyManager(otherCiv, civName) .apply { diplomaticStatus = DiplomaticStatus.Peace } - popupAlerts.add(PopupAlert(AlertType.FirstContact,otherCiv.civName)) + popupAlerts.add(PopupAlert(AlertType.FirstContact, otherCiv.civName)) - if(isCurrentPlayer() || otherCiv.isCurrentPlayer()) + if (isCurrentPlayer() || otherCiv.isCurrentPlayer()) UncivGame.Current.settings.addCompletedTutorialTask("Meet another civilization") } - fun discoverNaturalWonder(naturalWonderName: String) - { + fun discoverNaturalWonder(naturalWonderName: String) { naturalWonders.add(naturalWonderName) } - override fun toString(): String {return civName} // for debug + override fun toString(): String { + return civName + } // for debug /** Returns true if the civ was fully initialized and has no cities remaining */ fun isDefeated(): Boolean { @@ -314,9 +329,9 @@ class CivilizationInfo { fun getEra(): String { // For scenarios with no techs if (gameInfo.ruleSet.technologies.isEmpty()) return "None" - if(tech.researchedTechnologies.isEmpty()) + if (tech.researchedTechnologies.isEmpty()) return gameInfo.ruleSet.getEras().first() - val maxEraOfTech = tech.researchedTechnologies + val maxEraOfTech = tech.researchedTechnologies .asSequence() .map { it.column!! } .maxBy { it.columnNumber }!! @@ -328,7 +343,7 @@ class CivilizationInfo { return gameInfo.ruleSet.getEraNumber(getEra()) } - fun isAtWarWith(otherCiv:CivilizationInfo): Boolean { + fun isAtWarWith(otherCiv: CivilizationInfo): Boolean { if (otherCiv.civName == civName) return false // never at war with itself if (otherCiv.isBarbarian() || isBarbarian()) return true val diplomacyManager = diplomacy[otherCiv.civName] @@ -336,7 +351,7 @@ class CivilizationInfo { return diplomacyManager.diplomaticStatus == DiplomaticStatus.War } - fun isAtWar() = diplomacy.values.any { it.diplomaticStatus== DiplomaticStatus.War && !it.otherCiv().isDefeated() } + fun isAtWar() = diplomacy.values.any { it.diplomaticStatus == DiplomaticStatus.War && !it.otherCiv().isDefeated() } fun getLeaderDisplayName(): String { var leaderName = nation.getLeaderDisplayName().tr() @@ -349,10 +364,10 @@ class CivilizationInfo { } fun canSignResearchAgreement(): Boolean { - if(!isMajorCiv()) return false - if(!tech.getTechUniques().contains("Enables Research agreements")) return false + if (!isMajorCiv()) return false + if (!tech.getTechUniques().contains("Enables Research agreements")) return false if (gameInfo.ruleSet.technologies.values - .none { tech.canBeResearched(it.name) && !tech.isResearched(it.name) }) return false + .none { tech.canBeResearched(it.name) && !tech.isResearched(it.name) }) return false return true } @@ -366,8 +381,8 @@ class CivilizationInfo { && gold >= cost && otherCiv.gold >= cost } - fun getStatForRanking(category: RankingType) : Int { - return when(category) { + fun getStatForRanking(category: RankingType): Int { + return when (category) { RankingType.Population -> cities.sumBy { it.population.population } RankingType.CropYield -> statsForNextTurn.food.roundToInt() RankingType.Production -> statsForNextTurn.production.roundToInt() @@ -388,7 +403,7 @@ class CivilizationInfo { * and the updateVisibleTiles tries to meet civs... * And if they civs on't yet know who they are then they don;t know if they're barbarians =\ * */ - fun setNationTransient(){ + fun setNationTransient() { nation = gameInfo.ruleSet.nations[civName] ?: throw java.lang.Exception("Nation $civName is not found!") } @@ -397,25 +412,25 @@ class CivilizationInfo { goldenAges.civInfo = this policies.civInfo = this - if(policies.adoptedPolicies.size>0 && policies.numberOfAdoptedPolicies == 0) + if (policies.adoptedPolicies.size > 0 && policies.numberOfAdoptedPolicies == 0) policies.numberOfAdoptedPolicies = policies.adoptedPolicies.count { !it.endsWith("Complete") } policies.setTransients() questManager.civInfo = this questManager.setTransients() - if(citiesCreated==0 && cities.any()) + if (citiesCreated == 0 && cities.any()) citiesCreated = cities.filter { it.name in nation.cities }.count() tech.civInfo = this tech.setTransients() for (diplomacyManager in diplomacy.values) { - diplomacyManager.civInfo=this + diplomacyManager.civInfo = this diplomacyManager.updateHasOpenBorders() } - victoryManager.civInfo=this + victoryManager.civInfo = this for (cityInfo in cities) { cityInfo.civInfo = this // must be before the city's setTransients because it depends on the tilemap, that comes from the currentPlayerCivInfo @@ -452,9 +467,9 @@ class CivilizationInfo { for (unit in getCivUnits()) unit.startTurn() - for(tradeRequest in tradeRequests.toList()) { // remove trade requests where one of the sides can no longer supply + for (tradeRequest in tradeRequests.toList()) { // remove trade requests where one of the sides can no longer supply val offeringCiv = gameInfo.getCivilization(tradeRequest.requestingCiv) - if (offeringCiv.isDefeated() || !TradeEvaluation().isTradeValid(tradeRequest.trade,this, offeringCiv)) { + if (offeringCiv.isDefeated() || !TradeEvaluation().isTradeValid(tradeRequest.trade, this, offeringCiv)) { tradeRequests.remove(tradeRequest) // Yes, this is the right direction. I checked. offeringCiv.addNotification("Our proposed trade is no longer relevant!", Color.GOLD) @@ -512,7 +527,7 @@ class CivilizationInfo { } fun canEnterTiles(otherCiv: CivilizationInfo): Boolean { - if (otherCiv==this) return true + if (otherCiv == this) return true if (otherCiv.isBarbarian()) return true if (nation.isBarbarian() && gameInfo.turns >= gameInfo.difficultyObject.turnBarbariansCanEnterPlayerTiles) return true @@ -526,12 +541,12 @@ class CivilizationInfo { addNotification(text, color, LocationAction(locations)) } - fun addNotification(text: String, color: Color, action: NotificationAction?=null) { + fun addNotification(text: String, color: Color, action: NotificationAction? = null) { if (playerType == PlayerType.AI) return // no point in lengthening the saved game info if no one will read it notifications.add(Notification(text, color, action)) } - fun addUnit(unitName:String, city: CityInfo?=null) { + fun addUnit(unitName: String, city: CityInfo? = null) { if (cities.isEmpty()) return val cityToAddTo = city ?: cities.random() if (!gameInfo.ruleSet.units.containsKey(unitName)) return @@ -551,32 +566,32 @@ class CivilizationInfo { } - fun destroy(){ - val destructionText = if(isMajorCiv()) "The civilization of [$civName] has been destroyed!" + fun destroy() { + val destructionText = if (isMajorCiv()) "The civilization of [$civName] has been destroyed!" else "The City-State of [$civName] has been destroyed!" - for(civ in gameInfo.civilizations) + for (civ in gameInfo.civilizations) civ.addNotification(destructionText, null, Color.RED) getCivUnits().forEach { it.destroy() } tradeRequests.clear() // if we don't do this then there could be resources taken by "pending" trades forever - for(diplomacyManager in diplomacy.values){ + for (diplomacyManager in diplomacy.values) { diplomacyManager.trades.clear() diplomacyManager.otherCiv().getDiplomacyManager(this).trades.clear() - for(tradeRequest in diplomacyManager.otherCiv().tradeRequests.filter { it.requestingCiv==civName }) + for (tradeRequest in diplomacyManager.otherCiv().tradeRequests.filter { it.requestingCiv == civName }) diplomacyManager.otherCiv().tradeRequests.remove(tradeRequest) // it would be really weird to get a trade request from a dead civ } } fun giveGoldGift(otherCiv: CivilizationInfo, giftAmount: Int) { - if(!otherCiv.isCityState()) throw Exception("You can only gain influence with City-States!") + if (!otherCiv.isCityState()) throw Exception("You can only gain influence with City-States!") gold -= giftAmount - otherCiv.getDiplomacyManager(this).influence += giftAmount/10 + otherCiv.getDiplomacyManager(this).influence += giftAmount / 10 otherCiv.updateAllyCivForCityState() updateStatsForNextTurn() } fun getResearchAgreementCost(otherCiv: CivilizationInfo): Int { // https://forums.civfanatics.com/resources/research-agreements-bnw.25568/ - val basicGoldCostOfSignResearchAgreement = when(getEra()){ + val basicGoldCostOfSignResearchAgreement = when (getEra()) { Constants.medievalEra, Constants.renaissanceEra -> 250 Constants.industrialEra -> 300 Constants.modernEra -> 350 @@ -601,7 +616,7 @@ class CivilizationInfo { var newAllyName = "" if (!isCityState()) return val maxInfluence = diplomacy - .filter{ !it.value.otherCiv().isCityState() && !it.value.otherCiv().isDefeated() } + .filter { !it.value.otherCiv().isCityState() && !it.value.otherCiv().isDefeated() } .maxBy { it.value.influence } if (maxInfluence != null && maxInfluence.value.influence >= 60) { newAllyName = maxInfluence.key @@ -613,7 +628,7 @@ class CivilizationInfo { // If the city-state is captured by a civ, it stops being the ally of the civ it was previously an ally of. // This means that it will NOT HAVE a capital at that time, so if we run getCapital we'll get a crash! - val capitalLocation = if(cities.isNotEmpty()) getCapital().location else null + val capitalLocation = if (cities.isNotEmpty()) getCapital().location else null if (newAllyName != "") { val newAllyCiv = gameInfo.getCivilization(newAllyName) @@ -631,4 +646,4 @@ class CivilizationInfo { } //endregion -} +} \ No newline at end of file diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index da56295920..f9a640f1a8 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -14,15 +14,22 @@ import com.unciv.ui.utils.Fonts import kotlin.math.abs open class TileInfo { - @Transient lateinit var tileMap: TileMap - @Transient lateinit var ruleset: Ruleset // a tile can be a tile with a ruleset, even without a map. - @Transient var owningCity:CityInfo?=null - @Transient private lateinit var baseTerrainObject:Terrain + @Transient + lateinit var tileMap: TileMap + @Transient + lateinit var ruleset: Ruleset // a tile can be a tile with a ruleset, even without a map. + @Transient + var owningCity: CityInfo? = null + @Transient + private lateinit var baseTerrainObject: Terrain // These are for performance - checked with every tile movement and "canEnter" check, which makes them performance-critical - @Transient var isLand = false - @Transient var isWater = false - @Transient var isOcean = false + @Transient + var isLand = false + @Transient + var isWater = false + @Transient + var isOcean = false // This will be called often - farm can be built on Hill and tundra if adjacent to fresh water // and farms on adjacent to fresh water tiles will have +1 additional Food after researching Civil Service @@ -80,7 +87,7 @@ open class TileInfo { } fun containsUnfinishedGreatImprovement(): Boolean { - if(improvementInProgress==null) return false + if (improvementInProgress == null) return false return ruleset.tileImprovements[improvementInProgress!!]!!.isGreatImprovement() } @@ -298,7 +305,7 @@ open class TileInfo { /** Without regards to what civinfo it is, a lot of the checks are just for the improvement on the tile. * Doubles as a check for the map editor. */ - fun canImprovementBeBuiltHere(improvement: TileImprovement, resourceIsVisible:Boolean = resource!=null): Boolean { + fun canImprovementBeBuiltHere(improvement: TileImprovement, resourceIsVisible: Boolean = resource != null): Boolean { val topTerrain = getLastTerrain() return when { @@ -325,7 +332,7 @@ open class TileInfo { } } - fun matchesUniqueFilter(filter:String): Boolean { + fun matchesUniqueFilter(filter: String): Boolean { return filter == baseTerrain || filter == Constants.hill && isHill() || filter == "River" && isAdjacentToRiver() @@ -382,8 +389,8 @@ open class TileInfo { } /** The two tiles have a river between them */ - fun isConnectedByRiver(otherTile:TileInfo): Boolean { - if(otherTile==this) throw Exception("Should not be called to compare to self!") + fun isConnectedByRiver(otherTile: TileInfo): Boolean { + if (otherTile == this) throw Exception("Should not be called to compare to self!") val xDifference = this.position.x - otherTile.position.x val yDifference = this.position.y - otherTile.position.y @@ -496,4 +503,4 @@ open class TileInfo { && (terrainFeature == Constants.jungle || terrainFeature == Constants.forest) && isFriendlyTerritory(civInfo) //endregion -} +} \ No newline at end of file diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index f4bac9a85b..8a409b8ae5 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -12,13 +12,20 @@ import kotlin.math.abs class TileMap { - @Transient lateinit var gameInfo: GameInfo - @Transient var tileMatrix = ArrayList>() // this works several times faster than a hashmap, the performance difference is really astounding - @Transient var leftX = 0 - @Transient var bottomY = 0 - @delegate:Transient val maxLatitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.latitude) }.max()!! } - @delegate:Transient val maxLongitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.longitude) }.max()!! } - @delegate:Transient val naturalWonders: List by lazy { tileList.asSequence().filter { it.isNaturalWonder() }.map { it.naturalWonder!! }.distinct().toList() } + @Transient + lateinit var gameInfo: GameInfo + @Transient + var tileMatrix = ArrayList>() // this works several times faster than a hashmap, the performance difference is really astounding + @Transient + var leftX = 0 + @Transient + var bottomY = 0 + @delegate:Transient + val maxLatitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.latitude) }.max()!! } + @delegate:Transient + val maxLongitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.longitude) }.max()!! } + @delegate:Transient + val naturalWonders: List by lazy { tileList.asSequence().filter { it.isNaturalWonder() }.map { it.naturalWonder!! }.distinct().toList() } var mapParameters = MapParameters() @@ -31,19 +38,20 @@ class TileMap { constructor() /** generates an hexagonal map of given radius */ - constructor(radius:Int, ruleset: Ruleset){ - for(vector in HexMath.getVectorsInDistance(Vector2.Zero, radius)) + constructor(radius: Int, ruleset: Ruleset) { + for (vector in HexMath.getVectorsInDistance(Vector2.Zero, radius)) tileList.add(TileInfo().apply { position = vector; baseTerrain = Constants.grassland }) setTransients(ruleset) } /** generates a rectangular map of given width and height*/ constructor(width: Int, height: Int, ruleset: Ruleset) { - for(x in -width/2..width/2) - for (y in -height/2..height/2) + for (x in -width / 2..width / 2) + for (y in -height / 2..height / 2) tileList.add(TileInfo().apply { - position = HexMath.evenQ2HexCoords(Vector2(x.toFloat(),y.toFloat())) - baseTerrain = Constants.grassland }) + position = HexMath.evenQ2HexCoords(Vector2(x.toFloat(), y.toFloat())) + baseTerrain = Constants.grassland + }) setTransients(ruleset) } @@ -58,17 +66,17 @@ class TileMap { return contains(vector.x.toInt(), vector.y.toInt()) } - fun contains(x:Int, y:Int): Boolean { - val arrayXIndex = x-leftX - if(arrayXIndex<0 || arrayXIndex>=tileMatrix.size) return false - val arrayYIndex = y-bottomY - if(arrayYIndex<0 || arrayYIndex>=tileMatrix[arrayXIndex].size) return false + fun contains(x: Int, y: Int): Boolean { + val arrayXIndex = x - leftX + if (arrayXIndex < 0 || arrayXIndex >= tileMatrix.size) return false + val arrayYIndex = y - bottomY + if (arrayYIndex < 0 || arrayYIndex >= tileMatrix[arrayXIndex].size) return false return tileMatrix[arrayXIndex][arrayYIndex] != null } - operator fun get(x:Int, y:Int):TileInfo{ - val arrayXIndex = x-leftX - val arrayYIndex = y-bottomY + operator fun get(x: Int, y: Int): TileInfo { + val arrayXIndex = x - leftX + val arrayYIndex = y - bottomY return tileMatrix[arrayXIndex][arrayYIndex]!! } @@ -134,7 +142,7 @@ class TileMap { // both the civ name and actual civ need to be in here in order to calculate the canMoveTo...Darn unit.assignOwner(civInfo, false) - var unitToPlaceTile : TileInfo? = null + var unitToPlaceTile: TileInfo? = null // try to place at the original point (this is the most probable scenario) val currentTile = get(position) if (unit.movement.canMoveTo(currentTile)) unitToPlaceTile = currentTile @@ -145,7 +153,7 @@ class TileMap { var potentialCandidates = getPassableNeighbours(currentTile) while (unitToPlaceTile == null && tryCount++ < 10) { unitToPlaceTile = potentialCandidates - .sortedByDescending { if(unit.type.isLandUnit()) it.isLand else true } // Land units should prefer to go into land tiles + .sortedByDescending { if (unit.type.isLandUnit()) it.isLand else true } // Land units should prefer to go into land tiles .firstOrNull { unit.movement.canMoveTo(it) } if (unitToPlaceTile != null) continue // if it's not found yet, let's check their neighbours @@ -228,7 +236,7 @@ class TileMap { * @return stripped clone of [TileMap] */ fun stripAllUnits(): TileMap { - return clone().apply { tileList.forEach {it.stripUnits()} } + return clone().apply { tileList.forEach { it.stripUnits() } } } /** Strips all units and starting location from [TileMap] for specified [Player] @@ -237,7 +245,9 @@ class TileMap { */ fun stripPlayer(player: Player) { tileList.forEach { - if (it.improvement == "StartingLocation " + player.chosenCiv) { it.improvement = null } + if (it.improvement == "StartingLocation " + player.chosenCiv) { + it.improvement = null + } for (unit in it.getUnits()) if (unit.owner == player.chosenCiv) unit.removeFromTile() } } @@ -249,33 +259,34 @@ class TileMap { */ fun switchPlayersNation(player: Player, newNation: Nation) { tileList.forEach { - if (it.improvement == "StartingLocation " + player.chosenCiv) { it.improvement = "StartingLocation "+newNation.name } + if (it.improvement == "StartingLocation " + player.chosenCiv) { + it.improvement = "StartingLocation " + newNation.name + } for (unit in it.getUnits()) if (unit.owner == player.chosenCiv) { unit.owner = newNation.name - unit.civInfo = CivilizationInfo(newNation.name).apply { nation=newNation } + unit.civInfo = CivilizationInfo(newNation.name).apply { nation = newNation } } } } - fun setTransients(ruleset: Ruleset, setUnitCivTransients:Boolean=true) { // In the map editor, no Civs or Game exist, so we won't set the unit transients - val topY= tileList.asSequence().map { it.position.y.toInt() }.max()!! - bottomY= tileList.asSequence().map { it.position.y.toInt() }.min()!! - val rightX= tileList.asSequence().map { it.position.x.toInt() }.max()!! + fun setTransients(ruleset: Ruleset, setUnitCivTransients: Boolean = true) { // In the map editor, no Civs or Game exist, so we won't set the unit transients + val topY = tileList.asSequence().map { it.position.y.toInt() }.max()!! + bottomY = tileList.asSequence().map { it.position.y.toInt() }.min()!! + val rightX = tileList.asSequence().map { it.position.x.toInt() }.max()!! leftX = tileList.asSequence().map { it.position.x.toInt() }.min()!! - for(x in leftX..rightX){ + for (x in leftX..rightX) { val row = ArrayList() - for(y in bottomY..topY) row.add(null) + for (y in bottomY..topY) row.add(null) tileMatrix.add(row) } - for (tileInfo in values){ - tileMatrix[tileInfo.position.x.toInt()-leftX][tileInfo.position.y.toInt()-bottomY] = tileInfo + for (tileInfo in values) { + tileMatrix[tileInfo.position.x.toInt() - leftX][tileInfo.position.y.toInt() - bottomY] = tileInfo tileInfo.tileMap = this tileInfo.ruleset = ruleset tileInfo.setTerrainTransients() tileInfo.setUnitTransients(setUnitCivTransients) } } -} - +} \ No newline at end of file diff --git a/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt b/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt index f7f52c3052..1ba3dc6fdc 100644 --- a/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt +++ b/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt @@ -41,9 +41,9 @@ class TileImprovementConstructionTests { val terrain = improvement.terrainsCanBeBuiltOn.firstOrNull() ?: continue tile.baseTerrain = terrain tile.setTransients() - if(improvement.uniqueTo!=null) civInfo.civName = improvement.uniqueTo!! + if (improvement.uniqueTo != null) civInfo.civName = improvement.uniqueTo!! val canBeBuilt = tile.canBuildImprovement(improvement, civInfo) - Assert.assertTrue( improvement.name, canBeBuilt) + Assert.assertTrue(improvement.name, canBeBuilt) } } @@ -51,12 +51,12 @@ class TileImprovementConstructionTests { fun allResourceImprovementsCanBeBuilt() { for (improvement in ruleSet.tileImprovements.values) { tile.resource = ruleSet.tileResources.values - .firstOrNull { it.improvement == improvement.name}?.name + .firstOrNull { it.improvement == improvement.name }?.name if (tile.resource == null) continue tile.baseTerrain = "Plains" tile.setTransients() val canBeBuilt = tile.canBuildImprovement(improvement, civInfo) - Assert.assertTrue( improvement.name, canBeBuilt) + Assert.assertTrue(improvement.name, canBeBuilt) } } @@ -77,7 +77,7 @@ class TileImprovementConstructionTests { if (!improvement.uniques.contains("Can only be built on Coastal tiles")) continue civInfo.civName = improvement.uniqueTo ?: "OtherCiv" val canBeBuilt = tile.canBuildImprovement(improvement, civInfo) - Assert.assertTrue( improvement.name, canBeBuilt) + Assert.assertTrue(improvement.name, canBeBuilt) } } @@ -89,7 +89,7 @@ class TileImprovementConstructionTests { tile.baseTerrain = "Plains" tile.setTransients() val canBeBuilt = tile.canBuildImprovement(improvement, civInfo) - Assert.assertFalse( improvement.name, canBeBuilt) + Assert.assertFalse(improvement.name, canBeBuilt) } } } \ No newline at end of file