PhantomMeteor:
- Ram finisher: charge at enemy when <200px and their energy <10
- Ram opportunity: charge when <60px and we have >20 energy advantage
- Integrated gunheat tracker for 1-2 tick earlier wave detection
- Distance control: smooth linear ramp toward preferred engagement distance
- Phantom range expanded 150→250px to catch closer threats
WaveSurfer:
- Wall-aware dodge bin selection: penalize bins leading off-arena
- Dodge timing: predict future position 15 ticks ahead for safety
- Distance control: radial blend when outside deadband (350±50px)
- Wall escape: invert strafe if pushing further into wall, blend toward center
ModularBot:
- Wired KNN gun (purple/magenta)
- Shadows tracked for movement (safer GF prediction)
- Bullet lifecycle management (onBulletFired/onBulletHitBot/onBulletHitWall)
- Unified phantom_meteor movement (wave_surfer unplugged)
- Config logging on round start + gun switch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gun selector now gates competition: guns with <15 total observations across
all power bins sit out until at least one gun qualifies. Falls back to ungated
selection if no gun reaches threshold, preventing cold-start stalls.
Sliding window increased from 50 to 100 ticks to reduce switching noise.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New DrussGT-inspired modules:
- KNNGun: K-nearest-neighbor statistical targeting using GF density peaks
- GunheatTracker: dual-heat system (predicted + confirmed) for 1-2 tick lead
- ShadowTracker: computes GF regions safe from in-flight bullets (enemy wave dodge)
VirtualBodyTracker now integrates gunheat for earlier fire detection and shadows
for safe-zone multiplier (90% reduction in danger zones).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Renames PatternMover_garage → PatternMover, RandomMover_garage → RandomMover,
WaveSurfer_garage → WaveSurfer. Updates all .json, .sh, .nimble, and config.nims
files to match TR Booter naming convention (directory name = bot name).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements VirtualBodyTracker (wave-based hit/miss scoring) instead of EMA damage accumulation. Movement switching now happens every tick, not every 3 rounds. Also refactors radar colors to dark teal (#004444/#0D4D4D) for faint visibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Adds WaveSurferModule as second movement option
- Tracks damage per round via onHitByBullet, EMA decay α=0.5
- Every round after round 2: switches to lower-damage movement
- Body color signals active mover (orange=phantom, blue=wave)
- vs SpinBot 10r: ModularBot 1412 vs SpinBot 650
- vs WaveSurfer 10r: ModularBot 1858 vs WaveSurfer 10
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GF gun: triangular head-on prior replaces flat bins (was always aiming at GF=-1)
- GF gun: recompute MEA per bullet power in onResult (was using stale first-bin value)
- Scores improved: SpinBot 1805-48, Crazy 1557-46, WaveSurfer 1868-10, PatternMover 1846-4
- All 6 guns active in selection across gauntlet
- Cold-start bug: uniform bins[0..30]=0.1 made peakBin() always return
0 (first-wins tie), giving GF=-1 (max CW escape) before any learning.
Fixed with a triangular head-on bump at bin 15 (GF=0) as the prior.
- onResult now recomputes mea from FeedbackEvent.bulletPower instead of
the stale first-bin mea cached by predict; correct per-power-bin GF.
- Add DebugGF const (default false) with [gf-dbg] echoes in predict/onResult.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
- 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>
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>
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>
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>
- 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>
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>
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>