Commit Graph

398 Commits

Author SHA1 Message Date
SirStone 1ed7797cb6 feat(ModularBot): 6 guns, pattern matcher, melee modules, adversarial bots
- New guns: guess-factor (GF histogram), pattern-matcher (movement tape replay)
- New modules: minimum-risk melee movement, spinning melee radar
- New test bots: PatternMover, RandomMover, WaveSurfer
- Fixed: FeedbackEvent now carries actualX/actualY for proper GF learning
- Fixed: TM gun warmup gating + directional residuals
- Fixed: circular gun integrated formula + multi-bin omega cache
- Fixed: oscillator wall-bounce lockout
- Fixed: phantom meteor perpendicular body orientation
- 6/6 battle wins across all enemy types
2026-09-20 00:59:53 +02:00
SirStone 254c7dc997 feat(ModularBot): pluggable bot with 4 guns, phantom meteor movement, radar harness
- Gun harness: virtual bullet tracker, rolling fitness, auto-selector
- Guns: head-on, linear (extrapolation), circular (integrated formula), tsetlin machine (learning)
- Movement: phantom meteor gravity engine (danger histograms, phantom bullets, fire detection)
- Radar: harness + radar_lock adapter
- Color-coded modules: turret/bullet color per gun, body per movement, scan per radar
- Beats Target, SpinBot, Crazy, TrackFire in 10-round battles
2026-09-20 00:37:10 +02:00
SirStone c9191b7afb fix(circular-gun): correct turn-rate calculation for multi-scan delays
Two bugs fixed:
1. Multi-tick gaps: turn rate assumed 1 tick between observations, but scans can be 5+ ticks apart. Now divides by actual tickDelta.
2. Per-power-bin state corruption: predict() called 4x per tick (per power bin). After first call, prevHeading was already updated, causing subsequent calls to compute 0° delta. Now captures oldHeading/oldTick before updating.

Verified: OscillatorBot at 4°/tick captured correctly; normalization [-180°,180°] works; tickDelta=1 typical; first bin gets delta, subsequent bins see 0 (expected).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-19 19:43:40 +02:00
SirStone dd78f3c239 fix(hebbian): symmetric learning — both active and inactive outputs learn
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-18 00:13:32 +02:00
SirStone f12bdf810e feat(BNNBot): shaped reward based on miss distance — every shot teaches something
Replace binary hit/miss reward with exponential decay based on miss distance:
- reward = 2.0 * exp(-missDistance / 36.0) - 1.0
- At 0px: +1.0 (perfect hit)
- At 36px: -0.26 (near miss, small penalty)
- At 100px: -0.87 (big miss, large penalty)

