## Per-enemy state table. Keyed by bot ID. ## Tank Royale: 0° = East. import std/[tables, 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 isAlive*(et: EnemyTracker, botId: int): bool = botId in et.enemies and et.enemies[botId].alive proc aliveCount*(et: EnemyTracker): int = for s in et.enemies.values: if s.alive: inc result 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