mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 22:06:05 -04:00
AI always uses great prophets if it has one & fixes them standing around in enemy land tiles (#7040)
This commit is contained in:
parent
22c8b033c9
commit
14f85e7c33
@ -239,7 +239,11 @@ object SpecificUnitAutomation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun automateImprovementPlacer(unit: MapUnit) {
|
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]
|
val improvement = unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementName]
|
||||||
?: return
|
?: return
|
||||||
val relatedStat = improvement.maxByOrNull { it.value }?.key ?: Stat.Culture
|
val relatedStat = improvement.maxByOrNull { it.value }?.key ?: Stat.Culture
|
||||||
@ -293,22 +297,22 @@ object SpecificUnitAutomation {
|
|||||||
if (unit.religion != unit.civInfo.religionManager.religion?.name)
|
if (unit.religion != unit.civInfo.religionManager.religion?.name)
|
||||||
return unit.destroy()
|
return unit.destroy()
|
||||||
|
|
||||||
val cities = unit.civInfo.gameInfo.getCities().asSequence()
|
val city = unit.civInfo.gameInfo.getCities().asSequence()
|
||||||
.filter { it.religion.getMajorityReligion()?.name != unit.getReligionDisplayName() }
|
.filter { it.religion.getMajorityReligion()?.name != unit.getReligionDisplayName() }
|
||||||
.filterNot { it.civInfo.isAtWarWith(unit.civInfo) }
|
.filterNot { it.civInfo.isAtWarWith(unit.civInfo) }
|
||||||
.minByOrNull { it.getCenterTile().aerialDistanceTo(unit.currentTile) } ?: return
|
.minByOrNull { it.getCenterTile().aerialDistanceTo(unit.currentTile) } ?: return
|
||||||
|
|
||||||
|
|
||||||
val destination = cities.getTiles().asSequence()
|
val destination = city.getTiles().asSequence()
|
||||||
.filterNot { unit.getTile().owningCity == it.owningCity } // to prevent the ai from moving around randomly
|
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
|
||||||
.filter { unit.movement.canMoveTo(it) }
|
|
||||||
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
||||||
.firstOrNull { unit.movement.canReach(it) } ?: return
|
.firstOrNull { unit.movement.canReach(it) } ?: return
|
||||||
|
|
||||||
unit.movement.headTowards(destination)
|
unit.movement.headTowards(destination)
|
||||||
|
|
||||||
if (unit.currentTile.owningCity?.religion?.getMajorityReligion()?.name != unit.religion)
|
if (unit.civInfo.religionManager.maySpreadReligionNow(unit)) {
|
||||||
doReligiousAction(unit, unit.getTile())
|
doReligiousAction(unit, unit.getTile())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun automateInquisitor(unit: MapUnit) {
|
fun automateInquisitor(unit: MapUnit) {
|
||||||
@ -326,16 +330,14 @@ object SpecificUnitAutomation {
|
|||||||
|
|
||||||
if (cityToProtect != null) {
|
if (cityToProtect != null) {
|
||||||
destination = cityToProtect.getCenterTile().neighbors.asSequence()
|
destination = cityToProtect.getCenterTile().neighbors.asSequence()
|
||||||
.filterNot { unit.getTile().owningCity == it.owningCity } // to prevent the ai from moving around randomly
|
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
|
||||||
.filter { unit.movement.canMoveTo(it) }
|
|
||||||
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
||||||
.firstOrNull { unit.movement.canReach(it) }
|
.firstOrNull { unit.movement.canReach(it) }
|
||||||
}
|
}
|
||||||
if (destination == null) {
|
if (destination == null) {
|
||||||
if (cityToConvert == null) return
|
if (cityToConvert == null) return
|
||||||
destination = cityToConvert.getCenterTile().neighbors.asSequence()
|
destination = cityToConvert.getCenterTile().neighbors.asSequence()
|
||||||
.filterNot { unit.getTile().owningCity == it.owningCity } // to prevent the ai from moving around randomly
|
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
|
||||||
.filter { unit.movement.canMoveTo(it) }
|
|
||||||
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
||||||
.firstOrNull { unit.movement.canReach(it) }
|
.firstOrNull { unit.movement.canReach(it) }
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ object UnitAutomation {
|
|||||||
val tileWithRuinOrEncampment = unitDistanceToTiles.keys
|
val tileWithRuinOrEncampment = unitDistanceToTiles.keys
|
||||||
.firstOrNull {
|
.firstOrNull {
|
||||||
(
|
(
|
||||||
(it.improvement != null && it.getTileImprovement()!!.isAncientRuinsEquivalent())
|
(it.improvement != null && it.getTileImprovement()!!.isAncientRuinsEquivalent())
|
||||||
|| it.improvement == Constants.barbarianEncampment
|
|| it.improvement == Constants.barbarianEncampment
|
||||||
)
|
)
|
||||||
&& unit.movement.canMoveTo(it)
|
&& unit.movement.canMoveTo(it)
|
||||||
@ -131,7 +131,7 @@ object UnitAutomation {
|
|||||||
|
|
||||||
if (unit.isCivilian()) {
|
if (unit.isCivilian()) {
|
||||||
if (tryRunAwayIfNeccessary(unit)) return
|
if (tryRunAwayIfNeccessary(unit)) return
|
||||||
|
|
||||||
if (unit.hasUnique(UniqueType.FoundCity))
|
if (unit.hasUnique(UniqueType.FoundCity))
|
||||||
return SpecificUnitAutomation.automateSettlerActions(unit)
|
return SpecificUnitAutomation.automateSettlerActions(unit)
|
||||||
|
|
||||||
@ -167,19 +167,22 @@ object UnitAutomation {
|
|||||||
if (unit.hasCitadelPlacementUnique || unit.hasStrengthBonusInRadiusUnique)
|
if (unit.hasCitadelPlacementUnique || unit.hasStrengthBonusInRadiusUnique)
|
||||||
return SpecificUnitAutomation.automateGreatGeneralFallback(unit)
|
return SpecificUnitAutomation.automateGreatGeneralFallback(unit)
|
||||||
|
|
||||||
if (unit.hasUnique(UniqueType.ConstructImprovementConsumingUnit))
|
if (unit.getMatchingUniques(UniqueType.CanActionSeveralTimes).any{ it.params[0] == "Spread Religion" }
|
||||||
return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units
|
&& unit.civInfo.religionManager.maySpreadReligionAtAll(unit))
|
||||||
|
|
||||||
if (unit.getMatchingUniques(UniqueType.CanActionSeveralTimes).any{ it.params[0] == "Spread Religion" })
|
|
||||||
return SpecificUnitAutomation.automateMissionary(unit)
|
return SpecificUnitAutomation.automateMissionary(unit)
|
||||||
|
|
||||||
if (unit.hasUnique(UniqueType.PreventSpreadingReligion))
|
if (unit.hasUnique(UniqueType.PreventSpreadingReligion))
|
||||||
return SpecificUnitAutomation.automateInquisitor(unit)
|
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.)
|
// 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
|
return // The AI doesn't know how to handle unknown civilian units
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +194,7 @@ object UnitAutomation {
|
|||||||
|
|
||||||
if (unit.baseUnit.isNuclearWeapon())
|
if (unit.baseUnit.isNuclearWeapon())
|
||||||
return SpecificUnitAutomation.automateNukes(unit)
|
return SpecificUnitAutomation.automateNukes(unit)
|
||||||
|
|
||||||
if (unit.hasUnique(UniqueType.SelfDestructs))
|
if (unit.hasUnique(UniqueType.SelfDestructs))
|
||||||
return SpecificUnitAutomation.automateMissile(unit)
|
return SpecificUnitAutomation.automateMissile(unit)
|
||||||
|
|
||||||
@ -301,7 +304,7 @@ object UnitAutomation {
|
|||||||
.map { it.getCenterTile() }
|
.map { it.getCenterTile() }
|
||||||
.filter { unit.movement.canMoveTo(it) }
|
.filter { unit.movement.canMoveTo(it) }
|
||||||
if (emptyCities.none()) return false // Nowhere to move to heal
|
if (emptyCities.none()) return false // Nowhere to move to heal
|
||||||
|
|
||||||
val nextTileToMove = unitDistanceToTiles.keys
|
val nextTileToMove = unitDistanceToTiles.keys
|
||||||
.filter { unit.movement.canMoveTo(it) }
|
.filter { unit.movement.canMoveTo(it) }
|
||||||
.minByOrNull { tile ->
|
.minByOrNull { tile ->
|
||||||
@ -309,7 +312,7 @@ object UnitAutomation {
|
|||||||
city.aerialDistanceTo(tile)
|
city.aerialDistanceTo(tile)
|
||||||
}
|
}
|
||||||
} ?: return false
|
} ?: return false
|
||||||
|
|
||||||
unit.movement.moveToTile(nextTileToMove)
|
unit.movement.moveToTile(nextTileToMove)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -445,7 +448,7 @@ object UnitAutomation {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun headTowardsEnemyCity(unit: MapUnit, closestReachableEnemyCity: TileInfo): Boolean {
|
private fun headTowardsEnemyCity(unit: MapUnit, closestReachableEnemyCity: TileInfo): Boolean {
|
||||||
val unitDistanceToTiles = unit.movement.getDistanceToTiles()
|
val unitDistanceToTiles = unit.movement.getDistanceToTiles()
|
||||||
@ -491,14 +494,14 @@ object UnitAutomation {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryEnterOwnClosestCity(unit: MapUnit): Boolean {
|
fun tryEnterOwnClosestCity(unit: MapUnit): Boolean {
|
||||||
val closestCity = unit.civInfo.cities
|
val closestCity = unit.civInfo.cities
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.sortedBy { it.getCenterTile().aerialDistanceTo(unit.getTile()) }
|
.sortedBy { it.getCenterTile().aerialDistanceTo(unit.getTile()) }
|
||||||
.firstOrNull { unit.movement.canReach(it.getCenterTile()) }
|
.firstOrNull { unit.movement.canReach(it.getCenterTile()) }
|
||||||
?: return false // Panic!
|
?: return false // Panic!
|
||||||
|
|
||||||
unit.movement.headTowards(closestCity.getCenterTile())
|
unit.movement.headTowards(closestCity.getCenterTile())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -596,7 +599,7 @@ object UnitAutomation {
|
|||||||
unit.civInfo.addNotification("${unit.shortDisplayName()} finished exploring.", unit.currentTile.position, unit.name, "OtherIcons/Sleep")
|
unit.civInfo.addNotification("${unit.shortDisplayName()} finished exploring.", unit.currentTile.position, unit.name, "OtherIcons/Sleep")
|
||||||
unit.action = null
|
unit.action = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the civilian spends its turn hiding and not moving */
|
/** Returns whether the civilian spends its turn hiding and not moving */
|
||||||
private fun tryRunAwayIfNeccessary(unit: MapUnit): Boolean {
|
private fun tryRunAwayIfNeccessary(unit: MapUnit): Boolean {
|
||||||
// This is a little 'Bugblatter Beast of Traal': Run if we can attack an enemy
|
// 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 (enemyUnitsInWalkingDistance.isNotEmpty() && !unit.baseUnit.isMilitary()) {
|
||||||
if (unit.getTile().militaryUnit == null && !unit.getTile().isCityCenter())
|
if (unit.getTile().militaryUnit == null && !unit.getTile().isCityCenter())
|
||||||
runAway(unit)
|
runAway(unit)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,8 +627,8 @@ object UnitAutomation {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val defensiveUnit = reachableTiles.keys
|
val defensiveUnit = reachableTiles.keys
|
||||||
.firstOrNull {
|
.firstOrNull {
|
||||||
it.militaryUnit != null && it.militaryUnit!!.civInfo == unit.civInfo && it.civilianUnit == null
|
it.militaryUnit != null && it.militaryUnit!!.civInfo == unit.civInfo && it.civilianUnit == null
|
||||||
}
|
}
|
||||||
if (defensiveUnit != null) {
|
if (defensiveUnit != null) {
|
||||||
unit.movement.moveToTile(defensiveUnit)
|
unit.movement.moveToTile(defensiveUnit)
|
||||||
@ -646,7 +649,7 @@ object UnitAutomation {
|
|||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun containsEnemyMilitaryUnit(unit: MapUnit, tileInfo: TileInfo) =
|
private fun containsEnemyMilitaryUnit(unit: MapUnit, tileInfo: TileInfo) =
|
||||||
tileInfo.militaryUnit != null
|
tileInfo.militaryUnit != null
|
||||||
&& tileInfo.militaryUnit!!.civInfo.isAtWarWith(unit.civInfo)
|
&& tileInfo.militaryUnit!!.civInfo.isAtWarWith(unit.civInfo)
|
||||||
|
|
||||||
|
@ -319,6 +319,23 @@ class ReligionManager {
|
|||||||
religionState = ReligionState.EnhancedReligion
|
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 {
|
fun numberOfCitiesFollowingThisReligion(): Int {
|
||||||
if (religion == null) return 0
|
if (religion == null) return 0
|
||||||
return civInfo.gameInfo.getCities()
|
return civInfo.gameInfo.getCities()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user