Cities referenced by UUID (#1638)

* Cities referenced by UUID

* UUID defaulted in CityInfo

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
r3versi 2020-01-09 18:41:55 +01:00 committed by Yair Morgenstern
parent 065e944896
commit 036d4058f1
11 changed files with 83 additions and 24 deletions

View File

@ -5,16 +5,17 @@ import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.automation.NextTurnAutomation
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.LocationAction
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.civilization.*
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.metadata.GameParameters
import com.unciv.models.ruleset.Difficulty
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetCache
import java.util.*
import kotlin.collections.ArrayList
class GameInfo {
@Transient lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn
@ -58,6 +59,7 @@ class GameInfo {
fun getCurrentPlayerCivilization() = currentPlayerCiv
fun getBarbarianCivilization() = getCivilization("Barbarians")
fun getDifficulty() = difficultyObject
fun getCities() = civilizations.flatMap { it.cities }
//endregion
fun nextTurn() {
@ -265,11 +267,62 @@ class GameInfo {
// This doesn't HAVE to go here, but why not.
// As of version 3.1.3, trade offers of "Declare war on X" and "Introduction to X" were changed to X,
// with the extra text being added only on UI display (solved a couple of problems).
for(trade in civInfo.tradeRequests.map { it.trade })
for(offer in trade.theirOffers.union(trade.ourOffers)){
for(trade in civInfo.tradeRequests.map { it.trade }) {
for (offer in trade.theirOffers.union(trade.ourOffers)) {
offer.name = offer.name.removePrefix("Declare war on ")
offer.name = offer.name.removePrefix("Introduction to ")
}
}
// As of 3.4.9 cities are referenced by id, not by name
// So try to update every tradeRequest (if there are no conflicting names)
for(tradeRequest in civInfo.tradeRequests) {
val trade = tradeRequest.trade
val toRemove = ArrayList<TradeOffer>()
for (offer in trade.ourOffers) {
if (offer.type == TradeType.City) {
val countNames = civInfo.cities.count { it.name == offer.name}
if (countNames == 1)
offer.name = civInfo.cities.first { it.name == offer.name}.id
// There are conflicting names: we can't guess what city was being offered
else if (countNames > 1)
toRemove.add(offer)
}
}
trade.ourOffers.removeAll(toRemove)
toRemove.clear()
val themCivInfo = getCivilization(tradeRequest.requestingCiv)
for (offer in trade.theirOffers) {
if (offer.type == TradeType.City) {
val countNames = themCivInfo.cities.count { it.name == offer.name}
if (countNames == 1)
offer.name = themCivInfo.cities.first { it.name == offer.name}.id
// There are conflicting names: we can't guess what city was being offered
else if (countNames > 1)
toRemove.add(offer)
}
}
trade.theirOffers.removeAll(toRemove)
}
// As of 3.4.9 cities are referenced by id, not by name
val toRemove = ArrayList<PopupAlert>()
for (popupAlert in civInfo.popupAlerts.filter { it.type == AlertType.CityConquered }) {
val countNames = getCities().count { it.name == popupAlert.value }
if (countNames == 1)
popupAlert.value = getCities().first { it.name == popupAlert.value }.id
else if (countNames > 1) {
// Sorry again, conflicting names: who knows what city you conquered?
toRemove.add(popupAlert)
}
}
civInfo.popupAlerts.removeAll(toRemove)
}
for (civInfo in civilizations) civInfo.setNationTransient()

View File

@ -93,7 +93,7 @@ class SpecificUnitAutomation{
fun automateSettlerActions(unit: MapUnit) {
if(unit.getTile().militaryUnit==null) return // Don't move until you're accompanied by a military unit
val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities }
val tilesNearCities = unit.civInfo.gameInfo.getCities()
.flatMap {
val distanceAwayFromCity =
if (unit.civInfo.knows(it.civInfo)

View File

@ -45,14 +45,14 @@ class WorkerAutomation(val unit: MapUnit) {
val citiesToNumberOfUnimprovedTiles = HashMap<String, Int>()
for (city in unit.civInfo.cities) {
citiesToNumberOfUnimprovedTiles[city.name] =
citiesToNumberOfUnimprovedTiles[city.id] =
city.getTiles().count { it.isLand && it.civilianUnit == null
&& tileCanBeImproved(it, unit.civInfo) }
}
val mostUndevelopedCity = unit.civInfo.cities
.filter { citiesToNumberOfUnimprovedTiles[it.name]!! > 0 }
.sortedByDescending { citiesToNumberOfUnimprovedTiles[it.name] }
.filter { citiesToNumberOfUnimprovedTiles[it.id]!! > 0 }
.sortedByDescending { citiesToNumberOfUnimprovedTiles[it.id] }
.firstOrNull { unit.movement.canReach(it.getCenterTile()) } //goto most undeveloped city
if (mostUndevelopedCity != null && mostUndevelopedCity != unit.currentTile.owningCity) {
val reachedTile = unit.movement.headTowards(mostUndevelopedCity.getCenterTile())

View File

@ -256,7 +256,7 @@ class Battle(val gameInfo:GameInfo) {
}
if (attackerCiv.isPlayerCivilization()) {
attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.name))
attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.id))
UncivGame.Current.settings.addCompletedTutorialTask("Conquer a city")
}
else {

View File

@ -19,8 +19,10 @@ import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.withoutItem
import kotlin.math.*
import java.util.*
import kotlin.collections.HashMap
import kotlin.collections.HashSet
import kotlin.math.*
class CityInfo {
@Transient lateinit var civInfo: CivilizationInfo
@ -31,6 +33,7 @@ class CityInfo {
@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()
var name: String = ""
var foundingCiv = ""
var turnAcquired = 0
@ -99,15 +102,16 @@ class CityInfo {
//region pure functions
fun clone(): CityInfo {
val toReturn = CityInfo()
toReturn.location=location
toReturn.name=name
toReturn.health=health
toReturn.location = location
toReturn.id = id
toReturn.name = name
toReturn.health = health
toReturn.population = population.clone()
toReturn.cityConstructions=cityConstructions.clone()
toReturn.cityConstructions = cityConstructions.clone()
toReturn.expansion = expansion.clone()
toReturn.tiles = tiles
toReturn.workedTiles = workedTiles
toReturn.isBeingRazed=isBeingRazed
toReturn.isBeingRazed = isBeingRazed
toReturn.attackedThisTurn = attackedThisTurn
toReturn.resistanceCounter = resistanceCounter
toReturn.foundingCiv = foundingCiv

View File

@ -128,7 +128,7 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo){
val citiesReachedToMediums = HashMap<CityInfo, ArrayList<String>>()
var citiesToCheck = mutableListOf(civInfo.getCapital())
citiesReachedToMediums[civInfo.getCapital()] = arrayListOf("Start")
val allCivCities = civInfo.gameInfo.civilizations.flatMap { it.cities }
val allCivCities = civInfo.gameInfo.getCities()
val theWheelIsResearched = civInfo.tech.isResearched("The Wheel")

View File

@ -38,7 +38,7 @@ class TradeEvaluation{
TradeType.Technology -> return true
TradeType.Introduction -> return true
TradeType.WarDeclaration -> return true
TradeType.City -> return offerer.cities.any { it.name==tradeOffer.name }
TradeType.City -> return offerer.cities.any { it.id == tradeOffer.name }
}
}
@ -136,7 +136,7 @@ class TradeEvaluation{
else return 0 // why should we pay you to go fight someone...?
}
TradeType.City -> {
val city = tradePartner.cities.first { it.name==offer.name }
val city = tradePartner.cities.first { it.id==offer.name }
val stats = city.cityStats.currentCityStats
if(civInfo.getHappiness() + city.cityStats.happinessList.values.sum() < 0)
return 0 // we can't really afford to go into negative happiness because of buying a city
@ -204,7 +204,7 @@ class TradeEvaluation{
}
TradeType.City -> {
val city = civInfo.cities.first { it.name==offer.name }
val city = civInfo.cities.first { it.id == offer.name }
val stats = city.cityStats.currentCityStats
val sumOfStats = stats.culture+stats.gold+stats.science+stats.production+stats.happiness+stats.food
return sumOfStats.toInt() * 100

View File

@ -48,7 +48,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
if (!civInfo.isOneCityChallenger() && !otherCivilization.isOneCityChallenger()
&& !civInfo.isCityState() && !otherCivilization.isCityState()) {
for (city in civInfo.cities.filterNot { it.isCapital() })
offers.add(TradeOffer(city.name, TradeType.City, 0))
offers.add(TradeOffer(city.id, TradeType.City, 0))
}
val otherCivsWeKnow = civInfo.getKnownCivs()
@ -94,7 +94,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
to.tech.addTechnology(offer.name)
}
if (offer.type == TradeType.City) {
val city = from.cities.first { it.name == offer.name }
val city = from.cities.first { it.id == offer.name }
city.moveToCiv(to)
city.getCenterTile().getUnits().forEach { it.movement.teleportToClosestMoveableTile() }
to.updateViewableTiles()

View File

@ -1,5 +1,6 @@
package com.unciv.logic.trade
import com.unciv.UncivGame
import com.unciv.models.translations.tr
data class TradeOffer(var name:String, var type: TradeType,
@ -18,6 +19,7 @@ data class TradeOffer(var name:String, var type: TradeType,
var offerText = when(type){
TradeType.WarDeclaration -> "Declare war on [$name]"
TradeType.Introduction -> "Introduction to [$name]"
TradeType.City -> UncivGame.Current.gameInfo.getCities().first{ it.id == name }.name
else -> name
}.tr()
if (type !in tradesToNotHaveNumbers) offerText += " ($amount)"

View File

@ -256,7 +256,7 @@ class Building : NamedStats(), IConstruction{
// Regular wonders
if (isWonder){
if(civInfo.gameInfo.civilizations.flatMap { it.cities }
if(civInfo.gameInfo.getCities()
.any {it.cityConstructions.isBuilt(name)})
return "Wonder is already built"

View File

@ -58,7 +58,7 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
}
}
AlertType.CityConquered -> {
val city = worldScreen.gameInfo.civilizations.flatMap { it.cities }.first { it.name == popupAlert.value}
val city = worldScreen.gameInfo.getCities().first { it.id == popupAlert.value }
addGoodSizedLabel("What would you like to do with the city?",24)
.padBottom(20f).row()
val conqueringCiv = worldScreen.gameInfo.currentPlayerCiv