mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-22 22:00:24 +07:00
Resolved #3663 - fixed settler automation bug
This commit is contained in:
@ -20,8 +20,10 @@ object SpecificUnitAutomation {
|
||||
fun automateWorkBoats(unit: MapUnit) {
|
||||
val closestReachableResource = unit.civInfo.cities.asSequence()
|
||||
.flatMap { city -> city.getWorkableTiles() }
|
||||
.filter { hasWorkableSeaResource(it, unit.civInfo)
|
||||
&& (unit.currentTile == it || unit.movement.canMoveTo(it)) }
|
||||
.filter {
|
||||
hasWorkableSeaResource(it, unit.civInfo)
|
||||
&& (unit.currentTile == it || unit.movement.canMoveTo(it))
|
||||
}
|
||||
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
||||
.firstOrNull { unit.movement.canReach(it) }
|
||||
|
||||
@ -64,13 +66,14 @@ object SpecificUnitAutomation {
|
||||
val enemyCities = unit.civInfo.getKnownCivs()
|
||||
.filter { unit.civInfo.getDiplomacyManager(it).hasModifier(DiplomaticModifiers.StealingTerritory) }
|
||||
.flatMap { it.cities }.asSequence()
|
||||
// find the suitable tiles (or their neigbours)
|
||||
// find the suitable tiles (or their neighbours)
|
||||
val tileToSteal = enemyCities.flatMap { it.getTiles() } // City tiles
|
||||
.filter { it.neighbors.any { it.getOwner()!=unit.civInfo } } // Edge city tiles
|
||||
.filter { it.neighbors.any { it.getOwner() != unit.civInfo } } // Edge city tiles
|
||||
.flatMap { it.neighbors.asSequence() } // Neighbors of edge city tiles
|
||||
.filter { it in unit.civInfo.viewableTiles // we can see them
|
||||
&& it.neighbors.any { tile -> tile.getOwner() == unit.civInfo}// they are close to our borders
|
||||
}
|
||||
.filter {
|
||||
it in unit.civInfo.viewableTiles // we can see them
|
||||
&& it.neighbors.any { tile -> tile.getOwner() == unit.civInfo }// they are close to our borders
|
||||
}
|
||||
.sortedBy {
|
||||
// get closest tiles
|
||||
val distance = it.aerialDistanceTo(unit.currentTile)
|
||||
@ -78,8 +81,9 @@ object SpecificUnitAutomation {
|
||||
val owner = it.getOwner()
|
||||
if (owner != null)
|
||||
distance - WorkerAutomation(unit).getPriority(it, owner)
|
||||
else distance }
|
||||
.firstOrNull{ unit.movement.canReach(it) } // canReach is performance-heavy and always a last resort
|
||||
else distance
|
||||
}
|
||||
.firstOrNull { unit.movement.canReach(it) } // canReach is performance-heavy and always a last resort
|
||||
// if there is a good tile to steal - go there
|
||||
if (tileToSteal != null) {
|
||||
unit.movement.headTowards(tileToSteal)
|
||||
@ -90,14 +94,16 @@ object SpecificUnitAutomation {
|
||||
|
||||
// try to build a citadel for defensive purposes
|
||||
if (WorkerAutomation(unit).evaluateFortPlacement(unit.currentTile, unit.civInfo, true)) {
|
||||
UnitActions.getImprovementConstructionActions(unit,unit.currentTile).firstOrNull()?.action?.invoke()
|
||||
UnitActions.getImprovementConstructionActions(unit, unit.currentTile).firstOrNull()?.action?.invoke()
|
||||
return
|
||||
}
|
||||
|
||||
//if no unit to follow, take refuge in city or build citadel there.
|
||||
val reachableTest : (TileInfo) -> Boolean = {it.civilianUnit == null &&
|
||||
unit.movement.canMoveTo(it)
|
||||
&& unit.movement.canReach(it)}
|
||||
val reachableTest: (TileInfo) -> Boolean = {
|
||||
it.civilianUnit == null &&
|
||||
unit.movement.canMoveTo(it)
|
||||
&& unit.movement.canReach(it)
|
||||
}
|
||||
val cityToGarrison = unit.civInfo.cities.asSequence().map { it.getCenterTile() }
|
||||
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
||||
.firstOrNull { reachableTest(it) }
|
||||
@ -105,12 +111,14 @@ object SpecificUnitAutomation {
|
||||
if (cityToGarrison != null) {
|
||||
// try to find a good place for citadel nearby
|
||||
val potentialTilesNearCity = cityToGarrison.getTilesInDistanceRange(3..4)
|
||||
val tileForCitadel = potentialTilesNearCity.firstOrNull { reachableTest(it) &&
|
||||
WorkerAutomation(unit).evaluateFortPlacement(it, unit.civInfo, true) }
|
||||
val tileForCitadel = potentialTilesNearCity.firstOrNull {
|
||||
reachableTest(it) &&
|
||||
WorkerAutomation(unit).evaluateFortPlacement(it, unit.civInfo, true)
|
||||
}
|
||||
if (tileForCitadel != null) {
|
||||
unit.movement.headTowards(tileForCitadel)
|
||||
if (unit.currentMovement > 0 && unit.currentTile == tileForCitadel)
|
||||
UnitActions.getImprovementConstructionActions(unit,unit.currentTile).firstOrNull()?.action?.invoke()
|
||||
UnitActions.getImprovementConstructionActions(unit, unit.currentTile).firstOrNull()?.action?.invoke()
|
||||
} else
|
||||
unit.movement.headTowards(cityToGarrison)
|
||||
return
|
||||
@ -169,13 +177,16 @@ object SpecificUnitAutomation {
|
||||
.map { it.getTileResource() }.filter { it.resourceType == ResourceType.Luxury }
|
||||
.distinct()
|
||||
|
||||
val citiesByRanking= possibleCityLocations
|
||||
val citiesByRanking = possibleCityLocations
|
||||
.map { Pair(it, rankTileAsCityCenter(it, nearbyTileRankings, luxuryResourcesInCivArea)) }
|
||||
.sortedByDescending { it.second }.toList()
|
||||
|
||||
// It's possible that we'll see a tile "over the sea" that's better than the tiles close by, but that's not a reason to abandon the close tiles!
|
||||
// Also this lead to some routing problems, see https://github.com/yairm210/Unciv/issues/3653
|
||||
val bestCityLocation: TileInfo? = citiesByRanking.firstOrNull { unit.movement.getShortestPath(it.first).size < 4 }?.first
|
||||
val bestCityLocation: TileInfo? = citiesByRanking.firstOrNull {
|
||||
val pathSize = unit.movement.getShortestPath(it.first).size
|
||||
return@firstOrNull pathSize in 1..3
|
||||
}?.first
|
||||
|
||||
if (bestCityLocation == null) { // We got a badass over here, all tiles within 5 are taken? Screw it, random walk.
|
||||
if (UnitAutomation.tryExplore(unit)) return // try to find new areas
|
||||
@ -228,7 +239,7 @@ object SpecificUnitAutomation {
|
||||
val chosenTile = applicableTiles.sortedByDescending { Automation.rankTile(it, unit.civInfo) }
|
||||
.firstOrNull { unit.movement.canReach(it) }
|
||||
if (chosenTile == null) continue // to another city
|
||||
|
||||
|
||||
unit.movement.headTowards(chosenTile)
|
||||
if (unit.currentTile == chosenTile)
|
||||
UnitActions.getImprovementConstructionActions(unit, unit.currentTile).firstOrNull()?.action?.invoke()
|
||||
@ -251,7 +262,7 @@ object SpecificUnitAutomation {
|
||||
|
||||
val citiesByNearbyAirUnits = pathsToCities.keys
|
||||
.groupBy { key ->
|
||||
key.getTilesInDistance(unit.getRange()*2)
|
||||
key.getTilesInDistance(unit.getRange() * 2)
|
||||
.count {
|
||||
val firstAirUnit = it.airUnits.firstOrNull()
|
||||
firstAirUnit != null && firstAirUnit.civInfo.isAtWarWith(unit.civInfo)
|
||||
@ -301,9 +312,9 @@ object SpecificUnitAutomation {
|
||||
// This really needs to be changed, to have better targetting for missiles
|
||||
fun automateMissile(unit: MapUnit) {
|
||||
|
||||
val tilesInRange = unit.currentTile.getTilesInDistance(unit.getRange()*2)
|
||||
val tilesInRange = unit.currentTile.getTilesInDistance(unit.getRange() * 2)
|
||||
|
||||
for(tile in tilesInRange) {
|
||||
for (tile in tilesInRange) {
|
||||
// For now AI will only use nukes against cities because in all honesty that's the best use for them.
|
||||
if (tile.isCityCenter() && tile.getOwner()!!.isAtWarWith(unit.civInfo)) {
|
||||
Battle.nuke(MapUnitCombatant(unit), tile)
|
||||
@ -330,7 +341,7 @@ object SpecificUnitAutomation {
|
||||
|
||||
private fun tryRelocateToCitiesWithEnemyNearBy(unit: MapUnit): Boolean {
|
||||
val immediatelyReachableCitiesAndCarriers = unit.currentTile
|
||||
.getTilesInDistance(unit.getRange()*2).filter { unit.movement.canMoveTo(it) }
|
||||
.getTilesInDistance(unit.getRange() * 2).filter { unit.movement.canMoveTo(it) }
|
||||
|
||||
for (city in immediatelyReachableCitiesAndCarriers) {
|
||||
if (city.getTilesInDistance(unit.getRange())
|
||||
@ -341,5 +352,4 @@ object SpecificUnitAutomation {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@ class TileInfoTable(private val viewingCiv :CivilizationInfo) : Table(CameraStag
|
||||
add(getStatsTable(tile))
|
||||
add(tile.toString(viewingCiv).toLabel()).colspan(2).pad(10f)
|
||||
// For debug only!
|
||||
add(tile.position.toString().toLabel()).colspan(2).pad(10f)
|
||||
// add(tile.position.toString().toLabel()).colspan(2).pad(10f)
|
||||
}
|
||||
|
||||
pack()
|
||||
|
Reference in New Issue
Block a user