Remove Tactical AI files - untouched for 2 years and unused, causes confusion to new developers

This commit is contained in:
yairm210 2024-11-13 15:43:34 +02:00
parent 7b075bcf7c
commit 04ec4f9cdb
4 changed files with 0 additions and 391 deletions

View File

@ -1,57 +0,0 @@
package com.unciv.logic.automation.ai
import com.badlogic.gdx.graphics.Color
import com.unciv.GUI
import com.unciv.logic.IsPartOfGameInfoSerialization
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.ui.components.extensions.toGroup
import com.unciv.ui.images.ImageGetter
import com.unciv.utils.Log
class TacticalAI : IsPartOfGameInfoSerialization {
private val debug: Boolean = false
@Transient private val tacticalAnalysisMap = TacticalAnalysisMap()
@Transient private var player: Civilization? = null
fun init(player: Civilization) {
this.player = player
tacticalAnalysisMap.reset(player)
}
fun showZonesDebug(tile: Tile) {
if (!debug)
return
val zone = tacticalAnalysisMap.getZoneByTile(tile)
val zoneId = zone?.id
Log.debug("MYTAG Zone $zoneId City: ${zone?.city} Area: ${zone?.area} Area size: ${
tile.tileMap.continentSizes[tile.getContinent()]} Zone size: ${zone?.tileCount}")
val mapHolder = GUI.getMap()
for (otherTile in mapHolder.tileMap.values.asSequence()) {
val otherZoneId = tacticalAnalysisMap.plotPositionToZoneId[otherTile.position]
if (otherZoneId == zoneId) {
mapHolder.tileGroups[otherTile]?.let {
mapHolder.addOverlayOnTileGroup(it, ImageGetter.getCircle(
color = when (zone?.territoryType) {
TacticalTerritoryType.FRIENDLY -> Color.GREEN
TacticalTerritoryType.ENEMY -> Color.RED
else -> Color.WHITE
}
).toGroup(20f)) }
}
if (zone?.neighboringZones?.contains(otherZoneId) == true) {
mapHolder.tileGroups[otherTile]?.let {
mapHolder.addOverlayOnTileGroup(it, ImageGetter.getCircle(color = Color.GRAY).toGroup(20f)) }
}
}
}
}

View File