Maintains virtual hit/miss counters for display (threshold: 36px).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-18 00:10:28 +02:00
SirStone 63685b1729 style(BNNBot): remove 870-bit binary dump from output 2026-09-18 00:05:20 +02:00
SirStone b945bb1ac5 fix(hebbian): random weight init to escape zero local minimum
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 00:03:26 +02:00
SirStone e600204c84 feat(BNNBot): add virtual hit percentage to output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 23:54:31 +02:00
SirStone 481f284e1a fix(BNNBot): correct sin/cos for bullet position, gentler 1-bit exploration
- Swap sin/cos in virtual bullet position calc to match Tank Royale convention
- Change exploration from flipping each bit with 50% chance to flipping exactly 1 random bit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 23:51:22 +02:00
SirStone 22aefbddb6 feat(BNNBot): Hebbian weight matrix with virtual bullet learning — 870→7 bit forward pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 23:49:59 +02:00
SirStone 50e3c6fae9 feat(BNNBot): 10-tick sliding window of enemy data + self state — 870 bits total
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 23:35:57 +02:00
SirStone 89f63540bc feat(BNNBot): energy to 11 bits for 0.1 HP precision — 123 bits total
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 23:25:09 +02:00
SirStone 152fcba0cc feat(BNNBot): add energy (8+8 bits) and gun ready (1 bit) — 117 bits total
Added myEnergy, enemyEnergy, and canFire to ScanData. Energy fields quantize 0-150 → 8 bits each; gun ready is 1 bit (1 = can fire, 0 = can't). Updated total encoding from 100 to 117 bits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 23:21:39 +02:00
SirStone 938c259260 feat(BNNBot): add wall distances for both bots to binary encoding (100 bits total)
8 new fields in ScanData (myWallN/S/E/W, enemyWallN/S/E/W), 7 bits each via Gray code,
appended after existing 44 bits. TOTAL_BITS 44 → 100.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 23:17:26 +02:00
SirStone f82a74731d feat(BNNBot): add similarity and overlap metrics to output
Output format: <tick> <44 bits> <hamming> <similarity> <overlap>
- Similarity: bits that are the same (TOTAL_BITS - hamming)
- Overlap: bits that are 1 in both vectors (popcount of bitwise AND)
- First tick: all metrics printed as 0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 23:13:06 +02:00
SirStone 16c3e068fd style(BNNBot): align tick number in output 2026-09-17 22:59:56 +02:00
SirStone fa4c36acfe feat(BNNBot): print Hamming distance from previous tick 2026-09-17 22:58:14 +02:00
SirStone 27cc5720a3 feat(BNNBot): switch to Gray code encoding for smooth Hamming distance 2026-09-17 22:53:03 +02:00
SirStone 0f20e1a869 feat(BNNBot): 44-bit encoding with sin/cos bearing+heading, distance%, velocity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 22:47:04 +02:00
SirStone b31d1bf99f simplify(BNNBot): raw 10-bit binary encoding, clean output
- Replace population/thermometer/signed-thermometer encoding with simple 10-bit binary per value
- 5 values × 10 bits = 50 bits total (was 112)
- Each value normalized to 0-1023, then bit-extracted MSB-first
- Output is now just tick and raw binary string (no field labels, no debug log)
- Remove file logging entirely; stdout only

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 22:24:52 +02:00
SirStone 808ae44703 feat(BNNBot): scaffold binary neural network bot with scan data collection and binary encoding visualization
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 22:15:51 +02:00
SirStone 85005c1c27 milestone(SNNBot): 48% hit rate, grid accumulator with warm-start + frozen DECIDE snapshot — pausing for BNNBot exploration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-17 22:13:35 +02:00
SirStone 8289488e13 experiment(reservoir): reduce warm-start weight to 0.1 for faster learning adaptation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:44:47 +02:00
SirStone a20796cf9b feat(reservoir): warm-start grid with analytical lead values
Pre-populate all LeadGrid cells with arcsin(vPerp/bulletSpeed) so the
grid starts warm instead of cold, avoiding the early-round 0-data
fallback to -999 (no-lead) firing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:38:37 +02:00
SirStone 2d7413666c fix(SNNBot): freeze DECIDE-time snapshot for EVALUATE — eliminates training signal noise
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:36:09 +02:00
SirStone 26438395a8 diag(SNNBot): revert to baseline, add bias diagnostics
Reverted fire gate from 1° back to 2°, removed gridHasData cold-start
guard so bot fires on straight aim during cold-start. Added
/tmp/snnbot_bias_debug.log BIAS entries in EVALUATE phase logging
gridOffset, correctOffset, bias, vPerp, dist per cycle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:34:04 +02:00
SirStone d545a6f95d experiment(SNNBot): power 2, tight 1° fire gate, suppress cold-start fire
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:30:52 +02:00
SirStone 7e3e13386c experiment(SNNBot): try power 3 for more damage per hit, revert adaptive complexity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:27:59 +02:00
SirStone faa3edbe32 feat(SNNBot): adaptive fire power with lead scaling and velocity transition suppression
- P3 at err<0.5°, P1 at err<2.0° (was fixed P2); no fire at err>=2.0°
- Scale grid lead offset by bullet speed ratio (sin(θ) ∝ 1/v_bullet)
- ENERGY_GUARD 5→15 to survive Walls' sustained fire
- Suppress fire when |vPerp delta| > 2.0 (enemy changing direction)
- Store lastBulletSpeed = 20-3*chosenPower for correct EVALUATE travel time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:23:13 +02:00
SirStone 86dfd672b1 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>
2026-09-17 08:18:59 +02:00
SirStone 34f952ce20 fix(reservoir): proper bilinear interpolation in forward(), revert neighbor spread in learn()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:16:20 +02:00
SirStone 10a0696176 feat(reservoir): spread learning to neighbor grid cells for smoother interpolation
Each learn() call now updates a 3×3 neighborhood (center w=1.0, cardinal w=0.3,
diagonal w=0.1). count field changed to float64 to support fractional weights.
Fills grid ~5× faster and eliminates one-sided interpolation at bin boundaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:13:29 +02:00
SirStone 6274c0d29c fix(SNNBot): use 2° error gate for firing, remove unreliable gunTurnRemaining check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:05:33 +02:00
SirStone 20a6132530 fix(SNNBot): add gun-settled guard before firing — only fire when gun turn remaining < 1°
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-17 08:01:51 +02:00
SirStone 039b47b151 feat(SNNBot): grid accumulator replaces exemplar ring buffer
Ring buffer had amnesia — cycled out all data every 128 ticks,
preventing convergence. Grid accumulator permanently stores average
lead offsets indexed by (v_perp, distance). 136 cells, 1.5 KB.
Knowledge accumulates across rounds → convergence guaranteed for
stationary velocity patterns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 23:22:00 +02:00
SirStone d7e499209c tune(SNNBot): P2 fast bullets vs Walls — 3/20 wins
PATIENCE_TICKS 15→5, ENERGY_GUARD 10→5, fire gate 5° always, power 2.0
(speed 14). P1 (power 1) scored 0/20; P2 compromise wins 3/20.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 23:17:35 +02:00
SirStone 4bc7baee04 feat(SNNBot): encode perpendicular velocity for unambiguous lead
relVelDir ±5° shared 80% of bits despite needing opposite lead.
Now encodes v_perp = speed×sin(relVelDir) directly with signed
thermometer coding — positive and negative crossing velocities
have zero bit overlap. Also adds v_parallel for approach/recede.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 23:15:34 +02:00
SirStone 929fe5a696 tune(SNNBot): restore P3 + patience config with improved encoding
Set currentFirePower=3.0, bulletSpeed=P3_SPEED (11.0), PATIENCE_TICKS=15.
Fire gate: strict 3° post-warmup, loose 5° cold-start.
Thermometer speed encoding (bits 36-43) unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 23:12:49 +02:00
SirStone cc3c2649c2 feat(SNNBot): thermometer speed encoding for precise lead discrimination
3-bit speed encoding couldn't distinguish speed 3 from speed 5 —
9° of lead error baked into the input. Thermometer coding with 8 bits
gives 1-bit Hamming distance between adjacent speeds. MAX_K back to 128.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 23:10:04 +02:00
SirStone be4e9549ef fix(test_framework): pass --tps -1 to server for uncapped headless speed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-16 22:57:28 +02:00
SirStone 6da42fb06d 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>
2026-09-16 22:11:58 +02:00
SirStone 82ec84142c feat(SNNBot): patience-first strategy — P3 always, strict fire gate after warmup
- ENERGY_GUARD 15→10 to squeeze more shots out
- Remove power ladder (always P3, bulletSpeed=11)
- Add PATIENCE_TICKS=15: first 15 ticks per round use loose 5° gate (collect exemplars)
- After warmup (≥10 exemplars AND ≥15 ticks): strict 3° gate to avoid wasted shots
- roundTick counter resets each round; BinaryAimer exemplars persist across rounds
- Remove dead selectFirePower proc

Result: 30% win rate vs Walls (was 0%), survival in 7/10 rounds

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 22:01:57 +02:00
SirStone 802e0e0056 feat(SNNBot): physics-based input encoding for lead generalization
Replace (bearing, velDir, speed) with (relVelDir, speed, distance).
Raw bearing is irrelevant to lead offset — the correction depends on
how the target crosses the line of fire, not where it is. This lets
exemplars from one position generalize to all positions with similar
geometry.
2026-09-16 21:48:06 +02:00
SirStone 57cbcc5699 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>
2026-09-16 21:43:23 +02:00
SirStone 0384e2ba6a tune(SNNBot): bullet economy tuning vs Walls — 2/10 wins
Changes:
- Fixed fire power at 3.0 (removes hitRateEMA power ladder noise that
  cleared exemplars mid-battle and corrupted learning)
- Relative velocity encoding: input uses (velDir - bearing) instead of
  absolute velDir, so exemplars generalize across Walls' starting walls
- Fix test winner detection to use per-round score delta instead of
  rank field (rank in round_ended is cumulative battle rank, not round winner)
- Keep exemplars across power changes (no longer relevant with fixed power)
- Store lastBulletSpeed at fire time for accurate EVALUATE lead prediction

Result: 2/10 rounds won vs Walls (Nim); first-round win now possible from
round 1 when aimer generalizes from relative velocity patterns.
Bottleneck: sparse exemplars in early rounds; energy bleeds at P3 cold-start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-16 21:23:15 +02:00
SirStone cd0a19dbc5 fix(test_bullet_economy): correct bot name and rank comparison for winner detection
- Match "Walls (Nim)" instead of "WallsBot" — sample bot reports with "(Nim)" suffix
- Guard against unmatched bot (rank=0) so a missing entry doesn't silently flip the winner
- The rank comparison itself (lower = better) was correct; the stale name was the root cause

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 09:06:02 +02:00
SirStone 8f454285aa fix(test_framework): pass --max-speed to Java runner and drain stdout to prevent pipe stall
- Add maxSpeed param (default true) to runBattleRunner/runBattle
- Drain stdout in poll loop — Java blocked on full pipe buffer causing timeout
- TestBattleRunner.java already had --max-speed; .class was stale and needed recompile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 09:02:20 +02:00
SirStone c671e0b0e3 feat(test_framework): use TR_SAMPLE_BOTS env var for external bot directory
Adds TR_SAMPLE_BOTS env var support to point to external sample bots (Walls, Fire, SpinBot, etc). Updates test_bullet_economy.nim to use Walls from the sample-bots directory instead of custom WallsBot, removing the hardcoded path dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-09-16 08:43:46 +02:00
SirStone 67bba96da1 remove(test_framework): delete custom WallsBot, will use original bots 2026-09-16 08:43:16 +02:00
SirStone ffa277e31d feat(SNNBot): add bullet economy test against WallsBot
Add --max-speed flag to TestBattleRunner (sets defaultTurnsPerSecond=-1 for unlimited TPS).
Add SNNBot_garage/tests/test_bullet_economy.nim: 10-round vs WallsBot, prints per-round and summary stats for tuning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 08:41:25 +02:00