Code reorg - Split some functions off of civilizationInfo into their own sub-classes because it was getting too long

This commit is contained in:
Yair Morgenstern 2019-07-10 20:05:29 +03:00
parent d7cfdf3e83
commit 51ad40b8bf
7 changed files with 295 additions and 230 deletions

View file

@ -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()

View 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
}
}

View 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
}
}

View file

@ -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)

View file

@ -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())

View file

@ -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 {

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB