## L4: one live gauntlet proving `Tsetlin.vHits != Linear.vHits`. ## ## Runs ModularBot against a chosen adversary through the real Tank Royale server ## and reads the per-gun virtual-bullet window from /tmp/gun_stats.jsonl (written ## by ModularBot.onRoundEnded, independent of the RecordWorldState flag). ## ## Usage: nim c -r common_libs/tests/check_tsetlin_live.nim [AdversaryName] [rounds] ## default adversary RandomMover, 3 rounds. ## Skips cleanly when the TR JARs are unavailable. import std/[os, strformat, json, strutils] import test_framework/test_framework const repoRoot = currentSourcePath().parentDir.parentDir.parentDir modularBotDir = repoRoot / "ModularBot_garage" adversariesDir = repoRoot / "common_libs" / "test_framework" / "adversaries" statsPath = "/tmp/gun_stats.jsonl" proc main() = let adversary = if paramCount() >= 1: paramStr(1) else: "RandomMover" let rounds = if paramCount() >= 2: parseInt(paramStr(2)) else: 3 let advDir = adversariesDir / adversary if not dirExists(advDir): echo "Skipping: adversary not found: ", advDir quit(0) if getEnv("TR_SERVER_JAR", "").len == 0 and not fileExists("/home/davide/Projects/tank-royale/server/build/libs/robocode-tankroyale-server-0.35.5-all.jar"): echo "Skipping: TR server JAR not found" quit(0) if fileExists(statsPath): removeFile(statsPath) echo &"live battle: ModularBot vs {adversary}, {rounds} round(s)" let battle = runBattle(@[modularBotDir, advDir], rounds = rounds, timeout = 300000, maxSpeed = true) for r in battle.results: echo &" {r.name:<14} rank={r.rank} score={r.totalScore}" var tHits, tShots, lHits, lShots, vDrop, vStarve = 0 var rows = 0 if fileExists(statsPath): for line in lines(statsPath): let s = line.strip() if s.len == 0: continue let d = parseJson(s) if not d.hasKey("guns"): continue inc rows for g in d["guns"]: case g["name"].getStr() of "Tsetlin": tHits += g["vHits"].getInt(); tShots += g["vShots"].getInt() of "Linear": lHits += g["vHits"].getInt(); lShots += g["vShots"].getInt() else: discard vDrop = d["vDropped"].getInt() vStarve = d["vStarved"].getInt() echo "" echo &"rounds logged: {rows}" echo &"Tsetlin vHits={tHits}/{tShots} Linear vHits={lHits}/{lShots}" echo &"vDropped={vDrop} vStarved={vStarve}" if tHits != lHits: echo "VERDICT: DIVERGED — Tsetlin.vHits != Linear.vHits" else: echo "VERDICT: IDENTICAL — the fix did not change the live outcome for this opponent" if vDrop != 0 or vStarve != 0: echo "WARNING: vDropped/vStarved are non-zero" quit(1) when isMainModule: main()