## Per-enemy state table. Keyed by bot ID. ## Tank Royale: 0° = East. import std/tables import std/math type EnemyState* = object id*: int x*, y*: float heading*: float ## degrees speed*: float energy*: float lastSeenTick*: int alive*: bool EnemyTracker* = object enemies*: Table[int, EnemyState] proc update*(et: var EnemyTracker, botId: int, x, y, heading, speed, energy: float, tick: int) = if botId in et.enemies and not et.enemies[botId].alive: return # don't resurrect dead bots et.enemies[botId] = EnemyState(id: botId, x: x, y: y, heading: heading, speed: speed, energy: energy, lastSeenTick: tick, alive: true) proc markDead*(et: var EnemyTracker, botId: int) = if botId in et.enemies: et.enemies[botId].alive = false proc resetRound*(et: var EnemyTracker) = et.enemies.clear() proc getEnemy*(et: EnemyTracker, botId: int): EnemyState = et.enemies[botId] proc allAlive*(et: EnemyTracker): seq[EnemyState] = for s in et.enemies.values: if s.alive: result.add(s) proc closestTo*(et: EnemyTracker, x, y: float): EnemyState = var bestDist = Inf for s in et.enemies.values: if not s.alive: continue let d = hypot(s.x - x, s.y - y) if d < bestDist: bestDist = d result = s proc weakest*(et: EnemyTracker): EnemyState = var bestEnergy = Inf for s in et.enemies.values: if not s.alive: continue if s.energy < bestEnergy: bestEnergy = s.energy result = s