@ -1,327 +0,0 @@
package com.unciv.logic.automation.ai
import com.badlogic.gdx.math.Vector2
import com.unciv.Constants
import com.unciv.logic.GameInfo
import com.unciv.logic.city.City
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.logic.map.TileMap
import com.unciv.utils.Log
import java.util.UUID
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
enum class TacticalTerritoryType {
NONE,
FRIENDLY,
ENEMY,
NEUTRAL
}
class TacticalDominanceZone {
var id = "UNKNOWN"
var territoryType = TacticalTerritoryType.NONE
var owner: Civilization? = null
var city: City? = null
var area: Int = -1
var tileCount: Int = 0
var neighboringZones: HashSet<String> = HashSet()
var friendlyMeleeStrength = 0
var friendlyRangeStrength = 0
var friendlyNavalMeleeStrength = 0
var friendlyNavalRangeStrength = 0
var friendlyUnitCount = 0
var friendlyNavalUnitCount = 0
var enemyMeleeStrength = 0
var enemyRangeStrength = 0
var enemyNavalMeleeStrength = 0
var enemyNavalRangeStrength = 0
var enemyUnitCount = 0
var enemyNavalUnitCount = 0
val neutralUnitStrength = 0
val neutralUnitCount = 0
var zoneValue = 0
fun getOverallFriendlyStrength(): Int {
return friendlyMeleeStrength*4/3 + friendlyNavalMeleeStrength + friendlyRangeStrength + friendlyNavalRangeStrength
}
fun getOverallEnemyStrength(): Int {
return enemyMeleeStrength*4/3 + enemyNavalMeleeStrength + enemyRangeStrength + enemyNavalRangeStrength
}
fun isWater(): Boolean {
return id.startsWith('-')
}
fun extend() {
tileCount += 1
}
}
class TacticalAnalysisMap {
lateinit var game: GameInfo // Current game
lateinit var player: Civilization // Current player
var lastUpdate: Int = -1
val zones: ArrayList<TacticalDominanceZone> = ArrayList()
val zoneIdToZoneIndex: HashMap<String, Int> = HashMap()
val plotPositionToZoneId: HashMap<Vector2, String> = HashMap()
companion object {
const val maxRange = 4
const val maxZoneSize = 30
}
fun reset(player: Civilization) {
this.player = player
this.game = player.gameInfo
this.lastUpdate = -1
this.zones.clear()
this.zoneIdToZoneIndex.clear()
this.plotPositionToZoneId.clear()
}
fun isUpToDate() : Boolean {
if (lastUpdate == -1)
return false
if (player != game.currentPlayerCiv)
return true
return lastUpdate == game.turns
}
fun invalidate() {
lastUpdate = -1
}
private fun refreshIfOutdated() {
if (isUpToDate())
return
Log.debug("Refreshing Tactical Analysis Map...")
// This is where creation and separation of zones occur
createDominanceZones()
establishZoneNeighborhood()
// This is workaround for absent "Area" mechanics.
// We glue small leftovers to bigger zones
glueSmallZonesToBig()
// TODO: calculateMilitaryStrength
// TODO: prioritizeZones
// TODO: updatePostures
}
fun getZoneByTile(tile: Tile): TacticalDominanceZone? {
refreshIfOutdated()
val zoneId = plotPositionToZoneId[tile.position]?: return null
return getZoneById(zoneId)
}
fun getZoneById(id: String): TacticalDominanceZone? {
refreshIfOutdated()
val index = zoneIdToZoneIndex[id]
if (index != null)
return getZoneByIndex(index)
return null
}
fun getZoneByIndex(index: Int): TacticalDominanceZone? {
refreshIfOutdated()
if (index < 0 || index >= zones.size)
return null
return zones[index]
}
fun createDominanceZones() {
lastUpdate = game.turns
zones.clear()
zoneIdToZoneIndex.clear()
plotPositionToZoneId.clear()
val unknownZone = TacticalDominanceZone()
zones.add(unknownZone)
zoneIdToZoneIndex[unknownZone.id] = 0
val nonCityTiles = ArrayList<Tile>()
var zone: TacticalDominanceZone? = null
for (tile in game.tileMap.values.asSequence()) {
// Unexplored plot go into their own zone
if (!player.hasExplored(tile)) {
plotPositionToZoneId[tile.position] = unknownZone.id
continue
}
// Is this plot close to a city?
val cityDistance = game.cityDistances.getClosestCityDistance(tile, null, false)
if (cityDistance == null) {
// Non-city tiles processed separately
nonCityTiles.add(tile)
continue
}
val city: City? = when {
cityDistance.distance < 3 -> cityDistance.city
else -> tile.getCity()
}
if (city == null) {
nonCityTiles.add(tile)
continue
}
val zoneId = if (tile.isWater) "-${city.id}" else city.id
// Chances are it's the same zone as before
if (zone == null || zone.id != zoneId) {
zone = getZoneById(zoneId)
// Still not found? Create new
if (zone == null) {
val newZone = TacticalDominanceZone()
newZone.id = zoneId
newZone.city = city
newZone.owner = city.civ
newZone.area = tile.getContinent()
if (newZone.owner == player)
newZone.territoryType = TacticalTerritoryType.FRIENDLY
else if (newZone.owner?.isAtWarWith(player) == true)
newZone.territoryType = TacticalTerritoryType.ENEMY
else
newZone.territoryType = TacticalTerritoryType.NEUTRAL
zoneIdToZoneIndex[zoneId] = zones.size
zones.add(newZone)
zone = zones.last()
}
}
plotPositionToZoneId[tile.position] = zoneId
zone.extend()
}
// Ensure that continents sizes are calculated
game.tileMap.assignContinents(TileMap.AssignContinentsMode.Ensure)
groupRemainingNonCityTiles(nonCityTiles)
}
private fun groupRemainingNonCityTiles(nonCityTiles: ArrayList<Tile>) {
while (nonCityTiles.isNotEmpty()) {
var count = maxZoneSize
val stack: ArrayList<Tile> = ArrayList()
stack.add(nonCityTiles.removeFirst())
val randomId = UUID.randomUUID().toString()
val newId = if (stack.last().isWater) "-$randomId" else randomId
val newZone = TacticalDominanceZone()
newZone.id = newId
newZone.city = null
newZone.area = stack.last().getContinent()
newZone.territoryType = TacticalTerritoryType.NEUTRAL
while (stack.isNotEmpty() || count > 0) {
val tile = stack.removeLastOrNull() ?: break
val tileContinentSize = tile.tileMap.continentSizes[tile.getContinent()] ?: Int.MAX_VALUE
plotPositionToZoneId[tile.position] = newId
newZone.extend()
for (neighbor in tile.neighbors) {
// We don't want lakes and mountains to be separate zones - should attach them too
val isLake = neighbor.matchesTerrainFilter(Constants.lakes)
val isMountain = neighbor.matchesTerrainFilter(Constants.mountain)
val neighborContinentSize = neighbor.tileMap.continentSizes[neighbor.getContinent()] ?: Int.MAX_VALUE
val isSameZone = neighbor.getContinent() == tile.getContinent()
|| isLake || (isMountain && neighbor.isLand)
|| neighborContinentSize < 4 || tileContinentSize < 4
if (isSameZone && nonCityTiles.contains(neighbor) && count > 0) {
nonCityTiles.remove(neighbor)
stack.add(neighbor)
count -= 1
}
}
}
zoneIdToZoneIndex[newZone.id] = zones.size
zones.add(newZone)
}
}
private fun glueSmallZonesToBig() {
val toRemove = HashSet<TacticalDominanceZone>()
for (zone in zones) {
if (zone.tileCount < 5 && zone.city == null) {
val biggerZone = zones.asSequence()
.filter { it.isWater() == zone.isWater() && it.neighboringZones.contains(zone.id) }
.firstOrNull()
if (biggerZone != null) {
plotPositionToZoneId.asSequence()
.filter { it.value == zone.id }
.forEach { plotPositionToZoneId[it.key] = biggerZone.id }
toRemove.add(zone)
}
}
}
zones.removeAll(toRemove)
zoneIdToZoneIndex.clear()
for (i in 0 until zones.size) {
val zoneId = zones[i].id
zoneIdToZoneIndex[zoneId] = i
}
}
private fun establishZoneNeighborhood() {
for (zone in zones)
zone.neighboringZones.clear()
val tileMap = game.tileMap
val directionsToCheck = setOf(12, 4, 8) // each tile only needs to check 3 directions for every possible neighboringZone to be identified
for (tile in tileMap.values) {
val zoneA = getZoneByTile(tile)
val zoneAId = zoneA!!.id
for (neighbor in directionsToCheck.mapNotNull { tileMap.getClockPositionNeighborTile(tile, it) }) {
val zoneB = getZoneByTile(neighbor)!!
val zoneBId = zoneB.id
if (zoneAId != zoneBId) {
zoneA.neighboringZones.add(zoneB.id)
zoneB.neighboringZones.add(zoneA.id)
}
}
}
}
fun debugOutput() {
Log.debug("MYTAG: Total tactical zones: ${zones.size}")
for (zone in zones) {
Log.debug("MYTAG: Zone: ${zone.id} City: ${zone.city} Territory: ${zone.territoryType} Neighbors: ${zone.neighboringZones}")
}
}
}

