Files
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

93 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BNNBot Research Brief
## Problem
Predict enemy future position in Robocode Tank Royale to aim bullets accurately. The prediction must happen online (during battle), without pre-training.
## Hard Constraints
- NO supervised learning (no labeled input→output training pairs)
- NO gradient descent (no derivatives, no surrogate gradients, no STE)
- Online learning only — must learn and improve during a single battle
- Computational budget: ~1ms per tick
- Binary-friendly (690-bit input encoding already exists)
## Allowed
- Backpropagation of SIGNALS (non-gradient information flowing backward through layers)
- Reinforcement learning (reward signal available from wave hit system)
- Self-supervised learning
- Unsupervised learning
- Network structure modification during runtime
## Current Architecture
### Input Engineering (binary_encoding.nim)
- 690-bit binary vector: 10 frames × 69 bits
- Per frame: bearing sin/cos (16b), distance (7b), velocity (5b), heading sin/cos (16b), enemy X/Y position (14b), enemy energy (11b)
- Gray-coded for Hamming distance smoothness
- Temporal window: 10 most recent radar scans
### Feedback System (wave system in BNNBot.nim)
- Every tick: 10 circular waves spawned at bot position
- Powers: 0.1 to 3.0 (10 levels), speeds: 19.7 to 11.0 px/tick
- When wave radius reaches enemy: records enemy state as 69-bit frame
- Provides ground truth: "if you fired at power X, the enemy would be HERE when the bullet arrives"
- ~95.6% hit rate in testing
### Current Predictor (predictor.nim)
- Linear extrapolation: predicted = current_pos + velocity * ticks_to_arrival
- Hebbian residual table: 8 heading sectors × 3 distance bands = 24 cells
- Each cell stores (correction_x, correction_y), updated online with lr=0.2
- Backtest results: 14-21% MAE reduction over pure linear extrapolation
- Converges within one battle (MAE 14.85 → 2.62, first 50 vs last 50 rows)
## Key Findings
### Data Analysis (analysis/report.txt)
- Enemy movement is 97.8% constant-velocity straight lines
- Acceleration is negligible (std 0.25-0.49 px/tick²)
- Heading is very stable across 10-frame windows
- Linear extrapolation MAE: 15-27px (1.5-2.7% of arena)
- Distance to enemy is the main error driver
- Scalar velocity alone is weak predictor (r=0.15); directional velocity from frame deltas is strong
### Backtest Results (analysis/backtest_report.txt)
- P1 (linear): MAE 8.1-18.7 encoded units
- P2 (weighted 4-frame): ~8% improvement, trivial cost
- P3 (linear + Hebbian residual): 14-21% improvement, converges fast
- Most residual table cells stay empty — only ~10/24 activate
### Encoding Insights
- sin/cos angle encoding avoids wraparound discontinuity — worth the extra bits
- Enemy X/Y position partially redundant with bearing+distance (encodes absolute position)
- Wall distance → XY% compression saved 140 bits losslessly
- Self-state removed (not needed for aiming)
## What We've Tried
1. ✅ Input engineering with Gray coding and temporal window — works well
2. ✅ Linear extrapolation — strong baseline, 15-27px error
3. ✅ Hebbian residual table — learns online, 14-21% improvement
4. ❌ Pure XOR layer stacking — collapses (associative, no non-linearity)
5. ❌ XOR + AND layers — AND with fixed mask is still linear over GF(2)
6. ✅ XOR + popcount + threshold = valid binary neuron (non-linear)
## Open Questions
1. Can we go deeper than the current shallow predictor while respecting the constraints?
2. What non-gradient learning rules can train multi-layer binary networks?
3. Can the temporal structure (10 frames) be exploited by the network architecture?
4. Is there a way to do credit assignment through depth without gradients?
5. Can the wave hit system provide richer learning signal than just miss distance?
## Architecture Philosophy
- Input engineering IS the feature hierarchy (handcrafted, domain-informed)
- Current approach is essentially reservoir computing: rich fixed features → simple learnable readout
- Question: can we do better with a learnable feature extractor, or is the handcrafted one already near-optimal?
## Files
- `src/BNNBot.nim` — main bot, wave system, integration
- `src/binary_encoding.nim` — 690-bit input encoding
- `src/predictor.nim` — linear extrapolation + Hebbian residual table
- `analysis/correlations.py` — data analysis script
- `analysis/backtest.py` — predictor comparison script
- `analysis/report.txt` — correlation analysis results
- `analysis/backtest_report.txt` — predictor backtest results
- `data/` — CSV battle logs (enabled via BNNBOT_CSV=1)