diff --git a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt index c61120c277..3439e4ce13 100644 --- a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt @@ -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) } } diff --git a/core/src/com/unciv/logic/automation/UnitAutomation.kt b/core/src/com/unciv/logic/automation/UnitAutomation.kt index b893d93797..8f3bed02e1 100644 --- a/core/src/com/unciv/logic/automation/UnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/UnitAutomation.kt @@ -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) diff --git a/core/src/com/unciv/logic/civilization/ReligionManager.kt b/core/src/com/unciv/logic/civilization/ReligionManager.kt index f166287342..7e805cfb08 100644 --- a/core/src/com/unciv/logic/civilization/ReligionManager.kt +++ b/core/src/com/unciv/logic/civilization/ReligionManager.kt @@ -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()