mirror of
https://github.com/yairm210/Unciv.git
synced 2025-10-02 00:15:36 -04:00
AI now more focused on improving small cities to big ones
This commit is contained in:
parent
6769c30ebe
commit
22a8a85426
@ -6,9 +6,9 @@ import com.badlogic.gdx.Input
|
|||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.GameSaver
|
import com.unciv.logic.GameSaver
|
||||||
import com.unciv.logic.GameStarter
|
import com.unciv.logic.GameStarter
|
||||||
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
import com.unciv.models.metadata.GameParameters
|
import com.unciv.models.metadata.GameParameters
|
||||||
import com.unciv.models.metadata.GameSettings
|
import com.unciv.models.metadata.GameSettings
|
||||||
import com.unciv.models.gamebasics.GameBasics
|
|
||||||
import com.unciv.ui.LanguagePickerScreen
|
import com.unciv.ui.LanguagePickerScreen
|
||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
import com.unciv.ui.worldscreen.WorldScreen
|
import com.unciv.ui.worldscreen.WorldScreen
|
||||||
|
@ -66,9 +66,9 @@ class GameSaver {
|
|||||||
val newAutosaveFilename = saveFilesFolder + File.separator + "Autosave-${gameInfo.currentPlayer}-${gameInfoClone.turns}"
|
val newAutosaveFilename = saveFilesFolder + File.separator + "Autosave-${gameInfo.currentPlayer}-${gameInfoClone.turns}"
|
||||||
getSave("Autosave").copyTo(Gdx.files.local(newAutosaveFilename))
|
getSave("Autosave").copyTo(Gdx.files.local(newAutosaveFilename))
|
||||||
|
|
||||||
val autosaves = getSaves().filter { it.startsWith("Autosave") }
|
fun getAutosaves(): List<String> { return getSaves().filter { it.startsWith("Autosave") } }
|
||||||
while(autosaves.size>10){
|
while(getAutosaves().size>10){
|
||||||
val saveToDelete = autosaves.minBy { getSave(it).lastModified() }!!
|
val saveToDelete = getAutosaves().minBy { getSave(it).lastModified() }!!
|
||||||
deleteSave(saveToDelete)
|
deleteSave(saveToDelete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import kotlin.math.sqrt
|
|||||||
class Automation {
|
class Automation {
|
||||||
|
|
||||||
internal fun rankTile(tile: TileInfo?, civInfo: CivilizationInfo): Float {
|
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)
|
val stats = tile.getTileStats(null, civInfo)
|
||||||
var rank = rankStatsValue(stats, civInfo)
|
var rank = rankStatsValue(stats, civInfo)
|
||||||
if (tile.improvement == null) rank += 0.5f // improvement potential!
|
if (tile.improvement == null) rank += 0.5f // improvement potential!
|
||||||
@ -22,9 +22,37 @@ class Automation {
|
|||||||
return rank
|
return rank
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun rankSpecialist(stats: Stats?, civInfo: CivilizationInfo): Float {
|
fun rankTileForCityWork(tile:TileInfo, city: CityInfo): Float {
|
||||||
if (stats == null) return 0.0f
|
val stats = tile.getTileStats(city, city.civInfo)
|
||||||
var rank = rankStatsValue(stats, 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
|
rank += 0.3f //GPP bonus
|
||||||
return rank
|
return rank
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,9 @@ class PopulationManager {
|
|||||||
val bestTile: TileInfo? = cityInfo.getTiles()
|
val bestTile: TileInfo? = cityInfo.getTiles()
|
||||||
.filter { it.arialDistanceTo(cityInfo.getCenterTile()) <= 3 }
|
.filter { it.arialDistanceTo(cityInfo.getCenterTile()) <= 3 }
|
||||||
.filterNot { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position}
|
.filterNot { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position}
|
||||||
.maxBy { Automation().rankTile(it,cityInfo.civInfo) }
|
.maxBy { Automation().rankTileForCityWork(it,cityInfo) }
|
||||||
val valueBestTile = Automation().rankTile(bestTile, cityInfo.civInfo)
|
val valueBestTile = if(bestTile==null) 0f
|
||||||
|
else Automation().rankTileForCityWork(bestTile, cityInfo)
|
||||||
|
|
||||||
//evaluate specialists
|
//evaluate specialists
|
||||||
val maxSpecialistsMap = getMaxSpecialists().toHashMap()
|
val maxSpecialistsMap = getMaxSpecialists().toHashMap()
|
||||||
@ -89,11 +90,11 @@ class PopulationManager {
|
|||||||
val bestJob: Stat? = specialists.toHashMap()
|
val bestJob: Stat? = specialists.toHashMap()
|
||||||
.filter {maxSpecialistsMap.containsKey(it.key) && it.value < maxSpecialistsMap[it.key]!!}
|
.filter {maxSpecialistsMap.containsKey(it.key) && it.value < maxSpecialistsMap[it.key]!!}
|
||||||
.map {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
|
var valueBestSpecialist = 0f
|
||||||
if (bestJob != null) {
|
if (bestJob != null) {
|
||||||
val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(bestJob, policies)
|
val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(bestJob, policies)
|
||||||
valueBestSpecialist = Automation().rankSpecialist(specialistStats, cityInfo.civInfo)
|
valueBestSpecialist = Automation().rankSpecialist(specialistStats, cityInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
//assign population
|
//assign population
|
||||||
@ -117,24 +118,28 @@ class PopulationManager {
|
|||||||
|
|
||||||
while (getFreePopulation()<0) {
|
while (getFreePopulation()<0) {
|
||||||
//evaluate tiles
|
//evaluate tiles
|
||||||
val worstWorkedTile: TileInfo? = cityInfo.workedTiles
|
val worstWorkedTile: TileInfo? = if(cityInfo.workedTiles.isEmpty()) null
|
||||||
.asSequence()
|
else {
|
||||||
.map { cityInfo.tileMap[it] }
|
cityInfo.workedTiles.asSequence()
|
||||||
.minBy {Automation().rankTile(it, cityInfo.civInfo)}
|
.map { cityInfo.tileMap[it] }
|
||||||
val valueWorstTile = Automation().rankTile(worstWorkedTile, cityInfo.civInfo)
|
.minBy { Automation().rankTileForCityWork(it, cityInfo) }!!
|
||||||
|
}
|
||||||
|
val valueWorstTile = if(worstWorkedTile==null) 0f
|
||||||
|
else Automation().rankTileForCityWork(worstWorkedTile, cityInfo)
|
||||||
|
|
||||||
|
|
||||||
//evaluate specialists
|
//evaluate specialists
|
||||||
val policies = cityInfo.civInfo.policies.adoptedPolicies
|
val policies = cityInfo.civInfo.policies.adoptedPolicies
|
||||||
val worstJob: Stat? = specialists.toHashMap()
|
val worstJob: Stat? = specialists.toHashMap()
|
||||||
.filter { it.value > 0 }
|
.filter { it.value > 0 }
|
||||||
.map {it.key}
|
.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
|
var valueWorstSpecialist = 0f
|
||||||
if (worstJob != null)
|
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
|
//un-assign population
|
||||||
if ((valueWorstTile < valueWorstSpecialist && worstWorkedTile != null)
|
if ((worstWorkedTile != null && valueWorstTile < valueWorstSpecialist)
|
||||||
|| worstJob == null) {
|
|| worstJob == null) {
|
||||||
cityInfo.workedTiles = cityInfo.workedTiles.withoutItem(worstWorkedTile!!.position)
|
cityInfo.workedTiles = cityInfo.workedTiles.withoutItem(worstWorkedTile!!.position)
|
||||||
} else {
|
} else {
|
||||||
|
@ -89,7 +89,7 @@ open class TileInfo {
|
|||||||
|
|
||||||
|
|
||||||
// This is for performance - since we access the neighbors of a tile ALL THE TIME,
|
// 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
|
@Transient private var internalNeighbors : List<TileInfo>?=null
|
||||||
val neighbors: List<TileInfo>
|
val neighbors: List<TileInfo>
|
||||||
get(){
|
get(){
|
||||||
@ -99,9 +99,9 @@ open class TileInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getHeight(): Int {
|
fun getHeight(): Int {
|
||||||
if (baseTerrain==Constants.mountain) return 4
|
if (baseTerrain == Constants.mountain) return 4
|
||||||
if (baseTerrain == Constants.hill) return 2
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user