mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-30 23:41:03 -04:00
Removed ALL hardcoded decisions in worker AI - we're now fully moddable! (#6003)
I tested this out with RekMOD, 150 simulated turns, to see if this was working. Not only did I discover that workers were squatting on Antiquity Sites since they had resource improvements that they couldn't build, I also discovered something much worse. Even after fixing that, most cities were woefully underimproved. Turns out, the construction automation would limit worker construction to a measly *3 workers* even for a *10 city* civ! After removing this limitation and making civs aim for a 1:1 ratio between cities and workers, everything started looking much, much better. I'm not sure what the exact effect on the AI will be but I'm _sure_ that this leads to a major improvement. More improved tiles means more stats means more everything.
This commit is contained in:
parent
feb9b19d11
commit
080fc245d8
@ -168,12 +168,9 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
&& it.isBuildable(cityConstructions)
|
&& it.isBuildable(cityConstructions)
|
||||||
&& Automation.allowSpendingResource(civInfo, it) }
|
&& Automation.allowSpendingResource(civInfo, it) }
|
||||||
if (workerEquivalents.isEmpty()) return // for mods with no worker units
|
if (workerEquivalents.isEmpty()) return // for mods with no worker units
|
||||||
if (civInfo.getIdleUnits().any { it.isAutomated() && it.hasUniqueToBuildImprovements })
|
|
||||||
return // If we have automated workers who have no work to do then it's silly to construct new workers.
|
|
||||||
|
|
||||||
val citiesCountedTowardsWorkers = min(5, cities) // above 5 cities, extra cities won't make us want more workers
|
if (workers < cities) {
|
||||||
if (workers < citiesCountedTowardsWorkers * 0.6f && civUnits.none { it.hasUniqueToBuildImprovements && it.isIdle() }) {
|
var modifier = cities / (workers + 0.1f) // The worse our worker to city ratio is, the more desperate we are
|
||||||
var modifier = citiesCountedTowardsWorkers / (workers + 0.1f)
|
|
||||||
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
|
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
|
||||||
addChoice(relativeCostEffectiveness, workerEquivalents.minByOrNull { it.cost }!!.name, modifier)
|
addChoice(relativeCostEffectiveness, workerEquivalents.minByOrNull { it.cost }!!.name, modifier)
|
||||||
}
|
}
|
||||||
|
@ -333,15 +333,21 @@ class WorkerAutomation(
|
|||||||
private fun chooseImprovement(unit: MapUnit, tile: TileInfo): TileImprovement? {
|
private fun chooseImprovement(unit: MapUnit, tile: TileInfo): TileImprovement? {
|
||||||
|
|
||||||
// turnsToBuild is what defines them as buildable
|
// turnsToBuild is what defines them as buildable
|
||||||
val tileImprovements = ruleSet.tileImprovements.filter {
|
val potentialTileImprovements = ruleSet.tileImprovements.filter {
|
||||||
it.value.turnsToBuild != 0 && tile.canImprovementBeBuiltHere(it.value, tile.hasViewableResource(civInfo)) }
|
unit.canBuildImprovement(it.value, tile)
|
||||||
val uniqueImprovement = tileImprovements.values
|
&& tile.canImprovementBeBuiltHere(it.value, tile.hasViewableResource(civInfo))
|
||||||
.firstOrNull { it.uniqueTo == civInfo.civName }
|
&& (it.value.uniqueTo == null || it.value.uniqueTo == unit.civInfo.civName)
|
||||||
|
}
|
||||||
|
if (potentialTileImprovements.isEmpty()) return null
|
||||||
|
|
||||||
val currentlyBuildableImprovements = tileImprovements.values.filter { tile.canBuildImprovement(it, civInfo) }
|
val uniqueImprovement = potentialTileImprovements.values.asSequence()
|
||||||
val bestBuildableImprovement = currentlyBuildableImprovements.map { Pair(it, Automation.rankStatsValue(it, civInfo)) }
|
.filter { it.uniqueTo == civInfo.civName }
|
||||||
.filter { it.second > 0f }
|
.maxByOrNull { Automation.rankStatsValue(it, unit.civInfo) }
|
||||||
.maxByOrNull { it.second }?.first
|
|
||||||
|
val bestBuildableImprovement = potentialTileImprovements.values.asSequence()
|
||||||
|
.map { Pair(it, Automation.rankStatsValue(it, civInfo)) }
|
||||||
|
.filter { it.second > 0f }
|
||||||
|
.maxByOrNull { it.second }?.first
|
||||||
|
|
||||||
val lastTerrain = tile.getLastTerrain()
|
val lastTerrain = tile.getLastTerrain()
|
||||||
|
|
||||||
@ -358,7 +364,12 @@ class WorkerAutomation(
|
|||||||
|
|
||||||
val improvementString = when {
|
val improvementString = when {
|
||||||
tile.improvementInProgress != null -> tile.improvementInProgress!!
|
tile.improvementInProgress != null -> tile.improvementInProgress!!
|
||||||
improvementStringForResource != null && tileImprovements.containsKey(improvementStringForResource) -> improvementStringForResource
|
improvementStringForResource != null -> {
|
||||||
|
if (potentialTileImprovements.containsKey(improvementStringForResource))
|
||||||
|
improvementStringForResource
|
||||||
|
// if this is a resource that HAS an improvement, but this unit can't build it, don't waste your time
|
||||||
|
else return null
|
||||||
|
}
|
||||||
tile.containsGreatImprovement() -> return null
|
tile.containsGreatImprovement() -> return null
|
||||||
tile.containsUnfinishedGreatImprovement() -> return null
|
tile.containsUnfinishedGreatImprovement() -> return null
|
||||||
|
|
||||||
@ -367,20 +378,12 @@ class WorkerAutomation(
|
|||||||
!civInfo.isPlayerCivilization() && evaluateFortPlacement(tile, civInfo,false) -> Constants.fort
|
!civInfo.isPlayerCivilization() && evaluateFortPlacement(tile, civInfo,false) -> Constants.fort
|
||||||
// I think we can assume that the unique improvement is better
|
// I think we can assume that the unique improvement is better
|
||||||
uniqueImprovement != null && tile.canBuildImprovement(uniqueImprovement, civInfo)
|
uniqueImprovement != null && tile.canBuildImprovement(uniqueImprovement, civInfo)
|
||||||
&& unit.canBuildImprovement(uniqueImprovement, tile) ->
|
-> uniqueImprovement.name
|
||||||
uniqueImprovement.name
|
|
||||||
|
|
||||||
lastTerrain.let {
|
lastTerrain.let {
|
||||||
isUnbuildableAndRemovable(it) &&
|
isUnbuildableAndRemovable(it) &&
|
||||||
(Automation.rankStatsValue(it, civInfo) < 0 || it.hasUnique(UniqueType.NullifyYields) )
|
(Automation.rankStatsValue(it, civInfo) < 0 || it.hasUnique(UniqueType.NullifyYields) )
|
||||||
} -> Constants.remove + lastTerrain.name
|
} -> Constants.remove + lastTerrain.name
|
||||||
tile.terrainFeatures.contains(Constants.jungle) -> Constants.tradingPost
|
|
||||||
tile.terrainFeatures.contains("Oasis") -> return null
|
|
||||||
tile.terrainFeatures.contains(Constants.forest) && tileImprovements.containsKey("Lumber mill") -> "Lumber mill"
|
|
||||||
tile.isHill() && tileImprovements.containsKey("Mine") -> "Mine"
|
|
||||||
tile.baseTerrain in listOf(Constants.grassland, Constants.desert, Constants.plains)
|
|
||||||
&& tileImprovements.containsKey("Farm") -> "Farm"
|
|
||||||
tile.isAdjacentToFreshwater && tileImprovements.containsKey("Farm") -> "Farm"
|
|
||||||
|
|
||||||
bestBuildableImprovement != null -> bestBuildableImprovement.name
|
bestBuildableImprovement != null -> bestBuildableImprovement.name
|
||||||
else -> return null
|
else -> return null
|
||||||
|
@ -1115,8 +1115,9 @@ class MapUnit {
|
|||||||
&& improvement.name != Constants.cancelImprovementOrder
|
&& improvement.name != Constants.cancelImprovementOrder
|
||||||
&& tile.improvementInProgress != improvement.name
|
&& tile.improvementInProgress != improvement.name
|
||||||
) return false
|
) return false
|
||||||
val matchingUniques = getMatchingUniques(UniqueType.BuildImprovements)
|
|
||||||
return matchingUniques.any { improvement.matchesFilter(it.params[0]) || tile.matchesTerrainFilter(it.params[0]) }
|
return getMatchingUniques(UniqueType.BuildImprovements)
|
||||||
|
.any { improvement.matchesFilter(it.params[0]) || tile.matchesTerrainFilter(it.params[0]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getReligionDisplayName(): String? {
|
fun getReligionDisplayName(): String? {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user