AI always uses great prophets if it has one & fixes them standing around in enemy land tiles (#7040)

This commit is contained in:
OptimizedForDensity
2022-06-04 09:12:24 -04:00
committed by GitHub
parent 22c8b033c9
commit 14f85e7c33
3 changed files with 51 additions and 29 deletions

View File

@ -239,7 +239,11 @@ object SpecificUnitAutomation {
}
fun automateImprovementPlacer(unit: MapUnit) {
val improvementName = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit).first().params[0]
var improvementBuildingUniques = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
if (unit.religiousActionsUnitCanDo().all { unit.abilityUsesLeft[it] == unit.maxAbilityUses[it] })
improvementBuildingUniques += unit.getMatchingUniques(UniqueType.CanConstructIfNoOtherActions)
val improvementName = improvementBuildingUniques.first().params[0]
val improvement = unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementName]
?: return
val relatedStat = improvement.maxByOrNull { it.value }?.key ?: Stat.Culture
@ -293,22 +297,22 @@ object SpecificUnitAutomation {
if (unit.religion != unit.civInfo.religionManager.religion?.name)
return unit.destroy()
val cities = unit.civInfo.gameInfo.getCities().asSequence()
val city = unit.civInfo.gameInfo.getCities().asSequence()
.filter { it.religion.getMajorityReligion()?.name != unit.getReligionDisplayName() }
.filterNot { it.civInfo.isAtWarWith(unit.civInfo) }
.minByOrNull { it.getCenterTile().aerialDistanceTo(unit.currentTile) } ?: return
val destination = cities.getTiles().asSequence()
.filterNot { unit.getTile().owningCity == it.owningCity } // to prevent the ai from moving around randomly
.filter { unit.movement.canMoveTo(it) }
val destination = city.getTiles().asSequence()
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
.firstOrNull { unit.movement.canReach(it) } ?: return
unit.movement.headTowards(destination)
if (unit.currentTile.owningCity?.religion?.getMajorityReligion()?.name != unit.religion)
if (unit.civInfo.religionManager.maySpreadReligionNow(unit)) {
doReligiousAction(unit, unit.getTile())
}
}
fun automateInquisitor(unit: MapUnit) {
@ -326,16 +330,14 @@ object SpecificUnitAutomation {
if (cityToProtect != null) {
destination = cityToProtect.getCenterTile().neighbors.asSequence()
.filterNot { unit.getTile().owningCity == it.owningCity } // to prevent the ai from moving around randomly
.filter { unit.movement.canMoveTo(it) }
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
.firstOrNull { unit.movement.canReach(it) }
}
if (destination == null) {
if (cityToConvert == null) return
destination = cityToConvert.getCenterTile().neighbors.asSequence()
.filterNot { unit.getTile().owningCity == it.owningCity } // to prevent the ai from moving around randomly
.filter { unit.movement.canMoveTo(it) }
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
.firstOrNull { unit.movement.canReach(it) }
}

View File

@ -52,7 +52,7 @@ object UnitAutomation {
val tileWithRuinOrEncampment = unitDistanceToTiles.keys
.firstOrNull {
(
(it.improvement != null && it.getTileImprovement()!!.isAncientRuinsEquivalent())
(it.improvement != null && it.getTileImprovement()!!.isAncientRuinsEquivalent())
|| it.improvement == Constants.barbarianEncampment
)
&& unit.movement.canMoveTo(it)
@ -131,7 +131,7 @@ object UnitAutomation {
if (unit.isCivilian()) {
if (tryRunAwayIfNeccessary(unit)) return
if (unit.hasUnique(UniqueType.FoundCity))
return SpecificUnitAutomation.automateSettlerActions(unit)
@ -167,19 +167,22 @@ object UnitAutomation {
if (unit.hasCitadelPlacementUnique || unit.hasStrengthBonusInRadiusUnique)
return SpecificUnitAutomation.automateGreatGeneralFallback(unit)
if (unit.hasUnique(UniqueType.ConstructImprovementConsumingUnit))
return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units
if (unit.getMatchingUniques(UniqueType.CanActionSeveralTimes).any{ it.params[0] == "Spread Religion" })
if (unit.getMatchingUniques(UniqueType.CanActionSeveralTimes).any{ it.params[0] == "Spread Religion" }
&& unit.civInfo.religionManager.maySpreadReligionAtAll(unit))
return SpecificUnitAutomation.automateMissionary(unit)
if (unit.hasUnique(UniqueType.PreventSpreadingReligion))
return SpecificUnitAutomation.automateInquisitor(unit)
if (unit.hasUnique(UniqueType.ConstructImprovementConsumingUnit)
|| (unit.hasUnique(UniqueType.CanConstructIfNoOtherActions)
&& unit.religiousActionsUnitCanDo().all { unit.abilityUsesLeft[it] == unit.maxAbilityUses[it] }))
// catch great prophet for civs who can't found/enhance/spread religion
return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units
// ToDo: automation of great people skills (may speed up construction, provides a science boost, etc.)
return // The AI doesn't know how to handle unknown civilian units
}
@ -191,7 +194,7 @@ object UnitAutomation {
if (unit.baseUnit.isNuclearWeapon())
return SpecificUnitAutomation.automateNukes(unit)
if (unit.hasUnique(UniqueType.SelfDestructs))
return SpecificUnitAutomation.automateMissile(unit)
@ -301,7 +304,7 @@ object UnitAutomation {
.map { it.getCenterTile() }
.filter { unit.movement.canMoveTo(it) }
if (emptyCities.none()) return false // Nowhere to move to heal
val nextTileToMove = unitDistanceToTiles.keys
.filter { unit.movement.canMoveTo(it) }
.minByOrNull { tile ->
@ -309,7 +312,7 @@ object UnitAutomation {
city.aerialDistanceTo(tile)
}
} ?: return false
unit.movement.moveToTile(nextTileToMove)
return true
}
@ -445,7 +448,7 @@ object UnitAutomation {
}
return false
}
private fun headTowardsEnemyCity(unit: MapUnit, closestReachableEnemyCity: TileInfo): Boolean {
val unitDistanceToTiles = unit.movement.getDistanceToTiles()
@ -491,14 +494,14 @@ object UnitAutomation {
return true
}
fun tryEnterOwnClosestCity(unit: MapUnit): Boolean {
val closestCity = unit.civInfo.cities
.asSequence()
.sortedBy { it.getCenterTile().aerialDistanceTo(unit.getTile()) }
.firstOrNull { unit.movement.canReach(it.getCenterTile()) }
?: return false // Panic!
unit.movement.headTowards(closestCity.getCenterTile())
return true
}
@ -596,7 +599,7 @@ object UnitAutomation {
unit.civInfo.addNotification("${unit.shortDisplayName()} finished exploring.", unit.currentTile.position, unit.name, "OtherIcons/Sleep")
unit.action = null
}
/** Returns whether the civilian spends its turn hiding and not moving */
private fun tryRunAwayIfNeccessary(unit: MapUnit): Boolean {
// This is a little 'Bugblatter Beast of Traal': Run if we can attack an enemy
@ -608,10 +611,10 @@ object UnitAutomation {
if (enemyUnitsInWalkingDistance.isNotEmpty() && !unit.baseUnit.isMilitary()) {
if (unit.getTile().militaryUnit == null && !unit.getTile().isCityCenter())
runAway(unit)
return true
}
return false
}
@ -624,8 +627,8 @@ object UnitAutomation {
return
}
val defensiveUnit = reachableTiles.keys
.firstOrNull {
it.militaryUnit != null && it.militaryUnit!!.civInfo == unit.civInfo && it.civilianUnit == null
.firstOrNull {
it.militaryUnit != null && it.militaryUnit!!.civInfo == unit.civInfo && it.civilianUnit == null
}
if (defensiveUnit != null) {
unit.movement.moveToTile(defensiveUnit)
@ -646,7 +649,7 @@ object UnitAutomation {
return 4
}
private fun containsEnemyMilitaryUnit(unit: MapUnit, tileInfo: TileInfo) =
private fun containsEnemyMilitaryUnit(unit: MapUnit, tileInfo: TileInfo) =
tileInfo.militaryUnit != null
&& tileInfo.militaryUnit!!.civInfo.isAtWarWith(unit.civInfo)

View File

@ -319,6 +319,23 @@ class ReligionManager {
religionState = ReligionState.EnhancedReligion
}
fun maySpreadReligionAtAll(missionary: MapUnit): Boolean {
if (!civInfo.gameInfo.isReligionEnabled()) return false // No religion, no spreading
if (religion == null) return false // need a religion
if (religionState < ReligionState.Religion) return false // First found an actual religion
if (!civInfo.isMajorCiv()) return false // Only major civs
return true
}
fun maySpreadReligionNow(missionary: MapUnit): Boolean {
if (!maySpreadReligionAtAll(missionary)) return false
if (missionary.getTile().getOwner() == null) return false
if (missionary.currentTile.owningCity?.religion?.getMajorityReligion()?.name == missionary.religion)
return false
return true
}
fun numberOfCitiesFollowingThisReligion(): Int {
if (religion == null) return 0
return civInfo.gameInfo.getCities()