diff --git a/core/src/com/unciv/logic/automation/unit/BattleHelper.kt b/core/src/com/unciv/logic/automation/unit/BattleHelper.kt index 9124704e2a..617ad2c42c 100644 --- a/core/src/com/unciv/logic/automation/unit/BattleHelper.kt +++ b/core/src/com/unciv/logic/automation/unit/BattleHelper.kt @@ -68,8 +68,7 @@ object BattleHelper { val tilesInAttackRange = if (unit.hasUnique(UniqueType.IndirectFire) || unit.baseUnit.movesLikeAirUnits()) reachableTile.getTilesInDistance(rangeOfAttack) - else reachableTile.getViewableTilesList(rangeOfAttack) - .asSequence() + else reachableTile.tileMap.getViewableTiles(reachableTile.position, rangeOfAttack, true).asSequence() for (tile in tilesInAttackRange) { if (tile in tilesWithEnemies) attackableTiles += AttackableTile( diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index 377a0c2a8b..cff30ffdb3 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -329,7 +329,7 @@ class TileMap : IsPartOfGameInfoSerialization { data class ViewableTile(val tile:TileInfo, val maxHeightSeenToTile:Int, val isVisible:Boolean, val isAttackable: Boolean) /** @return List of tiles visible from location [position] for a unit with sight range [sightDistance] */ - fun getViewableTiles(position: Vector2, sightDistance: Int): List { + fun getViewableTiles(position: Vector2, sightDistance: Int, forAttack:Boolean = false): List { val aUnitHeight = get(position).unitHeight val viewableTiles = mutableListOf(ViewableTile( get(position), @@ -373,6 +373,8 @@ class TileMap : IsPartOfGameInfoSerialization { viewableTiles.addAll(tilesToAddInDistanceI) } + if (forAttack) return viewableTiles.filter { it.isAttackable }.map { it.tile } + return viewableTiles.filter { it.isVisible }.map { it.tile } } diff --git a/tests/src/com/unciv/logic/map/VisibilityTests.kt b/tests/src/com/unciv/logic/map/VisibilityTests.kt index 87a3737913..611ad282ea 100644 --- a/tests/src/com/unciv/logic/map/VisibilityTests.kt +++ b/tests/src/com/unciv/logic/map/VisibilityTests.kt @@ -186,6 +186,18 @@ class VisibilityTests { assert(viewableTiles.contains(beyondSight)) } + @Test + fun canSeeElevation3TilesEvenWithInvisibleIntermediate() { + val source = addTile("Grassland", Vector2(0f,0f)) + addTile(listOf("Grassland", "Hill"), Vector2(1f,0f)) + val intermediate = addTile(listOf("Grassland", "Hill"), Vector2(2f,0f)) + val beyondSight = addTile(listOf("Grassland", "Hill", "Forest"), Vector2(3f,0f)) + + val viewableTiles = source.getViewableTilesList(2) + assert(viewableTiles.contains(beyondSight)) + assert(!viewableTiles.contains(intermediate)) + } + @Test fun cannotSeeHiddenElevation3Tiles() { val source = addTile("Grassland", Vector2(0f,0f)) @@ -197,4 +209,26 @@ class VisibilityTests { assert(!viewableTiles.contains(beyondSight)) } + @Test + fun canSeeButNotAttackHillForestOverHill() { + val grassland = addTile("Grassland", Vector2(0f,0f)) + addTile(listOf("Grassland", "Hill"), Vector2(1f,0f)) + val hillForest = addTile(listOf("Grassland", "Hill", "Forest"), Vector2(2f, 0f)) + val viewableTiles = grassland.getViewableTilesList(2) + assert(viewableTiles.contains(hillForest)) + val attackableTiles = tileMap.getViewableTiles(grassland.position, 2, true) + assert(!attackableTiles.contains(hillForest)) + } + + @Test + fun canSeeAndAttackMountainOverHill() { + val grassland = addTile("Grassland", Vector2(0f,0f)) + addTile(listOf("Grassland", "Hill"), Vector2(1f,0f)) + val mountain = addTile(listOf("Mountain"), Vector2(2f, 0f)) + val viewableTiles = grassland.getViewableTilesList(2) + assert(viewableTiles.contains(mountain)) + val attackableTiles = tileMap.getViewableTiles(grassland.position, 2, true) + assert(attackableTiles.contains(mountain)) + } + }