Far targets need more smoothing (small jitter = big miss at distance).
Close targets need less (fast tracking). Linear ramp α=0.3..0.9 over 0..600 units.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adjacent 1° bins have similar scores, causing the winner to flip
tick to tick. Circular EMA (α=0.6) on sin/cos dampens oscillation
while preserving tracking response.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Float population code produced 0-1 active bits after binarization —
not enough to discriminate 72 bins. Replace with direct binary encoding:
5 bits per angular channel (center ± 2 neighbors), 3 bits for speed.
Adjacent bearings share 4/5 bits (smooth); distant bearings share 0
(clean separation). Fix circular error display.
Delete 1024-neuron reservoir — it added noise, not features.
Direct 80-bit input → 72 output bins via popcount + WTA Hebbian.
Same learning rule (OR reinforce, AND NOT punish), zero indirection.
Reservoir adds value for temporal features (step 3), not now.
Dense firing (~50%) caused all readout bins to saturate identically.
Replace threshold-based firing with k-WTA: only top 50 neurons fire
per tick (~5% sparsity). Sparse patterns give low inter-angle overlap
-> readout bins can discriminate between different bearings.
- Threshold 4→1: neurons now fire (~50% rate) instead of never firing
- Remove aggressive decay that erased learning signal immediately
- Remove EVALUATE re-forward that corrupted reservoir state before learn()
New architecture: 1024 binary neurons in fixed random reservoir,
72-bin population-coded output, WTA Hebbian learning with binary ops.
Forward pass: AND + popcount. Learning: OR (reinforce) / AND NOT (punish).
No backprop, no floats in hot path. Toggle via USE_RESERVOIR const.
Forecast: ~200-400 ticks to learn stationary target aiming.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delete ring buffer, aim snapshots, maturation loop (~80 lines).
Replace with simple velocity extrapolation: predict enemy position at
bullet impact time, use bearing to predicted position as SuperSpike
target. Immediate error signal every EVALUATE — no delay, no snapshot
state storage. Mathematically equivalent to retroactive for linear movers.
Fire during WAITING phase using FIRE_POWER constant (matches error
signal's bullet speed calculation). Always shooting — fire timing
optimization is out of scope for this map.
Multiple superSpikeUpdate calls per EVALUATE caused oscillation by
effectively multiplying the learning rate. Now: accumulate retroTarget
via circular mean across all matured snapshots, apply one update with
the averaged target and most recent snapshot's SNN state.
Multiple snapshots can mature by EVALUATE time but only the last one
triggered a superSpikeUpdate. Earlier matured snapshots were silently
discarded — wasting learning signal. Now each matured snapshot with a
valid ring buffer hit gets its own weight update.
Weights were barely moving: |wih| +0.14%, |wOut| +7.7% over full session.
Bump output ETA 2x and input→hidden ETA 4x to accelerate convergence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Lower THRESH 0.2→0.08 to increase hidden firing rates (output layer was frozen due to rate≈0 in weight updates)
- Add ETA_IH=0.005 for input→hidden updates (10x smaller than output ETA=0.05 to prevent weight thrashing from large preTrace magnitudes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The retroactive error signal matures many ticks after the snapshot was taken,
but superSpikeUpdate was using bot.lastSpikes/lastVSnap which had been
overwritten by subsequent DECIDE cycles. Learning was applied against wrong
neural activity — effectively random weight perturbations.
Fix: AimSnapshot now captures spikes, vSnap, and preTrace at DECIDE time.
superSpikeUpdate receives these saved values at maturation instead of the
stale current state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Expand input layer from 36 to 80 neurons: bearing (0-35) + velocity direction (36-71) + speed (72-79)
- Population-code velocity direction (same 10° band scheme as bearing) and speed (8 bands, 1 unit/tick)
- Compute 1-tick velocity from position deltas in onScannedBot
- Add 100-slot ring buffer with per-slot tick tracking for enemy positions
- Replace instantaneous bearing error with retroactive would-have-hit signal
- Skip learning until first aim snapshot matures (buffer fill period)
- Delayed-target SuperSpike: weight updates use most recently matured retroactive bearing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>