AI now more focused on improving small cities to big ones

This commit is contained in:
Yair Morgenstern 2019-08-27 14:39:54 +03:00
parent 6769c30ebe
commit 22a8a85426
5 changed files with 56 additions and 23 deletions

View file

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

View file

@ -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<String> { return getSaves().filter { it.startsWith("Autosave") } }
while(getAutosaves().size>10){
val saveToDelete = getAutosaves().minBy { getSave(it).lastModified() }!!
deleteSave(saveToDelete)
}

View file

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

View file

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

View file

@ -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<TileInfo>?=null
val neighbors: List<TileInfo>
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
}