c034eb9d25
- fix(ModularBot): onBulletHitBot → onBulletHit (real hits were never tracked) - feat(ModularBot): per-round gun stats dump to /tmp/gun_stats.jsonl - feat(ModularBot): gun selection counter per round - fix(tests): adversary paths _garage suffix removed from 7 test files - feat(tests): test_gauntlet_5bots.nim — 10-round gauntlet vs all 5 adversaries - feat(tests): analyze_gun_stats.nim — JSONL parser for gun performance tables - docs: gun_rack_analysis.md — full per-gun performance report - docs: gun_rack_summary.md — TL;DR verdict table (keep/drop/tune) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
67 lines
2.9 KiB
Nim
67 lines
2.9 KiB
Nim
## Gun gauntlet: ModularBot vs all 5 adversaries, 10 rounds each.
|
|
## Dumps per-gun stats via ModularBot's onRoundEnded to /tmp/gun_stats.jsonl.
|
|
## nim c -r --path:../../common_libs tests/test_gauntlet_5bots.nim
|
|
|
|
import std/[os, strutils, strformat, tables]
|
|
import test_framework/server_manager
|
|
import test_framework/bot_compiler
|
|
import test_framework/runner_process
|
|
import test_framework/battle_result
|
|
|
|
const
|
|
modularBotDir = currentSourcePath().parentDir.parentDir
|
|
adversariesDir = "/home/davide/Projects/SirRoboGarage/common_libs/test_framework/adversaries"
|
|
serverJar = "/home/davide/Projects/tank-royale/server/build/libs/robocode-tankroyale-server-0.35.5-all.jar"
|
|
runnerJar = "/home/davide/Projects/tank-royale/runner/examples/lib/robocode-tankroyale-runner.jar"
|
|
|
|
if not fileExists(serverJar):
|
|
echo "SKIP: server JAR not found at " & serverJar
|
|
quit(0)
|
|
if not fileExists(runnerJar):
|
|
echo "SKIP: runner JAR not found at " & runnerJar
|
|
quit(0)
|
|
|
|
putEnv("TR_SERVER_JAR", serverJar)
|
|
putEnv("TR_BATTLE_RUNNER", runnerJar)
|
|
putEnv("TR_BATTLE_RUNNER_DIR", "/home/davide/Projects/SirRoboGarage/tools/battle_runner")
|
|
|
|
# Pre-compile ModularBot once
|
|
discard compileBots(@[modularBotDir])
|
|
echo "[gauntlet] ModularBot compiled OK"
|
|
|
|
proc runBattle(label, enemyName, enemyDir: string) =
|
|
let sep = "=".repeat(60)
|
|
echo "\n" & sep
|
|
echo " " & label
|
|
echo sep
|
|
let bots = @[modularBotDir, enemyDir]
|
|
discard compileBots(@[enemyDir]) # ensure adversary is compiled
|
|
# Write session marker so analysis can map rounds to enemy name
|
|
block:
|
|
let lf = open("/tmp/gun_stats.jsonl", fmAppend)
|
|
lf.writeLine("{\"session_start\":\"" & enemyName & "\"}")
|
|
lf.close()
|
|
let raw = runBattleRunner(getServerUrl(), bots, 10, 300_000, true)
|
|
let r = parseServerOutput(raw)
|
|
var mbScore = 0; var enScore = 0
|
|
for b in r.results:
|
|
if b.name == "ModularBot": mbScore = b.totalScore
|
|
elif b.name == enemyName: enScore = b.totalScore
|
|
let winner = if mbScore >= enScore: "ModularBot" else: enemyName
|
|
echo fmt" ModularBot: {mbScore} {enemyName}: {enScore} -> {winner} wins"
|
|
echo fmt" Rounds played: {r.rounds.len}"
|
|
|
|
# Write summary line to gauntlet log
|
|
let logLine = fmt"[{label}] ModularBot={mbScore} {enemyName}={enScore} winner={winner} rounds={r.rounds.len}"
|
|
let lf = open("/tmp/gun_gauntlet_results.log", fmAppend)
|
|
lf.writeLine(logLine)
|
|
lf.close()
|
|
|
|
ensureServer()
|
|
runBattle("Battle 1/5: vs SittingDuck", "SittingDuck", adversariesDir / "SittingDuck")
|
|
runBattle("Battle 2/5: vs OscillatorBot","OscillatorBot", adversariesDir / "OscillatorBot")
|
|
runBattle("Battle 3/5: vs RandomMover", "RandomMover", adversariesDir / "RandomMover")
|
|
runBattle("Battle 4/5: vs PatternMover", "PatternMover", adversariesDir / "PatternMover")
|
|
runBattle("Battle 5/5: vs WaveSurfer", "WaveSurfer", adversariesDir / "WaveSurfer")
|
|
echo "\nGauntlet complete. Stats in /tmp/gun_stats.jsonl and /tmp/gun_gauntlet_results.log"
|