Code reorg - Split some functions off of civilizationInfo into their own sub-classes because it was getting too long
This commit is contained in:
parent
d7cfdf3e83
commit
51ad40b8bf
7 changed files with 295 additions and 230 deletions
|
@ -177,7 +177,8 @@ class NextTurnAutomation{
|
|||
private fun adoptPolicy(civInfo: CivilizationInfo) {
|
||||
while (civInfo.policies.canAdoptPolicy()) {
|
||||
|
||||
val adoptablePolicies = GameBasics.PolicyBranches.values.flatMap { it.policies.union(listOf(it)) }
|
||||
val adoptablePolicies = GameBasics.PolicyBranches.values
|
||||
.flatMap { it.policies.union(listOf(it)) }
|
||||
.filter { civInfo.policies.isAdoptable(it) }
|
||||
|
||||
val preferredVictoryType = civInfo.victoryType()
|
||||
|
|
131
core/src/com/unciv/logic/civilization/CivInfoStats.kt
Normal file
131
core/src/com/unciv/logic/civilization/CivInfoStats.kt
Normal file
|
@ -0,0 +1,131 @@
|
|||
package com.unciv.logic.civilization
|
||||
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.models.gamebasics.tile.ResourceType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.StatMap
|
||||
import com.unciv.models.stats.Stats
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
/** CivInfo class was getting too crowded */
|
||||
class CivInfoStats(val civInfo: CivilizationInfo){
|
||||
|
||||
private fun getUnitUpkeep(): Int {
|
||||
val baseUnitCost = 0.5f
|
||||
val freeUnits = 3
|
||||
var unitsToPayFor = civInfo.getCivUnits()
|
||||
if(civInfo.policies.isAdopted("Oligarchy")) unitsToPayFor = unitsToPayFor.filterNot { it.getTile().isCityCenter() }
|
||||
|
||||
var numberOfUnitsToPayFor = max(0f, unitsToPayFor.count().toFloat() - freeUnits)
|
||||
if(civInfo.getNation().unique=="67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance."){
|
||||
val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.type.isLandUnit() }.toFloat())
|
||||
numberOfUnitsToPayFor -= 0.25f * numberOfUnitsWithDiscount
|
||||
}
|
||||
|
||||
|
||||
val gameProgress = civInfo.gameInfo.turns/400f // as game progresses Maintenance cost rises
|
||||
var cost = baseUnitCost*numberOfUnitsToPayFor*(1+gameProgress)
|
||||
cost = cost.pow(1+gameProgress/3) // Why 3? To spread 1 to 1.33
|
||||
if(!civInfo.isPlayerCivilization())
|
||||
cost *= civInfo.gameInfo.getDifficulty().aiUnitMaintenanceModifier
|
||||
if(civInfo.policies.isAdopted("Autocracy")) cost *= 0.66f
|
||||
return cost.toInt()
|
||||
}
|
||||
|
||||
private fun getTransportationUpkeep(): Int {
|
||||
var transportationUpkeep = 0
|
||||
for (it in civInfo.gameInfo.tileMap.values.filter { it.getOwner()==civInfo }.filterNot { it.isCityCenter() }) {
|
||||
when(it.roadStatus) {
|
||||
RoadStatus.Road -> transportationUpkeep += 1
|
||||
RoadStatus.Railroad -> transportationUpkeep += 2
|
||||
}
|
||||
}
|
||||
if (civInfo.policies.isAdopted("Trade Unions")) transportationUpkeep *= (2 / 3f).toInt()
|
||||
return transportationUpkeep
|
||||
}
|
||||
|
||||
fun getStatMapForNextTurn(): HashMap<String, Stats> {
|
||||
val statMap = StatMap()
|
||||
for (city in civInfo.cities){
|
||||
statMap.add("Cities",city.cityStats.currentCityStats)
|
||||
}
|
||||
|
||||
//City states culture bonus
|
||||
for (otherCiv in civInfo.getKnownCivs()) {
|
||||
if (otherCiv.isCityState() && otherCiv.getCityStateType() == CityStateType.Cultured
|
||||
&& otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel() >= RelationshipLevel.Friend) {
|
||||
val cultureBonus = Stats()
|
||||
cultureBonus.add(Stat.Culture, 3f * (civInfo.getEra().ordinal+1))
|
||||
statMap.add("City States",cultureBonus)
|
||||
}
|
||||
}
|
||||
|
||||
for (entry in getHappinessBreakdown()) {
|
||||
statMap.add(entry.key, Stats().apply { happiness=entry.value })
|
||||
}
|
||||
|
||||
statMap["Transportation upkeep"] = Stats().apply { gold=- getTransportationUpkeep().toFloat()}
|
||||
statMap["Unit upkeep"] = Stats().apply { gold=- getUnitUpkeep().toFloat()}
|
||||
|
||||
if (civInfo.policies.isAdopted("Mandate Of Heaven")) {
|
||||
val happiness = statMap.values.map { it.happiness }.sum()
|
||||
if(happiness>0) statMap.add("Policies", Stats().apply { culture=happiness/2 })
|
||||
}
|
||||
|
||||
// negative gold hurts science
|
||||
// if we have - or 0, then the techs will never be complete and the tech button
|
||||
// will show a negative number of turns and int.max, respectively
|
||||
if (statMap.values.map { it.gold }.sum() < 0) {
|
||||
val scienceDeficit = max(statMap.values.map { it.gold }.sum(),
|
||||
1 - statMap.values.map { it.science }.sum())// Leave at least 1
|
||||
statMap["Treasury deficit"] = Stats().apply { science = scienceDeficit }
|
||||
}
|
||||
val goldDifferenceFromTrade = civInfo.diplomacy.values.sumBy { it.goldPerTurn() }
|
||||
if(goldDifferenceFromTrade!=0)
|
||||
statMap["Trade"] = Stats().apply { gold= goldDifferenceFromTrade.toFloat() }
|
||||
|
||||
return statMap
|
||||
}
|
||||
|
||||
|
||||
fun getHappinessBreakdown(): HashMap<String, Float> {
|
||||
val statMap = HashMap<String, Float>()
|
||||
statMap["Base happiness"] = civInfo.getDifficulty().baseHappiness.toFloat()
|
||||
|
||||
var happinessPerUniqueLuxury = 5f
|
||||
if (civInfo.policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1
|
||||
statMap["Luxury resources"]= civInfo.getCivResources().map { it.resource }
|
||||
.count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury
|
||||
|
||||
for(city in civInfo.cities.toList()){
|
||||
for(keyvalue in city.cityStats.happinessList){
|
||||
if(statMap.containsKey(keyvalue.key))
|
||||
statMap[keyvalue.key] = statMap[keyvalue.key]!!+keyvalue.value
|
||||
else statMap[keyvalue.key] = keyvalue.value
|
||||
}
|
||||
}
|
||||
|
||||
if (civInfo.getBuildingUniques().contains("Provides 1 happiness per social policy")) {
|
||||
if(!statMap.containsKey("Policies")) statMap["Policies"]=0f
|
||||
statMap["Policies"] = statMap["Policies"]!! +
|
||||
civInfo.policies.getAdoptedPolicies().count { !it.endsWith("Complete") }.toFloat()
|
||||
}
|
||||
|
||||
//From city-states
|
||||
for (otherCiv in civInfo.getKnownCivs()) {
|
||||
if (otherCiv.isCityState() && otherCiv.getCityStateType() == CityStateType.Mercantile
|
||||
&& otherCiv.getDiplomacyManager(civInfo).relationshipLevel() >= RelationshipLevel.Friend) {
|
||||
if (statMap.containsKey("City-states"))
|
||||
statMap["City-states"] = statMap["City-states"]!! + 3f
|
||||
else
|
||||
statMap["City-states"] = 3f
|
||||
}
|
||||
}
|
||||
|
||||
return statMap
|
||||
}
|
||||
|
||||
}
|
140
core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt
Normal file
140
core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt
Normal file
|
@ -0,0 +1,140 @@
|
|||
package com.unciv.logic.civilization
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.map.BFS
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.tile.ResourceSupplyList
|
||||
import com.unciv.models.gamebasics.tr
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.addAll
|
||||
import kotlin.collections.arrayListOf
|
||||
import kotlin.collections.asSequence
|
||||
import kotlin.collections.filter
|
||||
import kotlin.collections.filterNot
|
||||
import kotlin.collections.flatMap
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.map
|
||||
import kotlin.collections.mapNotNull
|
||||
import kotlin.collections.mutableListOf
|
||||
import kotlin.collections.plusAssign
|
||||
import kotlin.collections.set
|
||||
import kotlin.collections.toList
|
||||
|
||||
/** CivInfo class was getting too crowded */
|
||||
class CivInfoTransientUpdater(val civInfo: CivilizationInfo){
|
||||
|
||||
// This is a big performance
|
||||
fun updateViewableTiles() {
|
||||
val newViewableTiles = HashSet<TileInfo>()
|
||||
newViewableTiles.addAll(civInfo.cities.flatMap { it.getTiles() }.flatMap { it.neighbors }) // tiles adjacent to city tiles
|
||||
newViewableTiles.addAll(civInfo.getCivUnits().flatMap { it.viewableTiles})
|
||||
civInfo.viewableTiles = newViewableTiles // to avoid concurrent modification problems
|
||||
|
||||
val newViewableInvisibleTiles = HashSet<TileInfo>()
|
||||
newViewableInvisibleTiles.addAll(civInfo.getCivUnits()
|
||||
.filter {it.hasUnique("Can attack submarines")}
|
||||
.flatMap {it.viewableTiles})
|
||||
civInfo.viewableInvisibleUnitsTiles = newViewableInvisibleTiles
|
||||
// updating the viewable tiles also affects the explored tiles, obvs
|
||||
|
||||
val newExploredTiles = HashSet<Vector2>(civInfo.exploredTiles)
|
||||
newExploredTiles.addAll(newViewableTiles.asSequence().map { it.position }
|
||||
.filterNot { civInfo.exploredTiles.contains(it) })
|
||||
civInfo.exploredTiles = newExploredTiles // ditto
|
||||
|
||||
|
||||
val viewedCivs = HashSet<CivilizationInfo>()
|
||||
for(tile in civInfo.viewableTiles){
|
||||
val tileOwner = tile.getOwner()
|
||||
if(tileOwner!=null) viewedCivs+=tileOwner
|
||||
for(unit in tile.getUnits()) viewedCivs+=unit.civInfo
|
||||
}
|
||||
|
||||
if(!civInfo.isBarbarianCivilization()) {
|
||||
for (otherCiv in viewedCivs.filterNot { it == civInfo || it.isBarbarianCivilization() })
|
||||
if (!civInfo.diplomacy.containsKey(otherCiv.civName)) {
|
||||
civInfo.meetCivilization(otherCiv)
|
||||
civInfo.addNotification("We have encountered [${otherCiv.civName}]!".tr(), null, Color.GOLD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateHasActiveGreatWall(){
|
||||
civInfo.hasActiveGreatWall = !civInfo.tech.isResearched("Dynamite") &&
|
||||
civInfo.getBuildingUniques().contains("Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)")
|
||||
}
|
||||
|
||||
fun setCitiesConnectedToCapitalTransients(){
|
||||
if(civInfo.cities.isEmpty()) return // eg barbarians
|
||||
|
||||
// We map which cities we've reached, to the mediums they've been reached by -
|
||||
// this is so we know that if we've seen which cities can be connected by port A, and one
|
||||
// of those is city B, then we don't need to check the cities that B can connect to by port,
|
||||
// since we'll get the same cities we got from A, since they're connected to the same sea.
|
||||
val citiesReachedToMediums = HashMap<CityInfo, ArrayList<String>>()
|
||||
var citiesToCheck = mutableListOf(civInfo.getCapital())
|
||||
citiesReachedToMediums[civInfo.getCapital()] = arrayListOf("Start")
|
||||
val allCivCities = civInfo.gameInfo.civilizations.flatMap { it.cities }
|
||||
|
||||
while(citiesToCheck.isNotEmpty() && citiesReachedToMediums.size<allCivCities.size){
|
||||
val newCitiesToCheck = mutableListOf<CityInfo>()
|
||||
for(cityToConnectFrom in citiesToCheck){
|
||||
val reachedMediums = citiesReachedToMediums[cityToConnectFrom]!!
|
||||
|
||||
// This is copypasta and can be cleaned up
|
||||
if(!reachedMediums.contains("Road")){
|
||||
|
||||
val roadBfs = BFS(cityToConnectFrom.getCenterTile()) { it.roadStatus != RoadStatus.None }
|
||||
roadBfs.stepToEnd()
|
||||
val reachedCities = allCivCities.filter { roadBfs.tilesReached.containsKey(it.getCenterTile())}
|
||||
for(reachedCity in reachedCities){
|
||||
if(!citiesReachedToMediums.containsKey(reachedCity)){
|
||||
newCitiesToCheck.add(reachedCity)
|
||||
citiesReachedToMediums[reachedCity] = arrayListOf()
|
||||
}
|
||||
val cityReachedByMediums = citiesReachedToMediums[reachedCity]!!
|
||||
if(!cityReachedByMediums.contains("Road"))
|
||||
cityReachedByMediums.add("Road")
|
||||
}
|
||||
citiesReachedToMediums[cityToConnectFrom]!!.add("Road")
|
||||
}
|
||||
|
||||
if(!reachedMediums.contains("Harbor")
|
||||
&& cityToConnectFrom.cityConstructions.containsBuildingOrEquivalent("Harbor")){
|
||||
val seaBfs = BFS(cityToConnectFrom.getCenterTile()) { it.isWater || it.isCityCenter() }
|
||||
seaBfs.stepToEnd()
|
||||
val reachedCities = allCivCities.filter { seaBfs.tilesReached.containsKey(it.getCenterTile())}
|
||||
for(reachedCity in reachedCities){
|
||||
if(!citiesReachedToMediums.containsKey(reachedCity)){
|
||||
newCitiesToCheck.add(reachedCity)
|
||||
citiesReachedToMediums[reachedCity] = arrayListOf()
|
||||
}
|
||||
val cityReachedByMediums = citiesReachedToMediums[reachedCity]!!
|
||||
if(!cityReachedByMediums.contains("Harbor"))
|
||||
cityReachedByMediums.add("Harbor")
|
||||
}
|
||||
citiesReachedToMediums[cityToConnectFrom]!!.add("Harbor")
|
||||
}
|
||||
}
|
||||
citiesToCheck = newCitiesToCheck
|
||||
}
|
||||
|
||||
civInfo.citiesConnectedToCapital = citiesReachedToMediums.keys.toList()
|
||||
}
|
||||
|
||||
|
||||
fun updateDetailedCivResources() {
|
||||
val newDetailedCivResources = ResourceSupplyList()
|
||||
for (city in civInfo.cities) newDetailedCivResources.add(city.getCityResources())
|
||||
for (dip in civInfo.diplomacy.values) newDetailedCivResources.add(dip.resourcesFromTrade())
|
||||
for(resource in civInfo.getCivUnits().mapNotNull { it.baseUnit.requiredResource }.map { GameBasics.TileResources[it]!! })
|
||||
newDetailedCivResources.add(resource,-1,"Units")
|
||||
civInfo.detailedCivResources = newDetailedCivResources
|
||||
}
|
||||
}
|
|
@ -9,25 +9,16 @@ import com.unciv.logic.GameInfo
|
|||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.map.BFS
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.trade.TradeRequest
|
||||
import com.unciv.models.gamebasics.*
|
||||
import com.unciv.models.gamebasics.tech.TechEra
|
||||
import com.unciv.models.gamebasics.tile.ResourceSupplyList
|
||||
import com.unciv.models.gamebasics.tile.ResourceType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.StatMap
|
||||
import com.unciv.models.stats.Stats
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class CivilizationInfo {
|
||||
|
@ -136,125 +127,17 @@ class CivilizationInfo {
|
|||
else return VictoryType.Neutral
|
||||
}
|
||||
|
||||
fun stats() = CivInfoStats(this)
|
||||
private fun transients() = CivInfoTransientUpdater(this)
|
||||
|
||||
fun updateStatsForNextTurn(){
|
||||
statsForNextTurn = getStatMapForNextTurn().values.toList().reduce{a,b->a+b}
|
||||
statsForNextTurn = stats().getStatMapForNextTurn().values.toList().reduce{a,b->a+b}
|
||||
}
|
||||
|
||||
fun getStatMapForNextTurn(): HashMap<String, Stats> {
|
||||
val statMap = StatMap()
|
||||
for (city in cities){
|
||||
statMap.add("Cities",city.cityStats.currentCityStats)
|
||||
}
|
||||
|
||||
//City states culture bonus
|
||||
for (otherCiv in getKnownCivs()) {
|
||||
if (otherCiv.isCityState() && otherCiv.getCityStateType() == CityStateType.Cultured
|
||||
&& otherCiv.getDiplomacyManager(civName).relationshipLevel() >= RelationshipLevel.Friend) {
|
||||
val cultureBonus = Stats()
|
||||
cultureBonus.add(Stat.Culture, 3f * (getEra().ordinal+1))
|
||||
statMap.add("City States",cultureBonus)
|
||||
}
|
||||
}
|
||||
|
||||
for (entry in getHappinessBreakdown()) {
|
||||
statMap.add(entry.key,Stats().apply { happiness=entry.value })
|
||||
}
|
||||
|
||||
statMap["Transportation upkeep"] = Stats().apply { gold=- getTransportationUpkeep().toFloat()}
|
||||
statMap["Unit upkeep"] = Stats().apply { gold=- getUnitUpkeep().toFloat()}
|
||||
|
||||
if (policies.isAdopted("Mandate Of Heaven")) {
|
||||
val happiness = statMap.values.map { it.happiness }.sum()
|
||||
if(happiness>0) statMap.add("Policies",Stats().apply { culture=happiness/2 })
|
||||
}
|
||||
|
||||
// negative gold hurts science
|
||||
// if we have - or 0, then the techs will never be complete and the tech button
|
||||
// will show a negative number of turns and int.max, respectively
|
||||
if (statMap.values.map { it.gold }.sum() < 0) {
|
||||
val scienceDeficit = max(statMap.values.map { it.gold }.sum(),
|
||||
1 - statMap.values.map { it.science }.sum())// Leave at least 1
|
||||
statMap["Treasury deficit"] = Stats().apply { science = scienceDeficit }
|
||||
}
|
||||
val goldDifferenceFromTrade = diplomacy.values.sumBy { it.goldPerTurn() }
|
||||
if(goldDifferenceFromTrade!=0)
|
||||
statMap["Trade"] = Stats().apply { gold= goldDifferenceFromTrade.toFloat() }
|
||||
|
||||
return statMap
|
||||
}
|
||||
|
||||
private fun getUnitUpkeep(): Int {
|
||||
val baseUnitCost = 0.5f
|
||||
val freeUnits = 3
|
||||
var unitsToPayFor = getCivUnits()
|
||||
if(policies.isAdopted("Oligarchy")) unitsToPayFor = unitsToPayFor.filterNot { it.getTile().isCityCenter() }
|
||||
|
||||
var numberOfUnitsToPayFor = max(0f, unitsToPayFor.count().toFloat() - freeUnits)
|
||||
if(getNation().unique=="67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance."){
|
||||
val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.type.isLandUnit() }.toFloat())
|
||||
numberOfUnitsToPayFor -= 0.25f * numberOfUnitsWithDiscount
|
||||
}
|
||||
|
||||
|
||||
val gameProgress = gameInfo.turns/400f // as game progresses Maintenance cost rises
|
||||
var cost = baseUnitCost*numberOfUnitsToPayFor*(1+gameProgress)
|
||||
cost = cost.pow(1+gameProgress/3) // Why 3? To spread 1 to 1.33
|
||||
if(!isPlayerCivilization())
|
||||
cost *= gameInfo.getDifficulty().aiUnitMaintenanceModifier
|
||||
if(policies.isAdopted("Autocracy")) cost *= 0.66f
|
||||
return cost.toInt()
|
||||
}
|
||||
fun getHappiness() = stats().getHappinessBreakdown().values.sum().roundToInt()
|
||||
|
||||
private fun getTransportationUpkeep(): Int {
|
||||
var transportationUpkeep = 0
|
||||
for (it in gameInfo.tileMap.values.filter { it.getOwner()==this }.filterNot { it.isCityCenter() }) {
|
||||
when(it.roadStatus) {
|
||||
RoadStatus.Road -> transportationUpkeep += 1
|
||||
RoadStatus.Railroad -> transportationUpkeep += 2
|
||||
}
|
||||
}
|
||||
if (policies.isAdopted("Trade Unions")) transportationUpkeep *= (2 / 3f).toInt()
|
||||
return transportationUpkeep
|
||||
}
|
||||
|
||||
fun getHappiness() = getHappinessBreakdown().values.sum().roundToInt()
|
||||
|
||||
fun getHappinessBreakdown(): HashMap<String, Float> {
|
||||
val statMap = HashMap<String,Float>()
|
||||
statMap["Base happiness"] = getDifficulty().baseHappiness.toFloat()
|
||||
|
||||
var happinessPerUniqueLuxury = 5f
|
||||
if (policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1
|
||||
statMap["Luxury resources"]= getCivResources().map { it.resource }
|
||||
.count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury
|
||||
|
||||
for(city in cities.toList()){
|
||||
for(keyvalue in city.cityStats.happinessList){
|
||||
if(statMap.containsKey(keyvalue.key))
|
||||
statMap[keyvalue.key] = statMap[keyvalue.key]!!+keyvalue.value
|
||||
else statMap[keyvalue.key] = keyvalue.value
|
||||
}
|
||||
}
|
||||
|
||||
if (getBuildingUniques().contains("Provides 1 happiness per social policy")) {
|
||||
if(!statMap.containsKey("Policies")) statMap["Policies"]=0f
|
||||
statMap["Policies"] = statMap["Policies"]!! +
|
||||
policies.getAdoptedPolicies().count { !it.endsWith("Complete") }.toFloat()
|
||||
}
|
||||
|
||||
//From city-states
|
||||
for (otherCiv in getKnownCivs()) {
|
||||
if (otherCiv.isCityState() && otherCiv.getCityStateType() == CityStateType.Mercantile
|
||||
&& otherCiv.getDiplomacyManager(this).relationshipLevel() >= RelationshipLevel.Friend) {
|
||||
if (statMap.containsKey("City-states"))
|
||||
statMap["City-states"] = statMap["City-states"]!! + 3f
|
||||
else
|
||||
statMap["City-states"] = 3f
|
||||
}
|
||||
}
|
||||
|
||||
return statMap
|
||||
}
|
||||
|
||||
fun getCivResources(): ResourceSupplyList {
|
||||
val newResourceSupplyList=ResourceSupplyList()
|
||||
|
@ -263,14 +146,6 @@ class CivilizationInfo {
|
|||
return newResourceSupplyList
|
||||
}
|
||||
|
||||
fun updateDetailedCivResources() {
|
||||
val newDetailedCivResources = ResourceSupplyList()
|
||||
for (city in cities) newDetailedCivResources.add(city.getCityResources())
|
||||
for (dip in diplomacy.values) newDetailedCivResources.add(dip.resourcesFromTrade())
|
||||
for(resource in getCivUnits().mapNotNull { it.baseUnit.requiredResource }.map { GameBasics.TileResources[it]!! })
|
||||
newDetailedCivResources.add(resource,-1,"Units")
|
||||
detailedCivResources = newDetailedCivResources
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a dictionary of ALL resource names, and the amount that the civ has of each
|
||||
|
@ -338,40 +213,6 @@ class CivilizationInfo {
|
|||
return baseBuilding
|
||||
}
|
||||
|
||||
// This is a big performance
|
||||
fun updateViewableTiles() {
|
||||
val newViewableTiles = HashSet<TileInfo>()
|
||||
newViewableTiles.addAll(cities.flatMap { it.getTiles() }.flatMap { it.neighbors }) // tiles adjacent to city tiles
|
||||
newViewableTiles.addAll(getCivUnits().flatMap { it.viewableTiles})
|
||||
viewableTiles = newViewableTiles // to avoid concurrent modification problems
|
||||
|
||||
val newViewableInvisibleTiles = HashSet<TileInfo>()
|
||||
newViewableInvisibleTiles.addAll(getCivUnits().filter {it.hasUnique("Can attack submarines")}.flatMap {it.viewableTiles})
|
||||
viewableInvisibleUnitsTiles = newViewableInvisibleTiles
|
||||
// updating the viewable tiles also affects the explored tiles, obvs
|
||||
|
||||
val newExploredTiles = HashSet<Vector2>(exploredTiles)
|
||||
newExploredTiles.addAll(newViewableTiles.asSequence().map { it.position }
|
||||
.filterNot { exploredTiles.contains(it) })
|
||||
exploredTiles = newExploredTiles // ditto
|
||||
|
||||
|
||||
val viewedCivs = HashSet<CivilizationInfo>()
|
||||
for(tile in viewableTiles){
|
||||
val tileOwner = tile.getOwner()
|
||||
if(tileOwner!=null) viewedCivs+=tileOwner
|
||||
for(unit in tile.getUnits()) viewedCivs+=unit.civInfo
|
||||
}
|
||||
|
||||
if(!isBarbarianCivilization()) {
|
||||
for (otherCiv in viewedCivs.filterNot { it == this || it.isBarbarianCivilization() })
|
||||
if (!diplomacy.containsKey(otherCiv.civName)) {
|
||||
meetCivilization(otherCiv)
|
||||
addNotification("We have encountered [${otherCiv.civName}]!".tr(), null, Color.GOLD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun meetCivilization(otherCiv: CivilizationInfo) {
|
||||
diplomacy[otherCiv.civName] = DiplomacyManager(this, otherCiv.civName)
|
||||
.apply { diplomaticStatus = DiplomaticStatus.Peace }
|
||||
|
@ -437,10 +278,11 @@ class CivilizationInfo {
|
|||
updateDetailedCivResources()
|
||||
}
|
||||
|
||||
fun updateHasActiveGreatWall(){
|
||||
hasActiveGreatWall = !tech.isResearched("Dynamite") &&
|
||||
getBuildingUniques().contains("Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)")
|
||||
}
|
||||
// implementation in a seperate class, to not clog up CivInfo
|
||||
fun setCitiesConnectedToCapitalTransients() = transients().setCitiesConnectedToCapitalTransients()
|
||||
fun updateHasActiveGreatWall() = transients().updateHasActiveGreatWall()
|
||||
fun updateViewableTiles() = transients().updateViewableTiles()
|
||||
fun updateDetailedCivResources() = transients().updateDetailedCivResources()
|
||||
|
||||
fun startTurn(){
|
||||
updateStatsForNextTurn() // for things that change when turn passes e.g. golden age, city state influence
|
||||
|
@ -534,63 +376,6 @@ class CivilizationInfo {
|
|||
newCity.cityConstructions.chooseNextConstruction()
|
||||
}
|
||||
|
||||
fun setCitiesConnectedToCapitalTransients(){
|
||||
if(cities.isEmpty()) return // eg barbarians
|
||||
|
||||
// We map which cities we've reached, to the mediums they've been reached by -
|
||||
// this is so we know that if we've seen which cities can be connected by port A, and one
|
||||
// of those is city B, then we don't need to check the cities that B can connect to by port,
|
||||
// since we'll get the same cities we got from A, since they're connected to the same sea.
|
||||
val citiesReachedToMediums = HashMap<CityInfo,ArrayList<String>>()
|
||||
var citiesToCheck = mutableListOf(getCapital())
|
||||
citiesReachedToMediums[getCapital()] = arrayListOf("Start")
|
||||
val allCivCities = gameInfo.civilizations.flatMap { it.cities }
|
||||
|
||||
while(citiesToCheck.isNotEmpty() && citiesReachedToMediums.size<allCivCities.size){
|
||||
val newCitiesToCheck = mutableListOf<CityInfo>()
|
||||
for(cityToConnectFrom in citiesToCheck){
|
||||
val reachedMediums = citiesReachedToMediums[cityToConnectFrom]!!
|
||||
|
||||
// This is copypasta and can be cleaned up
|
||||
if(!reachedMediums.contains("Road")){
|
||||
|
||||
val roadBfs = BFS(cityToConnectFrom.getCenterTile()){it.roadStatus!=RoadStatus.None}
|
||||
roadBfs.stepToEnd()
|
||||
val reachedCities = allCivCities.filter { roadBfs.tilesReached.containsKey(it.getCenterTile())}
|
||||
for(reachedCity in reachedCities){
|
||||
if(!citiesReachedToMediums.containsKey(reachedCity)){
|
||||
newCitiesToCheck.add(reachedCity)
|
||||
citiesReachedToMediums[reachedCity] = arrayListOf()
|
||||
}
|
||||
val cityReachedByMediums = citiesReachedToMediums[reachedCity]!!
|
||||
if(!cityReachedByMediums.contains("Road"))
|
||||
cityReachedByMediums.add("Road")
|
||||
}
|
||||
citiesReachedToMediums[cityToConnectFrom]!!.add("Road")
|
||||
}
|
||||
|
||||
if(!reachedMediums.contains("Harbor")
|
||||
&& cityToConnectFrom.cityConstructions.containsBuildingOrEquivalent("Harbor")){
|
||||
val seaBfs = BFS(cityToConnectFrom.getCenterTile()){it.isWater || it.isCityCenter()}
|
||||
seaBfs.stepToEnd()
|
||||
val reachedCities = allCivCities.filter { seaBfs.tilesReached.containsKey(it.getCenterTile())}
|
||||
for(reachedCity in reachedCities){
|
||||
if(!citiesReachedToMediums.containsKey(reachedCity)){
|
||||
newCitiesToCheck.add(reachedCity)
|
||||
citiesReachedToMediums[reachedCity] = arrayListOf()
|
||||
}
|
||||
val cityReachedByMediums = citiesReachedToMediums[reachedCity]!!
|
||||
if(!cityReachedByMediums.contains("Harbor"))
|
||||
cityReachedByMediums.add("Harbor")
|
||||
}
|
||||
citiesReachedToMediums[cityToConnectFrom]!!.add("Harbor")
|
||||
}
|
||||
}
|
||||
citiesToCheck = newCitiesToCheck
|
||||
}
|
||||
|
||||
citiesConnectedToCapital = citiesReachedToMediums.keys.toList()
|
||||
}
|
||||
|
||||
fun destroy(){
|
||||
for(civ in gameInfo.civilizations)
|
||||
|
|
|
@ -140,12 +140,15 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
|||
happinessTable.defaults().pad(5f)
|
||||
happinessTable.add("Happiness".toLabel().setFontSize(24)).colspan(2).row()
|
||||
happinessTable.addSeparator()
|
||||
for (entry in currentPlayerCivInfo.getHappinessBreakdown()) {
|
||||
|
||||
val happinessBreakdown = currentPlayerCivInfo.stats().getHappinessBreakdown()
|
||||
|
||||
for (entry in happinessBreakdown) {
|
||||
happinessTable.add(entry.key.tr())
|
||||
happinessTable.add(entry.value.roundToInt().toString()).row()
|
||||
}
|
||||
happinessTable.add("Total".tr())
|
||||
happinessTable.add(currentPlayerCivInfo.getHappinessBreakdown().values.sum().roundToInt().toString())
|
||||
happinessTable.add(happinessBreakdown.values.sum().roundToInt().toString())
|
||||
happinessTable.pack()
|
||||
return happinessTable
|
||||
}
|
||||
|
@ -156,7 +159,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
|||
goldTable.add("Gold".toLabel().setFontSize(24)).colspan(2).row()
|
||||
goldTable.addSeparator()
|
||||
var total=0f
|
||||
for (entry in currentPlayerCivInfo.getStatMapForNextTurn()) {
|
||||
for (entry in currentPlayerCivInfo.stats().getStatMapForNextTurn()) {
|
||||
if(entry.value.gold==0f) continue
|
||||
goldTable.add(entry.key.tr())
|
||||
goldTable.add(entry.value.gold.roundToInt().toString()).row()
|
||||
|
@ -174,7 +177,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
|||
scienceTable.defaults().pad(5f)
|
||||
scienceTable.add("Science".toLabel().setFontSize(24)).colspan(2).row()
|
||||
scienceTable.addSeparator()
|
||||
val scienceStats = currentPlayerCivInfo.getStatMapForNextTurn()
|
||||
val scienceStats = currentPlayerCivInfo.stats().getStatMapForNextTurn()
|
||||
.filter { it.value.science!=0f }
|
||||
for (entry in scienceStats) {
|
||||
scienceTable.add(entry.key.tr())
|
||||
|
|
|
@ -289,11 +289,16 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||
val tilesInMoveRange = if(isAirUnit) unit.getTile().getTilesInDistance(unit.getRange())
|
||||
else unit.getDistanceToTiles().keys
|
||||
|
||||
if(isAirUnit)
|
||||
for(tile in tilesInMoveRange)
|
||||
tileGroups[tile]!!.showCircle(Color.BLUE,0.3f)
|
||||
|
||||
for (tile: TileInfo in tilesInMoveRange)
|
||||
if (unit.canMoveTo(tile))
|
||||
tileGroups[tile]!!.showCircle(Color.WHITE,
|
||||
if (UnCivGame.Current.settings.singleTapMove || isAirUnit) 0.7f else 0.3f)
|
||||
|
||||
|
||||
val unitType = unit.type
|
||||
val attackableTiles: List<TileInfo> = if (unitType.isCivilian()) listOf()
|
||||
else {
|
||||
|
|
BIN
extraImages/PatreonImage.png
Normal file
BIN
extraImages/PatreonImage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 610 KiB |
Loading…
Reference in a new issue