import dev.robocode.tankroyale.runner.*; import dev.robocode.tankroyale.client.model.*; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; /** * Radar-lock diagnostic battle: PPO_Bot vs Target (1 round). * * Per tick prints: turn, each bot's radar direction, and any ScannedBotEvents. * * Usage: * ./run.sh */ public class RunBattle { static final Map idToName = new ConcurrentHashMap<>(); public static void main(String[] args) { Logger.getLogger("dev.robocode.tankroyale").setLevel(Level.WARNING); String ppoBotDir = requireEnv("PPO_BOT_DIR"); String sampleBots = requireEnv("SAMPLE_BOTS_DIR"); try (var runner = BattleRunner.create(b -> b.embeddedServer().suppressServerOutput())) { var setup = BattleSetup.classic(s -> s.setNumberOfRounds(1)); var bots = List.of( BotEntry.of(ppoBotDir), BotEntry.of(sampleBots + "/Target") ); var owner = new Object(); try (var handle = runner.startBattleAsync(setup, bots)) { handle.getOnGameStarted().on(owner, event -> { System.out.println("=== GAME STARTED ==="); for (var p : event.getParticipants()) { idToName.put(p.getId(), p.getName()); System.out.printf(" #%d %s%n", p.getId(), p.getName()); } System.out.printf("%-6s %-12s %-21s %-12s %-10s %-10s%n", "Turn", "Name", "Position", "Direction", "Speed", "RadarDir"); System.out.println("-".repeat(80)); }); handle.getOnTickEvent().on(owner, event -> { int turn = event.getTurnNumber(); // Keep id→name map current from bot states (handles race with onGameStarted) for (var state : event.getBotStates()) if (state.getName() != null) idToName.putIfAbsent(state.getId(), state.getName()); // Print position/speed/direction for every bot for (var state : event.getBotStates()) { String name = idToName.getOrDefault(state.getId(), state.getName() != null ? state.getName() : "#" + state.getId()); System.out.printf("%-6d %-12s pos=(%-6.1f,%-6.1f) dir=%-7.2f spd=%-6.2f radar=%-7.2f%n", turn, name, state.getX(), state.getY(), state.getDirection(), state.getSpeed(), state.getRadarDirection()); } // Print any scan events on the same tick for (var e : event.getEvents()) { if (e instanceof ScannedBotEvent scan) { String scanner = idToName.getOrDefault(scan.getScannedByBotId(), "?" + scan.getScannedByBotId()); String target = idToName.getOrDefault(scan.getScannedBotId(), "?" + scan.getScannedBotId()); System.out.printf("%-6d SCAN %s scanned %s at (%.1f,%.1f)%n", turn, scanner, target, scan.getX(), scan.getY()); } } }); handle.getOnRoundEnded().on(owner, event -> System.out.printf("%n=== ROUND %d ENDED (turn %d) ===%n", event.getRoundNumber(), event.getTurnNumber())); var results = handle.awaitResults(); System.out.printf("%n=== RESULTS (%d rounds) ===%n", results.getNumberOfRounds()); for (var r : results.getResults()) { System.out.printf(" #%d %-25s %d pts%n", r.getRank(), r.getName(), r.getTotalScore()); } } } } static String requireEnv(String name) { var v = System.getenv(name); if (v == null || v.isBlank()) { System.err.println("Error: " + name + " env var not set"); System.exit(1); } return v; } }