View File

@ -8,7 +8,6 @@ import com.unciv.logic.GameInfo
import com.unciv.logic.IsPartOfGameInfoSerialization
import com.unciv.logic.MultiFilter
import com.unciv.logic.UncivShowableException
import com.unciv.logic.automation.ai.TacticalAI
import com.unciv.logic.automation.unit.WorkerAutomation
import com.unciv.logic.city.City
import com.unciv.logic.city.managers.CityFounder
@ -169,9 +168,6 @@ class Civilization : IsPartOfGameInfoSerialization {
private var allyCivName: String? = null
var naturalWonders = ArrayList<String>()
/* AI section */
val tacticalAI = TacticalAI()
var notifications = ArrayList<Notification>()
var notificationsLog = ArrayList<NotificationsLog>()
@ -785,8 +781,6 @@ class Civilization : IsPartOfGameInfoSerialization {
hasLongCountDisplayUnique = hasUnique(UniqueType.MayanCalendarDisplay)
tacticalAI.init(this)
cache.setTransients()
}

View File

@ -197,7 +197,6 @@ class WorldMapHolder(
unitTable.citySelected(previousSelectedCity)
}
}
worldScreen.viewingCiv.tacticalAI.showZonesDebug(tile)
worldScreen.shouldUpdate = true
}