Commit Graph

337 Commits

Author SHA1 Message Date
SirStone 87bcd3df6b fix(SNNBot): fast recovery on target move + bidirectional fire gate
Problem 1: Dead zone (skip learn when error < 1.5°) means stale exemplars
linger in ring buffer after target moves. Fix: detect error jump >5° and
reset ring buffer (aimer.count, aimer.nextSlot = 0) for fresh start.

Problem 2: Fire gate only checked start condition (err < threshold), never
stopped firing when error worsened. Fix: explicit setFire(0.0) when error
exceeds tolerance, making gate bidirectional (start and stop).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-15 08:35:10 +02:00
SirStone 94fbde2934 fix(SNNBot): use absolute bearing to break aim feedback loop
The input encoded relative bearing, which changes when the bot aims,
creating a closed-loop oscillation (aim→input→aim). Switching to
absolute bearing (world frame) makes the input independent of aim
commands, eliminating the feedback-induced jitter.
2026-09-15 08:23:08 +02:00
SirStone b843a79313 feat(SNNBot): fire only when aim is locked on target
Bot now conserves ammo by firing only when aimLocked=true (error < 1.5°).
During WAITING phase, checks aimLocked flag before firing FIRE_POWER; calls
setFire(0.0) when not locked. Prevents wasted shots on moving targets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-15 08:15:29 +02:00
SirStone c05fb7a32b fix(SNNBot): hold aim when error is within dead zone
Adds aim-lock mechanism to prevent re-running forward() pass during DECIDE when the
error is already within 1.5° dead zone. Lock is set in EVALUATE when error < 1.5°,
reusing the previous targetAngle in DECIDE. Lock releases on fresh enemy scan or when
error exceeds threshold, eliminating the ±0.9° wobble from input pattern drift.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-15 08:14:28 +02:00
SirStone 8685f0e794 fix(SNNBot): skip learning when aim error < 1.5° (dead zone)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-15 08:10:31 +02:00
SirStone 844abe0bb7 feat(SNNBot): replace bin-based aimer with exemplar kernel regression
Eliminates aim jitter by switching from 360-bin WTA to weighted circular
mean over stored exemplars. Continuous float output, no bins, no
hysteresis, no saturation. K=128 ring buffer, Hamming similarity with
quadratic weighting.
2026-09-15 07:52:32 +02:00
SirStone 445c873316 fix(SNNBot): replace correct bin weights instead of OR to prevent saturation
OR-only reinforcement caused all bins to fill with set bits over time,
making all scores similar and the winner random. Now the correct bin
is REPLACED with the exact input pattern (no accumulation). Neighbors
still OR for generalization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-14 23:31:31 +02:00
SirStone be032e4ebd feat(SNNBot): replace aim smoothing with bin hysteresis
Smoothing masked jitter, hysteresis removes it at the source.
Gun stays on current bin unless a new bin wins by >1 point.
Removes all EMA/smoothing code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-14 23:28:50 +02:00
SirStone 9cb2727fef feat(SNNBot): distance-adaptive aim smoothing
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>
2026-09-14 23:25:50 +02:00
SirStone 21c974412c chore(SNNBot): remove SNN graph overlay, keep aiming lines
Deleted neuron panel visualization (input layer, hidden layer neurons, weight lines, output channels) from drawOverlay. Retain aiming lines: enemy bearing (green), gun direction (red), SNN target (yellow).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-14 23:23:42 +02:00
SirStone ac5301acb1 feat(SNNBot): exponential smoothing on aim angle to stop bin-flickering
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>
2026-09-14 23:22:43 +02:00
SirStone fc00e448a1 feat(SNNBot): 1° bin resolution (360 bins) + neighbor reinforcement
5° bins caused visible jumping. 360 bins at 1° costs 5.7KB.
Reinforce ±2 neighbors per learn call for faster coverage.
Punish only bins >2° away from correct target.
2026-09-14 23:19:25 +02:00
SirStone e9ddc7673d fix(SNNBot): binary-native input encoding with ~13 active bits
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.
2026-09-14 23:18:10 +02:00
SirStone f70d9e6d1e refactor(SNNBot): replace reservoir with direct binary readout
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.
2026-09-14 23:13:01 +02:00
SirStone 2963917072 fix(SNNBot): enforce sparse reservoir state via k-Winners-Take-All
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.
2026-09-14 23:08:06 +02:00
SirStone 45b167f2b3 fix(SNNBot): fix reservoir threshold, remove decay, stop re-forward in EVALUATE
- 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()
2026-09-14 23:04:45 +02:00
SirStone dbfb58ca1e feat(SNNBot): add binary reservoir aimer as alternative to SuperSpike (#159)
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>
2026-09-14 23:00:22 +02:00
SirStone 17178158b2 refactor(SNNBot): replace retroactive error with predictive lead target
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.
2026-09-14 22:39:28 +02:00
SirStone a78105c894 feat(SNNBot): fire bullets every tick at fixed power
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.
2026-09-14 22:30:28 +02:00
SirStone 42b6cebd8e fix(SNNBot): average matured snapshot targets instead of multiple updates
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.
2026-09-14 22:28:41 +02:00
SirStone d5777fba07 fix(SNNBot): apply weight update for every matured snapshot, not just last
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.
2026-09-14 22:25:39 +02:00
SirStone a80fd8d656 fix(SNNBot): increase learning rates — ETA 0.05→0.1, ETA_IH 0.005→0.02
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>
2026-09-14 22:21:29 +02:00
SirStone 80dbf81479 fix(SNNBot): tune SNN hyperparameters for 80-input layer
- 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>
2026-09-14 22:16:51 +02:00
SirStone 0ee5c21ef5 fix(SNNBot): store SNN state in aim snapshots for correct retroactive learning
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>
2026-09-14 22:08:22 +02:00
SirStone 5740c56a9f feat(SNNBot): add velocity input encoding and retroactive error signal (#159)
- 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>
2026-09-14 21:34:59 +02:00
SirStone 23bdf8acd6 research(SNNBot): survey existing lead-targeting and enemy tracking code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-13 20:30:10 +02:00
SirStone dbae449273 feat(SNNBot): replace R-STDP with SuperSpike learning rule (#158)
Three-factor local learning: Δw = η × pre_trace × σ'(U) × error
- Surrogate derivative σ'(U) = 1/(1+|β(U-ϑ)|)² gives directional gradient
- Random feedback weights project output error to hidden layer
- 10-tick inference window for rate-coded sin/cos output
- Fixed stale learning target bug (EVALUATE used wrong gun direction)

Hyperparams: ETA=0.05, THRESH=0.2, W_CLAMP=1.0, N_INFER=10, BETA=1.0
Removed: R-STDP eligibility traces, STDP timing window, exploration noise

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-13 20:07:31 +02:00
SirStone 7e1f1483a4 docs(test_framework): add comprehensive integration test guide and fix runner blocking issue
- Document exception handling, zero-value BotResult trap, shared adversary bots
- Add offline parsing example using parseServerOutput
- Skip tests gracefully when JARs missing (guard before suite blocks)
- Fix blocking readLine in runner_process.nim: poll with 50ms sleep + atEnd check
  (was preventing timeout enforcement, now blocks correctly during battle)
- Add test task to QBot.nimble and config.nims setup docs to AGENTS.md
- Add debug logging to TestBattleRunner for bot identity tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-13 10:54:56 +02:00
SirStone 2bfa8eb6a5 feat(SNNBot): add STDP learner and integration test (#153, #155)
- Implement reward-modulated STDP: spike timing, eligibility traces,
  reward-gated weight updates (w += η * reward * trace), clamp [-2,2]
- Add integration smoke test vs SittingDuck (compile + battle completion)
- Add tests/config.nims and nimble test task
2026-09-13 10:31:07 +02:00
SirStone c038128c2f feat(SNNBot): upgrade bot API, fix debug overlay and aiming lines
- Upgrade to robocode_tankroyale_botapi v1.0.7 (SVG viewBox fix)
- Fix Y-axis mirror in aiming line toXY helper
- Resize debug panel to half arena width/height
- Replace neuron boxes with barcode-style spike lines
- Thickness-encoded weight connections (all 216 lines)
- Add aiming line legend (top-left, white text)
- Dynamic aiming line length (distance + 50px overshoot)
2026-09-13 10:24:20 +02:00
SirStone 57a1915b10 feat: add shared integration test framework for garages (#126)
Implements:
- BattleResult type and JSON-lines parser (#127)
- TR server lifecycle manager (#128)
- Bot compiler using nim c (#129)
- runBattle() orchestrator (#130)
- Example test in OscillatorBot_garage (#131)
- Framework usage guide (#132)
- TestBattleRunner.java for external server (#133)
- BattleRunner process lifecycle (#134)

Fix: runner_process.nim was redefining TimeoutError locally; now
uses std/net.TimeoutError consistently with server_manager.nim.
2026-08-30 12:03:35 +02:00
SirStone a50571e6da docs: add NIM section to clarify main language usage 2026-08-27 19:16:38 +02:00
SirStone 06e68522cf Remove deprecated components from Tank Royale Bot API
- Deleted constants.nim, event_queue.nim, graphics.nim, json_parse.nim, schemas.nim, utils.nim, and ws_client.nim files.
- This cleanup removes unused code and simplifies the codebase, focusing on essential functionalities.
2026-08-27 18:45:56 +02:00
SirStone d3e4540e7f chore: add missing OscillatorBot.nimble 2026-08-27 18:42:35 +02:00
SirStone 259e67d7ff chore: standardize internal bot dir structure (src/, tests/, out/)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-27 18:42:03 +02:00
SirStone c5115fdf61 chore: standardize Nim builds to out/ subdir, simplify .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-27 18:35:54 +02:00
SirStone e276548223 chore: remove exported/ from AGENTS.md, generalize binary ignores in .gitignore
- Removed non-existent exported/ directory from layout docs
- Replaced hardcoded bot binary entries with *_garage/out/ pattern for build directories
- Added all known bot binaries (GotoTest, OscillatorBot, PPO_Bot, QBot, SAC_LSTM_Bot)
  to .gitignore with clarifying comment about Nim's compilation target structure

Nim places compiled binaries at bot root (no extension) and in out/ subdirs.
The out/ pattern catches all build outputs; specific bot binaries listed for
root-level executables since gitignore lacks a reliable "no-extension files" glob.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-08-27 18:32:09 +02:00
SirStone 2097c2e6fa chore: gitignore binaries/artifacts, remove drafts and stale files 2026-08-27 18:28:21 +02:00
SirStone 06ed905033 docs(AGENTS): generalize layout rules, remove hardcoded bot list 2026-08-27 18:22:38 +02:00
SirStone eab85be8b3 docs(AGENTS): update directory layout to match current structure 2026-08-27 18:19:37 +02:00
SirStone b509195ee9 chore: rename libs→common_libs, all bot dirs to _garage suffix, fix all path refs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-27 18:18:41 +02:00
SirStone f8c0c871c6 chore: remove unused prototypes/ and spike/ dirs 2026-08-27 18:16:34 +02:00
SirStone b9877bfff5 chore: add .gitignore 2026-08-27 18:12:08 +02:00
SirStone 8ba4bae21a chore: rename CLAUDE.md → AGENTS.md, move research doc to docs/ 2026-08-27 18:11:56 +02:00
SirStone f5b1ade48c fix(dashboard): harden generation against common failures 2026-08-24 11:10:39 +02:00
SirStone 12a0eca44a docs(dashboard): add health-check reference section 2026-08-24 10:18:43 +02:00
SirStone 08d1c44ca8 docs(dashboard): add how-to-read guide per panel 2026-08-24 09:25:14 +02:00
SirStone f47925eeb0 fix(dashboard): remove redundant standalone alpha panel 2026-08-24 09:22:54 +02:00
SirStone 55d69a9352 fix(dashboard): dual y-axis for losses+alpha panel 2026-08-24 09:21:43 +02:00
SirStone 4a6e3347c6 feat(dashboard): max-score-per-eval-cycle panel 2026-08-24 09:15:24 +02:00