## PPO_Bot — enemy tracker + state vector wired into the game loop. ## Forward pass uses a random ActorCritic policy (weights not yet trained). import std/os import arraymancer import tankroyale_botapi import network import actions import ./enemy_tracker import ./state_vector const botJsonPath = currentSourcePath().parentDir / "PPO_Bot.json" type PPOBot = ref object of Bot tracker: EnemyTracker var ac = initActorCritic() method onScannedBot*(bot: PPOBot, e: ScannedBotEvent) = bot.tracker.update(e.x, e.y, e.direction, e.speed, e.energy) method onRoundStarted*(bot: PPOBot, e: RoundStartedEvent) = bot.tracker = initEnemyTracker() method run(bot: PPOBot) = while isRunning(): bot.tracker.deadReckon() setRadarTurnRate(bot.tracker.getRadarTurnRate( getX(), getY(), getDirection(), getRadarDirection())) let botData = BotStateData( x: getX(), y: getY(), direction: getDirection(), speed: getSpeed(), energy: getEnergy(), gunDirection: getGunDirection(), gunHeat: getGunHeat(), arenaWidth: float64(getArenaWidth()), arenaHeight: float64(getArenaHeight()), ) let state = buildStateVector(botData, bot.tracker) let (rawActs, _) = ac.actorForward(state) let acts = mapActions(rawActs, getSpeed().float32, getGunHeat().float32) setTargetSpeed(acts.targetSpeed.float) setTurnRate(acts.turnRate.float) setGunTurnRate(acts.gunTurnRate.float) if acts.shouldFire: discard setFire(acts.firePower.float) go() when isMainModule: var bot = PPOBot(tracker: initEnemyTracker()) start(bot, botJsonPath)