diff --git a/core/src/com/unciv/UnCivGame.kt b/core/src/com/unciv/UnCivGame.kt index 07fe5faf57..ec229394fb 100644 --- a/core/src/com/unciv/UnCivGame.kt +++ b/core/src/com/unciv/UnCivGame.kt @@ -6,9 +6,9 @@ import com.badlogic.gdx.Input import com.unciv.logic.GameInfo import com.unciv.logic.GameSaver import com.unciv.logic.GameStarter +import com.unciv.models.gamebasics.GameBasics import com.unciv.models.metadata.GameParameters import com.unciv.models.metadata.GameSettings -import com.unciv.models.gamebasics.GameBasics import com.unciv.ui.LanguagePickerScreen import com.unciv.ui.utils.ImageGetter import com.unciv.ui.worldscreen.WorldScreen diff --git a/core/src/com/unciv/logic/GameSaver.kt b/core/src/com/unciv/logic/GameSaver.kt index db7a07cd0c..79048317a8 100644 --- a/core/src/com/unciv/logic/GameSaver.kt +++ b/core/src/com/unciv/logic/GameSaver.kt @@ -66,9 +66,9 @@ class GameSaver { val newAutosaveFilename = saveFilesFolder + File.separator + "Autosave-${gameInfo.currentPlayer}-${gameInfoClone.turns}" getSave("Autosave").copyTo(Gdx.files.local(newAutosaveFilename)) - val autosaves = getSaves().filter { it.startsWith("Autosave") } - while(autosaves.size>10){ - val saveToDelete = autosaves.minBy { getSave(it).lastModified() }!! + fun getAutosaves(): List { return getSaves().filter { it.startsWith("Autosave") } } + while(getAutosaves().size>10){ + val saveToDelete = getAutosaves().minBy { getSave(it).lastModified() }!! deleteSave(saveToDelete) } diff --git a/core/src/com/unciv/logic/automation/Automation.kt b/core/src/com/unciv/logic/automation/Automation.kt index 05e700d5cc..c951d3bd00 100644 --- a/core/src/com/unciv/logic/automation/Automation.kt +++ b/core/src/com/unciv/logic/automation/Automation.kt @@ -14,7 +14,7 @@ import kotlin.math.sqrt class Automation { internal fun rankTile(tile: TileInfo?, civInfo: CivilizationInfo): Float { - if (tile == null) return 0.0f + if (tile == null) return 0f val stats = tile.getTileStats(null, civInfo) var rank = rankStatsValue(stats, civInfo) if (tile.improvement == null) rank += 0.5f // improvement potential! @@ -22,9 +22,37 @@ class Automation { return rank } - internal fun rankSpecialist(stats: Stats?, civInfo: CivilizationInfo): Float { - if (stats == null) return 0.0f - var rank = rankStatsValue(stats, civInfo) + fun rankTileForCityWork(tile:TileInfo, city: CityInfo): Float { + val stats = tile.getTileStats(city, city.civInfo) + return rankStatsForCityWork(stats, city) + } + + private fun rankStatsForCityWork(stats: Stats, city: CityInfo): Float { + var rank = 0f + if(city.population.population < 5){ + // "small city" - we care more about food and less about global problems like gold science and culture + rank += stats.food * 1.2f + rank += stats.production + rank += stats.science/2 + rank += stats.culture/2 + rank += stats.gold / 5 // it's barely worth anything at this points + } + else{ + if (stats.food <= 2) rank += (stats.food * 1.2f) //food get more value to keep city growing + else rank += (2.4f + (stats.food - 2) / 2) // 1.2 point for each food up to 2, from there on half a point + + if (city.civInfo.gold < 0 && city.civInfo.statsForNextTurn.gold <= 0) rank += stats.gold // we have a global problem + else rank += stats.gold / 3 // 3 gold is worse than 2 production + + rank += stats.production + rank += stats.science + rank += stats.culture + } + return rank + } + + internal fun rankSpecialist(stats: Stats, cityInfo: CityInfo): Float { + var rank = rankStatsForCityWork(stats, cityInfo) rank += 0.3f //GPP bonus return rank } diff --git a/core/src/com/unciv/logic/city/PopulationManager.kt b/core/src/com/unciv/logic/city/PopulationManager.kt index f2a6ecd488..c204d4f48f 100644 --- a/core/src/com/unciv/logic/city/PopulationManager.kt +++ b/core/src/com/unciv/logic/city/PopulationManager.kt @@ -80,8 +80,9 @@ class PopulationManager { val bestTile: TileInfo? = cityInfo.getTiles() .filter { it.arialDistanceTo(cityInfo.getCenterTile()) <= 3 } .filterNot { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position} - .maxBy { Automation().rankTile(it,cityInfo.civInfo) } - val valueBestTile = Automation().rankTile(bestTile, cityInfo.civInfo) + .maxBy { Automation().rankTileForCityWork(it,cityInfo) } + val valueBestTile = if(bestTile==null) 0f + else Automation().rankTileForCityWork(bestTile, cityInfo) //evaluate specialists val maxSpecialistsMap = getMaxSpecialists().toHashMap() @@ -89,11 +90,11 @@ class PopulationManager { val bestJob: Stat? = specialists.toHashMap() .filter {maxSpecialistsMap.containsKey(it.key) && it.value < maxSpecialistsMap[it.key]!!} .map {it.key} - .maxBy { Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it, policies), cityInfo.civInfo) } + .maxBy { Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it, policies), cityInfo) } var valueBestSpecialist = 0f if (bestJob != null) { val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(bestJob, policies) - valueBestSpecialist = Automation().rankSpecialist(specialistStats, cityInfo.civInfo) + valueBestSpecialist = Automation().rankSpecialist(specialistStats, cityInfo) } //assign population @@ -117,24 +118,28 @@ class PopulationManager { while (getFreePopulation()<0) { //evaluate tiles - val worstWorkedTile: TileInfo? = cityInfo.workedTiles - .asSequence() - .map { cityInfo.tileMap[it] } - .minBy {Automation().rankTile(it, cityInfo.civInfo)} - val valueWorstTile = Automation().rankTile(worstWorkedTile, cityInfo.civInfo) + val worstWorkedTile: TileInfo? = if(cityInfo.workedTiles.isEmpty()) null + else { + cityInfo.workedTiles.asSequence() + .map { cityInfo.tileMap[it] } + .minBy { Automation().rankTileForCityWork(it, cityInfo) }!! + } + val valueWorstTile = if(worstWorkedTile==null) 0f + else Automation().rankTileForCityWork(worstWorkedTile, cityInfo) + //evaluate specialists val policies = cityInfo.civInfo.policies.adoptedPolicies val worstJob: Stat? = specialists.toHashMap() .filter { it.value > 0 } .map {it.key} - .minBy { Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it, policies), cityInfo.civInfo) } + .minBy { Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it, policies), cityInfo) } var valueWorstSpecialist = 0f if (worstJob != null) - valueWorstSpecialist = Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(worstJob, policies), cityInfo.civInfo) + valueWorstSpecialist = Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(worstJob, policies), cityInfo) //un-assign population - if ((valueWorstTile < valueWorstSpecialist && worstWorkedTile != null) + if ((worstWorkedTile != null && valueWorstTile < valueWorstSpecialist) || worstJob == null) { cityInfo.workedTiles = cityInfo.workedTiles.withoutItem(worstWorkedTile!!.position) } else { diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 919eb1d791..b8b4f22a80 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -89,7 +89,7 @@ open class TileInfo { // This is for performance - since we access the neighbors of a tile ALL THE TIME, - // and the neighbors of a tile never change, it's much more CPU efficient to save the list once and for all! + // and the neighbors of a tile never change, it's much more efficient to save the list once and for all! @Transient private var internalNeighbors : List?=null val neighbors: List get(){ @@ -99,9 +99,9 @@ open class TileInfo { } fun getHeight(): Int { - if (baseTerrain==Constants.mountain) return 4 + if (baseTerrain == Constants.mountain) return 4 if (baseTerrain == Constants.hill) return 2 - if (terrainFeature==Constants.forest || terrainFeature==Constants.jungle) return 1 + if (terrainFeature == Constants.forest || terrainFeature == Constants.jungle) return 1 return 0 }