fix(SNNBot): revert grid to working version, add file-based stats logging
Reverts reservoir.nim to the neighbor-blending forward() + single-cell learn() version (pre-bilinear-interpolation). Adds /tmp/snnbot_round_stats.log and /tmp/snnbot_aim_debug.log for diagnostics independent of test framework stdout. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,11 +9,39 @@
|
||||
# WAITING → aimTo() each tick; when error < 2° → EVALUATE
|
||||
# EVALUATE → measure error, compute SuperSpike/reservoir update, log, → DECIDE
|
||||
|
||||
import std/[math, random, os, strutils]
|
||||
import std/[math, random, os, strutils, strformat]
|
||||
import robocode_tankroyale_botapi
|
||||
import radar_lock/radar_lock as radar_lock
|
||||
import reservoir
|
||||
|
||||
# Diagnostic log file for bullet economy tracking (independent of test framework)
|
||||
let diagnosticLog = "/tmp/snnbot_diagnostic.log"
|
||||
let roundStatsLog = "/tmp/snnbot_round_stats.log"
|
||||
let aimDebugLog = "/tmp/snnbot_aim_debug.log"
|
||||
|
||||
proc diagLog(s: string) =
|
||||
try:
|
||||
let f = open(diagnosticLog, fmAppend)
|
||||
f.writeLine(s)
|
||||
f.close()
|
||||
except:
|
||||
discard
|
||||
|
||||
proc appendLog(path, s: string) =
|
||||
try:
|
||||
let f = open(path, fmAppend)
|
||||
f.writeLine(s)
|
||||
f.close()
|
||||
except:
|
||||
discard
|
||||
|
||||
proc truncateLog(path: string) =
|
||||
try:
|
||||
let f = open(path, fmWrite)
|
||||
f.close()
|
||||
except:
|
||||
discard
|
||||
|
||||
const USE_RESERVOIR* = true # ponytail: kept for SNN path fallback; remove when binary aimer is validated
|
||||
|
||||
# ── Constants ──────────────────────────────────────────────────────────────────
|
||||
@@ -303,9 +331,17 @@ method onRoundStarted*(bot: SNNBot, e: RoundStartedEvent) =
|
||||
setTargetSpeed(0.0)
|
||||
setTurnRate(0.0)
|
||||
|
||||
method onRoundEnded*(bot: SNNBot, e: RoundEndedEventForBot) =
|
||||
let rate = if bot.bulletsFired > 0: bot.bulletsHit.float / bot.bulletsFired.float * 100.0 else: 0.0
|
||||
let msg = "ROUND_STATS round=" & $e.roundNumber & " fired=" & $bot.bulletsFired & " hit=" & $bot.bulletsHit & " rate=" & formatFloat(rate, ffDecimal, 1) & "%"
|
||||
diagLog(msg)
|
||||
appendLog(roundStatsLog, fmt"ROUND fired={bot.bulletsFired} hit={bot.bulletsHit} rate={rate:.1f}% energy={getEnergy():.0f}")
|
||||
|
||||
method onGameStarted*(bot: SNNBot, e: GameStartedEventForBot) =
|
||||
initSNN(bot.snn)
|
||||
bot.res = initLeadGrid()
|
||||
truncateLog(roundStatsLog)
|
||||
truncateLog(aimDebugLog)
|
||||
|
||||
|
||||
method onBulletFired*(bot: SNNBot, e: BulletFiredEvent) =
|
||||
@@ -353,9 +389,11 @@ method run*(bot: SNNBot) =
|
||||
if aimOffset <= -999.0:
|
||||
bot.targetAngle = absBearing
|
||||
echo "RES tick=" & $bot.tick & " pwr=" & formatFloat(bot.currentFirePower, ffDecimal, 1) & " hitEMA=" & formatFloat(bot.hitRateEMA * 100.0, ffDecimal, 0) & "% cold-start aim=" & formatFloat(absBearing, ffDecimal, 1) & " fired=" & $bot.bulletsFired & " hit=" & $bot.bulletsHit & " rate=" & formatFloat(rate, ffDecimal, 1) & "% energy=" & formatFloat(getEnergy(), ffDecimal, 0) & " cells=" & $bot.res.totalCount
|
||||
diagLog("DECIDE tick=" & $bot.tick & " offset=cold-start cells=" & $bot.res.totalCount)
|
||||
else:
|
||||
bot.targetAngle = (absBearing + aimOffset + 360.0) mod 360.0
|
||||
echo "RES tick=" & $bot.tick & " pwr=" & formatFloat(bot.currentFirePower, ffDecimal, 1) & " hitEMA=" & formatFloat(bot.hitRateEMA * 100.0, ffDecimal, 0) & "% offset=" & formatFloat(aimOffset, ffDecimal, 1) & " aim=" & formatFloat(bot.targetAngle, ffDecimal, 1) & " fired=" & $bot.bulletsFired & " hit=" & $bot.bulletsHit & " rate=" & formatFloat(rate, ffDecimal, 1) & "% energy=" & formatFloat(getEnergy(), ffDecimal, 0) & " cells=" & $bot.res.totalCount
|
||||
diagLog("DECIDE tick=" & $bot.tick & " offset=" & formatFloat(aimOffset, ffDecimal, 2) & "° cells=" & $bot.res.totalCount)
|
||||
else:
|
||||
let inputs = encodeInputFull(absBearing, bot.velDirDeg, bot.velSpeed, bot.hasLastPos)
|
||||
# Multi-tick inference: accumulate sin/cos and spike counts over N_INFER ticks
|
||||
@@ -391,6 +429,8 @@ method run*(bot: SNNBot) =
|
||||
# Fire gate: gun must be aimed and settled before firing
|
||||
let energy = getEnergy()
|
||||
let readyToFire = err < 2.0 and energy >= ENERGY_GUARD and bot.roundTick >= PATIENCE_TICKS
|
||||
let leadOffset = normalizeRelativeAngle(bot.targetAngle - bot.lastAbsBearing)
|
||||
appendLog(aimDebugLog, fmt"TICK t={bot.roundTick} err={err:.2f} offset={leadOffset:.2f} vPerp={bot.lastVPerp:.2f} dist={bot.enemyDist:.1f} fired={readyToFire}")
|
||||
if readyToFire:
|
||||
bot.lastBulletSpeed = P2_SPEED
|
||||
discard setFire(2.0)
|
||||
|
||||
Reference in New Issue
Block a user