tune(SNNBot): P2 volume strategy vs Walls — 0/10 wins

P1 (0/10, score 320) and P2 (0/10, score 593) both tested.
P2 scores ~85% higher than P1 despite same win rate, making it
the better base. Loosened fire gate to 5°, PATIENCE_TICKS=5,
COLD_K=3, travel time now uses actual bullet speed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 22:11:58 +02:00
parent 82ec84142c
commit 6da42fb06d
+14 -16
View File
@@ -45,8 +45,10 @@ const
# ponytail: uniform exploration noise; upgrade to annealed Gaussian if convergence needs tuning
ENERGY_GUARD = 10.0 # don't fire below this energy
P3_SPEED = 11.0 # bullet speed for P3 (20 - 3*3); used for exemplar learning
COLD_K = 8 # exemplars needed before switching cold→warm (P1→P3)
PATIENCE_TICKS = 15 # don't fire for the first N ticks of each round
P1_SPEED = 17.0 # bullet speed for P1 (20 - 3*1)
P2_SPEED = 14.0 # bullet speed for P2 (20 - 3*2)
COLD_K = 3 # exemplars needed before leaving cold start
PATIENCE_TICKS = 5 # min ticks before firing
# ── SNN types ─────────────────────────────────────────────────────────────────
@@ -291,9 +293,9 @@ method onRoundStarted*(bot: SNNBot, e: RoundStartedEvent) =
bot.bulletsHit = 0
bot.hitRateEMA = 0.5 # optimistic start
bot.powerChangeCounter = 0
bot.currentFirePower = 3.0
bot.bulletSpeed = P3_SPEED
bot.lastBulletSpeed = P3_SPEED
bot.currentFirePower = 2.0
bot.bulletSpeed = P2_SPEED
bot.lastBulletSpeed = P2_SPEED
bot.lastEnemyX = 0.0
bot.lastEnemyY = 0.0
bot.lastAbsBearing = 0.0
@@ -423,16 +425,13 @@ method run*(bot: SNNBot) =
aimTo(bot.targetAngle, gunDir)
let err = abs(normalizeRelativeAngle(bot.targetAngle - gunDir))
# Fire gate: loose during learning phase, strict after patience period
# ponytail: err thresholds tuned for P3 (slow bullet, needs good lead); adjust if still losing
# Fire gate: P1 volume strategy — 5° gate, fire after minimal patience
let energy = getEnergy()
let warmedUp = bot.res.count >= 10 and bot.roundTick >= PATIENCE_TICKS
let readyToFire =
if warmedUp: err < 3.0 and energy >= ENERGY_GUARD
else: err < 5.0 and energy >= ENERGY_GUARD # loose gate during learning
let warmedUp = bot.res.count >= COLD_K and bot.roundTick >= PATIENCE_TICKS
let readyToFire = err < 5.0 and energy >= ENERGY_GUARD and (bot.roundTick >= PATIENCE_TICKS or warmedUp)
if readyToFire:
bot.lastBulletSpeed = P3_SPEED
discard setFire(3.0)
bot.lastBulletSpeed = P2_SPEED
discard setFire(2.0)
bot.phase = EVALUATE
else:
discard setFire(0.0)
@@ -440,9 +439,8 @@ method run*(bot: SNNBot) =
of EVALUATE:
# Predictive error signal: extrapolate enemy position at bullet impact time.
if bot.hasLastPos:
# Always compute lead for P3_SPEED so exemplars teach P3-correct offsets,
# even when the actual shot was P1 (cold-start).
let travelTime = bot.enemyDist / P3_SPEED
# Use actual bullet speed for travel time (P1 = 17.0)
let travelTime = bot.enemyDist / bot.lastBulletSpeed
let velRad = degToRad(bot.velDirDeg)
let futureX = bot.lastEnemyX + cos(velRad) * bot.velSpeed * travelTime
let futureY = bot.lastEnemyY + sin(velRad) * bot.velSpeed * travelTime