mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 17:28:57 +07:00
AI behaviour changes (#11839)
* AI behaviour changes * Update Automation.kt * Update Automation.kt * Update Automation.kt * Update Automation.kt * Update Automation.kt * Update ConstructionAutomation.kt * Update Automation.kt * Reverting some changes * Changes * revert changes * revert changes * revert changes * revert changes * Update CityLocationTileRanker.kt * Citizen assignment for stat conversion * Update CityLocationTileRanker.kt * Reduce AI settling * Avoid AI building units when in negative Supply * Update CityLocationTileRanker.kt * Update CityLocationTileRanker.kt * Update CityLocationTileRanker.kt * Update ConstructionAutomation.kt * Update build.gradle.kts * Update gradle-wrapper.properties * Update CityLocationTileRanker.kt * Update CityLocationTileRanker.kt * Update ConstructionAutomation.kt * Update CityLocationTileRanker.kt
This commit is contained in:
@ -9,6 +9,7 @@ import com.unciv.logic.map.mapunit.MapUnit
|
|||||||
import com.unciv.logic.map.tile.Tile
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.models.ruleset.Building
|
import com.unciv.models.ruleset.Building
|
||||||
import com.unciv.models.ruleset.INonPerpetualConstruction
|
import com.unciv.models.ruleset.INonPerpetualConstruction
|
||||||
|
import com.unciv.models.ruleset.PerpetualConstruction
|
||||||
import com.unciv.models.ruleset.Victory
|
import com.unciv.models.ruleset.Victory
|
||||||
import com.unciv.models.ruleset.nation.PersonalityValue
|
import com.unciv.models.ruleset.nation.PersonalityValue
|
||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
@ -48,6 +49,9 @@ object Automation {
|
|||||||
val yieldStats = stats.clone()
|
val yieldStats = stats.clone()
|
||||||
val civPersonality = city.civ.getPersonality()
|
val civPersonality = city.civ.getPersonality()
|
||||||
val cityStatsObj = city.cityStats
|
val cityStatsObj = city.cityStats
|
||||||
|
val civInfo = city.civ
|
||||||
|
val allTechsAreResearched = civInfo.gameInfo.ruleset.technologies.values
|
||||||
|
.all { civInfo.tech.isResearched(it.name) || !civInfo.tech.canBeResearched(it.name)}
|
||||||
|
|
||||||
if (areWeRankingSpecialist) {
|
if (areWeRankingSpecialist) {
|
||||||
// If you have the Food Bonus, count as 1 extra food production (base is 2food)
|
// If you have the Food Bonus, count as 1 extra food production (base is 2food)
|
||||||
@ -101,6 +105,21 @@ object Automation {
|
|||||||
yieldStats.happiness *= 2
|
yieldStats.happiness *= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (city.civ.getHappiness() < 0) {
|
||||||
|
// 75% of excess food is wasted when in negative happiness
|
||||||
|
yieldStats.food /= 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allTechsAreResearched) {
|
||||||
|
// Science is useless at this point
|
||||||
|
yieldStats.science *= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (city.cityConstructions.getCurrentConstruction() is PerpetualConstruction) {
|
||||||
|
// With 4:1 conversion of production to gold, production is overvalued by a factor (12*4)/8 = 6
|
||||||
|
yieldStats.production /= 6
|
||||||
|
}
|
||||||
|
|
||||||
for (stat in Stat.values()) {
|
for (stat in Stat.values()) {
|
||||||
if (city.civ.wantsToFocusOn(stat))
|
if (city.civ.wantsToFocusOn(stat))
|
||||||
yieldStats[stat] *= 2f
|
yieldStats[stat] *= 2f
|
||||||
|
@ -165,6 +165,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions) {
|
|||||||
|
|
||||||
private fun addMilitaryUnitChoice() {
|
private fun addMilitaryUnitChoice() {
|
||||||
if (!isAtWar && !cityIsOverAverageProduction) return // don't make any military units here. Infrastructure first!
|
if (!isAtWar && !cityIsOverAverageProduction) return // don't make any military units here. Infrastructure first!
|
||||||
|
if (civInfo.stats.getUnitSupplyDeficit() > 0) return // we don't want more units if it's already hurting our empire
|
||||||
|
// todo: add worker disbandment and consumption of great persons if under attack & short on unit supply
|
||||||
if (!isAtWar && (civInfo.stats.statsForNextTurn.gold < 0 || militaryUnits > max(7, cities * 5))) return
|
if (!isAtWar && (civInfo.stats.statsForNextTurn.gold < 0 || militaryUnits > max(7, cities * 5))) return
|
||||||
if (civInfo.gold < -50) return
|
if (civInfo.gold < -50) return
|
||||||
|
|
||||||
@ -263,6 +265,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions) {
|
|||||||
private fun addBuildingChoices() {
|
private fun addBuildingChoices() {
|
||||||
for (building in buildings.filterBuildable()) {
|
for (building in buildings.filterBuildable()) {
|
||||||
if (building.isWonder && city.isPuppet) continue
|
if (building.isWonder && city.isPuppet) continue
|
||||||
|
// We shouldn't try to build wonders in undeveloped empires
|
||||||
|
if (building.isWonder && civInfo.cities.size < 3) continue
|
||||||
addChoice(relativeCostEffectiveness, building.name, getValueOfBuilding(building))
|
addChoice(relativeCostEffectiveness, building.name, getValueOfBuilding(building))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,17 @@ object CityLocationTileRanker {
|
|||||||
tileValue += getDistanceToCityModifier(newCityTile, nearbyCities, civ)
|
tileValue += getDistanceToCityModifier(newCityTile, nearbyCities, civ)
|
||||||
|
|
||||||
val onCoast = newCityTile.isCoastalTile()
|
val onCoast = newCityTile.isCoastalTile()
|
||||||
|
val onHill = newCityTile.isHill()
|
||||||
|
val isNextToMountain = newCityTile.isAdjacentTo("Mountain")
|
||||||
// Only count a luxary resource that we don't have yet as unique once
|
// Only count a luxary resource that we don't have yet as unique once
|
||||||
val newUniqueLuxuryResources = HashSet<String>()
|
val newUniqueLuxuryResources = HashSet<String>()
|
||||||
|
|
||||||
if (onCoast) tileValue += 8
|
if (onCoast) tileValue += 3
|
||||||
if (newCityTile.isAdjacentToRiver()) tileValue += 10
|
// Hills are free production and defence
|
||||||
|
if (onHill) tileValue += 7
|
||||||
|
// Observatories are good, but current implementation no mod-friendly
|
||||||
|
if (isNextToMountain) tileValue += 5
|
||||||
|
if (newCityTile.isAdjacentToRiver()) tileValue += 14
|
||||||
if (newCityTile.terrainHasUnique(UniqueType.FreshWater)) tileValue += 5
|
if (newCityTile.terrainHasUnique(UniqueType.FreshWater)) tileValue += 5
|
||||||
// We want to found the city on an oasis because it can't be improved otherwise
|
// We want to found the city on an oasis because it can't be improved otherwise
|
||||||
if (newCityTile.terrainHasUnique(UniqueType.Unbuildable)) tileValue += 3
|
if (newCityTile.terrainHasUnique(UniqueType.Unbuildable)) tileValue += 3
|
||||||
@ -118,25 +124,15 @@ object CityLocationTileRanker {
|
|||||||
// If it is not higher the settler may get stuck when it ranks the same tile differently
|
// If it is not higher the settler may get stuck when it ranks the same tile differently
|
||||||
// as it moves away from the city and doesn't include it in the calculation
|
// as it moves away from the city and doesn't include it in the calculation
|
||||||
// and values it higher than when it moves closer to the city
|
// and values it higher than when it moves closer to the city
|
||||||
distanceToCity == 7 -> 5f // Perfect location, there aren't any unused tiles in between
|
distanceToCity == 7 -> 2f
|
||||||
distanceToCity == 6 -> -4f
|
distanceToCity == 6 -> 4f
|
||||||
distanceToCity == 5 -> -8f
|
distanceToCity == 5 -> 8f // Settling further away sacrifices tempo
|
||||||
distanceToCity == 4 -> -20f
|
distanceToCity == 4 -> 6f
|
||||||
distanceToCity == 3 -> -25f
|
distanceToCity == 3 -> -25f
|
||||||
distanceToCity < 3 -> -30f // Even if it is a mod that lets us settle closer, lets still not do it
|
distanceToCity < 3 -> -30f // Even if it is a mod that lets us settle closer, lets still not do it
|
||||||
else -> 0f
|
else -> 0f
|
||||||
}
|
}
|
||||||
// Bigger cities will expand more so we want to stay away from them
|
// We want a defensive ring around our capital
|
||||||
// Reduces the chance that we don't settle at the begining
|
|
||||||
distanceToCityModifier *= when {
|
|
||||||
city.population.population >= 12 -> 2f
|
|
||||||
city.population.population >= 8 -> 1.5f
|
|
||||||
city.population.population >= 3 -> 1.2f
|
|
||||||
else -> 1f
|
|
||||||
}
|
|
||||||
// It is worse to settle cities near our own compare to near another civ
|
|
||||||
// Do not settle near our capital unless really necessary
|
|
||||||
// Having a strong capital is esential to constructing wonders
|
|
||||||
if (city.civ == civ) distanceToCityModifier *= if (city.isCapital()) 2 else 1
|
if (city.civ == civ) distanceToCityModifier *= if (city.isCapital()) 2 else 1
|
||||||
modifier += distanceToCityModifier
|
modifier += distanceToCityModifier
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user