mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-15 02:09:21 +07:00
Added an AI for building & using spaceship parts (#6374)
This commit is contained in:
@ -26,6 +26,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
.filterNot { it.isAnyWonder() }
|
.filterNot { it.isAnyWonder() }
|
||||||
private val buildableWonders = buildableBuildings
|
private val buildableWonders = buildableBuildings
|
||||||
.filter { it.isAnyWonder() }
|
.filter { it.isAnyWonder() }
|
||||||
|
|
||||||
|
val buildableUnits = cityConstructions.getConstructableUnits()
|
||||||
|
|
||||||
val civUnits = civInfo.getCivUnits()
|
val civUnits = civInfo.getCivUnits()
|
||||||
val militaryUnits = civUnits.count { it.baseUnit.isMilitary() }
|
val militaryUnits = civUnits.count { it.baseUnit.isMilitary() }
|
||||||
@ -53,8 +55,9 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
fun chooseNextConstruction() {
|
fun chooseNextConstruction() {
|
||||||
if (!UncivGame.Current.settings.autoAssignCityProduction
|
if (!UncivGame.Current.settings.autoAssignCityProduction
|
||||||
&& civInfo.playerType == PlayerType.Human && !cityInfo.isPuppet
|
&& civInfo.playerType == PlayerType.Human && !cityInfo.isPuppet
|
||||||
)
|
) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
if (cityConstructions.getCurrentConstruction() !is PerpetualConstruction) return // don't want to be stuck on these forever
|
if (cityConstructions.getCurrentConstruction() !is PerpetualConstruction) return // don't want to be stuck on these forever
|
||||||
|
|
||||||
addFoodBuildingChoice()
|
addFoodBuildingChoice()
|
||||||
@ -65,15 +68,15 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
addDefenceBuildingChoice()
|
addDefenceBuildingChoice()
|
||||||
addUnitTrainingBuildingChoice()
|
addUnitTrainingBuildingChoice()
|
||||||
addCultureBuildingChoice()
|
addCultureBuildingChoice()
|
||||||
addSpaceshipPartChoice()
|
|
||||||
addOtherBuildingChoice()
|
addOtherBuildingChoice()
|
||||||
addReligiousUnit()
|
|
||||||
|
|
||||||
if (!cityInfo.isPuppet) {
|
if (!cityInfo.isPuppet) {
|
||||||
|
addSpaceshipPartChoice()
|
||||||
addWondersChoice()
|
addWondersChoice()
|
||||||
addWorkerChoice()
|
addWorkerChoice()
|
||||||
addWorkBoatChoice()
|
addWorkBoatChoice()
|
||||||
addMilitaryUnitChoice()
|
addMilitaryUnitChoice()
|
||||||
|
addReligiousUnit()
|
||||||
}
|
}
|
||||||
|
|
||||||
val production = cityInfo.cityStats.currentCityStats.production
|
val production = cityInfo.cityStats.currentCityStats.production
|
||||||
@ -138,15 +141,16 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addWorkBoatChoice() {
|
private fun addWorkBoatChoice() {
|
||||||
val buildableWorkboatUnits = cityInfo.cityConstructions.getConstructableUnits()
|
val buildableWorkboatUnits = buildableUnits
|
||||||
.filter {
|
.filter {
|
||||||
it.hasUnique(UniqueType.CreateWaterImprovements)
|
it.hasUnique(UniqueType.CreateWaterImprovements)
|
||||||
&& Automation.allowSpendingResource(civInfo, it)
|
&& Automation.allowSpendingResource(civInfo, it)
|
||||||
}
|
}
|
||||||
val canBuildWorkboat = buildableWorkboatUnits.any()
|
val alreadyHasWorkBoat = buildableWorkboatUnits.any()
|
||||||
&& !cityInfo.getTiles()
|
&& !cityInfo.getTiles().any {
|
||||||
.any { it.civilianUnit?.hasUnique(UniqueType.CreateWaterImprovements) == true }
|
it.civilianUnit?.hasUnique(UniqueType.CreateWaterImprovements) == true
|
||||||
if (!canBuildWorkboat) return
|
}
|
||||||
|
if (!alreadyHasWorkBoat) return
|
||||||
|
|
||||||
|
|
||||||
val bfs = BFS(cityInfo.getCenterTile()) {
|
val bfs = BFS(cityInfo.getCenterTile()) {
|
||||||
@ -167,12 +171,12 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addWorkerChoice() {
|
private fun addWorkerChoice() {
|
||||||
val workerEquivalents = civInfo.gameInfo.ruleSet.units.values
|
val workerEquivalents = buildableUnits
|
||||||
.filter {
|
.filter {
|
||||||
it.hasUnique(UniqueType.BuildImprovements)
|
it.hasUnique(UniqueType.BuildImprovements)
|
||||||
&& it.isBuildable(cityConstructions)
|
&& Automation.allowSpendingResource(civInfo, it)
|
||||||
&& Automation.allowSpendingResource(civInfo, it) }
|
}
|
||||||
if (workerEquivalents.isEmpty()) return // for mods with no worker units
|
if (workerEquivalents.none()) return // for mods with no worker units
|
||||||
|
|
||||||
if (workers < cities) {
|
if (workers < cities) {
|
||||||
var modifier = cities / (workers + 0.1f) // The worse our worker to city ratio is, the more desperate we are
|
var modifier = cities / (workers + 0.1f) // The worse our worker to city ratio is, the more desperate we are
|
||||||
@ -195,7 +199,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addSpaceshipPartChoice() {
|
private fun addSpaceshipPartChoice() {
|
||||||
val spaceshipPart = buildableNotWonders.firstOrNull { it.hasUnique(UniqueType.SpaceshipPart) }
|
val spaceshipPart = (buildableNotWonders + buildableUnits).firstOrNull { it.hasUnique(UniqueType.SpaceshipPart) }
|
||||||
if (spaceshipPart != null) {
|
if (spaceshipPart != null) {
|
||||||
var modifier = 1.5f
|
var modifier = 1.5f
|
||||||
if (preferredVictoryType == VictoryType.Scientific) modifier = 2f
|
if (preferredVictoryType == VictoryType.Scientific) modifier = 2f
|
||||||
@ -358,12 +362,12 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
|
|
||||||
// The performance of the regular getMatchingUniques is better, since it only tries to find one unique,
|
// The performance of the regular getMatchingUniques is better, since it only tries to find one unique,
|
||||||
// while the canBePurchasedWithStat tries (at time of writing) *6* different uniques.
|
// while the canBePurchasedWithStat tries (at time of writing) *6* different uniques.
|
||||||
val missionary = cityInfo.getRuleset().units.values
|
val missionary = buildableUnits
|
||||||
.firstOrNull { it -> it.getMatchingUniques("Can [] [] times").any { it.params[0] == "Spread Religion"}
|
.firstOrNull { it -> it.getMatchingUniques("Can [] [] times").any { it.params[0] == "Spread Religion"}
|
||||||
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
||||||
|
|
||||||
|
|
||||||
val inquisitor = cityInfo.getRuleset().units.values
|
val inquisitor = buildableUnits
|
||||||
.firstOrNull { it.hasUnique("Prevents spreading of religion to the city it is next to")
|
.firstOrNull { it.hasUnique("Prevents spreading of religion to the city it is next to")
|
||||||
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
||||||
|
|
||||||
@ -374,7 +378,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
val citiesNotFollowingOurReligion = civInfo.cities.asSequence()
|
val citiesNotFollowingOurReligion = civInfo.cities.asSequence()
|
||||||
.filterNot { it.religion.getMajorityReligion()?.name == civInfo.religionManager.religion!!.name }
|
.filterNot { it.religion.getMajorityReligion()?.name == civInfo.religionManager.religion!!.name }
|
||||||
|
|
||||||
val buildInqusitor = citiesNotFollowingOurReligion
|
val buildInquisitor = citiesNotFollowingOurReligion
|
||||||
.filter { it.religion.getMajorityReligion()?.name == civInfo.religionManager.religion?.name }
|
.filter { it.religion.getMajorityReligion()?.name == civInfo.religionManager.religion?.name }
|
||||||
.toList().size.toFloat() / 10 + modifier
|
.toList().size.toFloat() / 10 + modifier
|
||||||
|
|
||||||
@ -383,7 +387,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
|
|
||||||
val buildMissionary = possibleSpreadReligionTargets.toList().size.toFloat() / 15 + modifier
|
val buildMissionary = possibleSpreadReligionTargets.toList().size.toFloat() / 15 + modifier
|
||||||
|
|
||||||
if (buildMissionary > buildInqusitor && missionary != null) faithConstruction.add(missionary)
|
if (buildMissionary > buildInquisitor && missionary != null) faithConstruction.add(missionary)
|
||||||
else if(inquisitor != null) faithConstruction.add(inquisitor)
|
else if(inquisitor != null) faithConstruction.add(inquisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +282,15 @@ object SpecificUnitAutomation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun automateAddInCapital(unit: MapUnit) {
|
||||||
|
val capitalTile = unit.civInfo.getCapital().getCenterTile()
|
||||||
|
val unitTile = unit.movement.headTowards(capitalTile)
|
||||||
|
if (unitTile == capitalTile) {
|
||||||
|
UnitActions.getAddInCapitalAction(unit, unitTile).action!!()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun automateMissionary(unit: MapUnit) {
|
fun automateMissionary(unit: MapUnit) {
|
||||||
if (unit.religion != unit.civInfo.religionManager.religion?.name)
|
if (unit.religion != unit.civInfo.religionManager.religion?.name)
|
||||||
return unit.destroy()
|
return unit.destroy()
|
||||||
|
@ -153,6 +153,11 @@ object UnitAutomation {
|
|||||||
if (unit.hasUnique(UniqueType.CreateWaterImprovements))
|
if (unit.hasUnique(UniqueType.CreateWaterImprovements))
|
||||||
return SpecificUnitAutomation.automateWorkBoats(unit)
|
return SpecificUnitAutomation.automateWorkBoats(unit)
|
||||||
|
|
||||||
|
// We try to add any unit in the capital we can, though that might not always be desirable
|
||||||
|
// For now its a simple option to allow AI to win a science victory again
|
||||||
|
if (unit.hasUnique(UniqueType.AddInCapital))
|
||||||
|
return SpecificUnitAutomation.automateAddInCapital(unit)
|
||||||
|
|
||||||
if (unit.hasUnique("Bonus for units in 2 tile radius 15%"))
|
if (unit.hasUnique("Bonus for units in 2 tile radius 15%"))
|
||||||
return SpecificUnitAutomation.automateGreatGeneral(unit)
|
return SpecificUnitAutomation.automateGreatGeneral(unit)
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ class CityConstructions {
|
|||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Why is one of these called 'buildable' and the other 'constructable'?
|
||||||
internal fun getBuildableBuildings(): Sequence<Building> = cityInfo.getRuleset().buildings.values
|
internal fun getBuildableBuildings(): Sequence<Building> = cityInfo.getRuleset().buildings.values
|
||||||
.asSequence().filter { it.isBuildable(this) }
|
.asSequence().filter { it.isBuildable(this) }
|
||||||
|
|
||||||
|
@ -407,11 +407,9 @@ object UnitActions {
|
|||||||
}.takeIf { unit.currentMovement > 0 }
|
}.takeIf { unit.currentMovement > 0 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addAddInCapitalAction(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: TileInfo) {
|
fun getAddInCapitalAction(unit: MapUnit, tile: TileInfo): UnitAction {
|
||||||
if (!unit.hasUnique(UniqueType.AddInCapital)) return
|
return UnitAction(UnitActionType.AddInCapital,
|
||||||
|
|
||||||
actionList += UnitAction(UnitActionType.AddInCapital,
|
|
||||||
title = "Add to [${unit.getMatchingUniques(UniqueType.AddInCapital).first().params[0]}]",
|
title = "Add to [${unit.getMatchingUniques(UniqueType.AddInCapital).first().params[0]}]",
|
||||||
action = {
|
action = {
|
||||||
unit.civInfo.victoryManager.currentsSpaceshipParts.add(unit.name, 1)
|
unit.civInfo.victoryManager.currentsSpaceshipParts.add(unit.name, 1)
|
||||||
@ -420,6 +418,12 @@ object UnitActions {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addAddInCapitalAction(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: TileInfo) {
|
||||||
|
if (!unit.hasUnique(UniqueType.AddInCapital)) return
|
||||||
|
|
||||||
|
actionList += getAddInCapitalAction(unit, tile)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun addGreatPersonActions(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: TileInfo) {
|
private fun addGreatPersonActions(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: TileInfo) {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user