mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-17 03:09:27 +07:00
Significantly reduce AI turn time (#7441)
* Significantly speed up AI pathfinding * Undo caching and improve AI * Undo comment change * Improvement * Reorder and comment
This commit is contained in:

committed by
GitHub

parent
160b51d578
commit
cb6160c4a8
@ -137,7 +137,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
|||||||
* Does not consider if tiles can actually be entered, use canMoveTo for that.
|
* Does not consider if tiles can actually be entered, use canMoveTo for that.
|
||||||
* If a tile can be reached within the turn, but it cannot be passed through, the total distance to it is set to unitMovement
|
* If a tile can be reached within the turn, but it cannot be passed through, the total distance to it is set to unitMovement
|
||||||
*/
|
*/
|
||||||
fun getDistanceToTilesWithinTurn(origin: Vector2, unitMovement: Float, considerZoneOfControl: Boolean = true): PathsToTilesWithinTurn {
|
fun getDistanceToTilesWithinTurn(origin: Vector2, unitMovement: Float, considerZoneOfControl: Boolean = true, tilesToIgnore: HashSet<TileInfo>? = null): PathsToTilesWithinTurn {
|
||||||
val distanceToTiles = PathsToTilesWithinTurn()
|
val distanceToTiles = PathsToTilesWithinTurn()
|
||||||
if (unitMovement == 0f) return distanceToTiles
|
if (unitMovement == 0f) return distanceToTiles
|
||||||
|
|
||||||
@ -151,6 +151,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
|||||||
val updatedTiles = ArrayList<TileInfo>()
|
val updatedTiles = ArrayList<TileInfo>()
|
||||||
for (tileToCheck in tilesToCheck)
|
for (tileToCheck in tilesToCheck)
|
||||||
for (neighbor in tileToCheck.neighbors) {
|
for (neighbor in tileToCheck.neighbors) {
|
||||||
|
if (tilesToIgnore?.contains(neighbor) == true) continue // ignore this tile
|
||||||
var totalDistanceToTile: Float = when {
|
var totalDistanceToTile: Float = when {
|
||||||
!unit.civInfo.exploredTiles.contains(neighbor.position) ->
|
!unit.civInfo.exploredTiles.contains(neighbor.position) ->
|
||||||
distanceToTiles[tileToCheck]!!.totalDistance + 1f // If we don't know then we just guess it to be 1.
|
distanceToTiles[tileToCheck]!!.totalDistance + 1f // If we don't know then we just guess it to be 1.
|
||||||
@ -205,6 +206,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
|||||||
val newTilesToCheck = ArrayList<TileInfo>()
|
val newTilesToCheck = ArrayList<TileInfo>()
|
||||||
val distanceToDestination = HashMap<TileInfo, Float>()
|
val distanceToDestination = HashMap<TileInfo, Float>()
|
||||||
var considerZoneOfControl = true // only for first distance!
|
var considerZoneOfControl = true // only for first distance!
|
||||||
|
val visitedTiles: HashSet<TileInfo> = hashSetOf(currentTile)
|
||||||
while (true) {
|
while (true) {
|
||||||
if (distance == 2) { // only set this once after distance > 1
|
if (distance == 2) { // only set this once after distance > 1
|
||||||
movementThisTurn = unit.getMaxMovement().toFloat()
|
movementThisTurn = unit.getMaxMovement().toFloat()
|
||||||
@ -213,14 +215,15 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
|||||||
newTilesToCheck.clear()
|
newTilesToCheck.clear()
|
||||||
distanceToDestination.clear()
|
distanceToDestination.clear()
|
||||||
for (tileToCheck in tilesToCheck) {
|
for (tileToCheck in tilesToCheck) {
|
||||||
val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, considerZoneOfControl)
|
val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, considerZoneOfControl, visitedTiles)
|
||||||
for (reachableTile in distanceToTilesThisTurn.keys) {
|
for (reachableTile in distanceToTilesThisTurn.keys) {
|
||||||
// Avoid damaging terrain on first pass
|
// Avoid damaging terrain on first pass
|
||||||
if (avoidDamagingTerrain && unit.getDamageFromTerrain(reachableTile) > 0)
|
if (avoidDamagingTerrain && unit.getDamageFromTerrain(reachableTile) > 0)
|
||||||
continue
|
continue
|
||||||
if (reachableTile == destination)
|
if (reachableTile == destination) {
|
||||||
distanceToDestination[tileToCheck] = distanceToTilesThisTurn[reachableTile]!!.totalDistance
|
distanceToDestination[tileToCheck] = distanceToTilesThisTurn[reachableTile]!!.totalDistance
|
||||||
else {
|
break
|
||||||
|
} else {
|
||||||
if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing...
|
if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing...
|
||||||
if (!isUnknownTileWeShouldAssumeToBePassable(reachableTile) &&
|
if (!isUnknownTileWeShouldAssumeToBePassable(reachableTile) &&
|
||||||
!canMoveTo(reachableTile)) continue // This is a tile that we can't actually enter - either an intermediary tile containing our unit, or an enemy unit/city
|
!canMoveTo(reachableTile)) continue // This is a tile that we can't actually enter - either an intermediary tile containing our unit, or an enemy unit/city
|
||||||
@ -245,6 +248,8 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
|||||||
|
|
||||||
if (newTilesToCheck.isEmpty()) return emptyList() // there is NO PATH (eg blocked by enemy units)
|
if (newTilesToCheck.isEmpty()) return emptyList() // there is NO PATH (eg blocked by enemy units)
|
||||||
|
|
||||||
|
// add newTilesToCheck to visitedTiles so we do not path over these tiles in a later iteration
|
||||||
|
visitedTiles.addAll(newTilesToCheck)
|
||||||
// no need to check tiles that are surrounded by reachable tiles, only need to check the edgemost tiles.
|
// no need to check tiles that are surrounded by reachable tiles, only need to check the edgemost tiles.
|
||||||
// Because anything we can reach from intermediate tiles, can be more easily reached by the edgemost tiles,
|
// Because anything we can reach from intermediate tiles, can be more easily reached by the edgemost tiles,
|
||||||
// since we'll have to pass through an edgemost tile in order to reach the destination anyway
|
// since we'll have to pass through an edgemost tile in order to reach the destination anyway
|
||||||
|
Reference in New Issue
Block a user