tune(SNNBot): P1 cold-start with P3-target learning — 2/10 wins
Fire P1 for first COLD_K=8 exemplars (cheap misses), always store P3-correct lead offsets using P3_SPEED=11 in EVALUATE travelTime. Switches to P3 once exemplar buffer has enough data. Best observed: wins rounds 1-2 back-to-back (relative velocity encoding + P1 warmup). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,9 @@ const
|
||||
BETA = 1.0 # surrogate steepness (unitless; potentials are unitless)
|
||||
NOISE_AMP = 0.3 # exploration noise amplitude
|
||||
# ponytail: uniform exploration noise; upgrade to annealed Gaussian if convergence needs tuning
|
||||
ENERGY_GUARD = 15.0 # don't fire below this energy
|
||||
ENERGY_GUARD = 15.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)
|
||||
|
||||
# ── SNN types ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -447,10 +449,12 @@ method run*(bot: SNNBot) =
|
||||
|
||||
# Fire gate: only fire when error within adaptive dead zone
|
||||
if err < adaptiveDeadZone:
|
||||
# ponytail: fixed power 3.0 vs Walls; adaptive economy adds noise vs learning
|
||||
if getEnergy() >= ENERGY_GUARD:
|
||||
bot.lastBulletSpeed = bot.bulletSpeed
|
||||
discard setFire(bot.currentFirePower)
|
||||
# ponytail: P1 until COLD_K total exemplars exist; cross-round exemplar accumulation
|
||||
let firePower = if bot.res.count < COLD_K: 1.0 else: bot.currentFirePower
|
||||
let fireSpeed = 20.0 - 3.0 * firePower
|
||||
bot.lastBulletSpeed = fireSpeed
|
||||
discard setFire(firePower)
|
||||
bot.phase = EVALUATE
|
||||
else:
|
||||
discard setFire(0.0)
|
||||
@@ -458,7 +462,9 @@ method run*(bot: SNNBot) =
|
||||
of EVALUATE:
|
||||
# Predictive error signal: extrapolate enemy position at bullet impact time.
|
||||
if bot.hasLastPos:
|
||||
let travelTime = bot.enemyDist / bot.lastBulletSpeed # use speed from fire tick
|
||||
# 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
|
||||
let velRad = degToRad(bot.velDirDeg)
|
||||
let futureX = bot.lastEnemyX + cos(velRad) * bot.velSpeed * travelTime
|
||||
let futureY = bot.lastEnemyY + sin(velRad) * bot.velSpeed * travelTime
|
||||
|
||||
@@ -54,3 +54,4 @@ proc learn*(aimer: var BinaryAimer, input: BitVec80, offset: float) =
|
||||
aimer.exemplars[aimer.nextSlot] = Exemplar(pattern: input, offset: offset, active: true)
|
||||
aimer.nextSlot = (aimer.nextSlot + 1) mod MAX_K
|
||||
if aimer.count < MAX_K: inc aimer.count
|
||||
|
||||
|
||||
Reference in New Issue
Block a user