5 Commits

Author SHA1 Message Date
SirStone fb36a0a685 tracker: corpses do not exist - revert the fix and retire the workaround
The belief "BotDeathEvent never reaches ModularBot, so enemyTracker keeps dead
enemies alive forever" was written into a code comment and then believed twice.
It is FALSE. Measured in a 7-bot melee with a per-tick probe comparing
enemyTracker's alive count against the server's getEnemyCount():

  metric                          1.3.1 (20 rd)   0.35.5 (15 rd)
  observed enemy deaths                83              68
  ...non-round-ending              83 (100%)       66 (97%)
  ekBotDeath events DROPPED             0               0
  max dispatch lag (turns behind)       1               1
  phantom ticks                  1 / 16,820      1 / 12,596
  MAX CORPSE LIFETIME               0 ticks         0 ticks
  victims still alive at round end      0               0

onBotDeath fires for every death, including non-round-ending ones. The
API-level event-drop mechanism IS real (test_event_drop_mechanism.nim proves
it: ekBotDeath is not in isCritical and MAX_EVENTS_AGE=2) - the bot simply
never falls far enough behind for it to trigger (max lag 1 turn).

Removed:
- reconcileWithServer + ReconcilePersistTicks/mismatchTicks/sawServerAlive
  (uncommitted, and ON BY DEFAULT despite the premise being false). Its own
  comment admitted a shorter window once KILLED A LIVE ENEMY ("it fired three
  more times after the tracker marked it dead") - a latent mis-prune path
  defending against a bug that does not exist.
- The radar's CorpseTicks=40 filter and the same-class age>60 filter in
  recordRadarStats, both carrying the false comment. Removal changes no real
  behaviour: buildState feeds the radar enemyTracker.allAlive(), so a dead
  enemy never reaches computeScan.

Kept:
- The TR_TRACKER_PROBE instrument (default OFF), which produced the table above.
- test_event_drop_mechanism.nim - the drop mechanism is a genuine library
  behaviour worth guarding.
- isAlive/aliveCount on the tracker.

Added: docs/tracker_death_events.md (the durable negative, so this is not
re-invented a third time) and test_enemy_tracker_death.nim (13 checks) in place
of the test for the deleted feature.

Guards: test_gun_harness 39/39, test_vbullet_metric 11, test_power_selection 3,
test_adaptive_radar 41/41, test_event_drop_mechanism 6, test_enemy_tracker_death
13, acceptance 12/12, ModularBot compiles.
2026-09-21 22:41:11 +02:00
SirStone 68e0375be2 feat(radar): adaptive melee radar sweeps only the arc containing all enemies
Replaces melee_scan in the rack. melee_scan spun the radar at the 45 deg/tick
cap unconditionally, so a full 360 deg revolution took 8 ticks and every enemy
was scanned roughly every 8 ticks. The new module starts with the same full
spin, and once it is SURE it has covered every enemy it sweeps back and forth
over only the minimal covering arc of all enemy bearings.

MEASURED, real melees via the bridge, per-enemy onScannedBot counts:
  3-bot melee (2 enemies): 29.6 -> 61.1 scans/100 melee-ticks  (2.06x)
  4-bot melee (3 enemies): 36.0 -> 75.7 scans/100 melee-ticks  (2.10x)
Covering-arc widths observed: mostly <90 deg in the 2-enemy case, up to 240 deg
in the 3-enemy case, so the gain shrinks as the arc widens - and at the
ExitTrackWidthDeg=300 fallback it degenerates to exactly the old full spin, so
there is no loss when narrowing would not help.

TRADEOFF, recorded rather than hidden: a wider arc legitimately takes longer to
traverse, so the freshness window costs 5-7 points (fresh<=16: 93-95% vs
98-100%) and more at fresh<=8 (75-76% vs 97-100%). More scans per enemy, at
slightly staler individual fixes.

DESIGN: acquisition spins 360 until every live known enemy was seen within
FreshnessTicks=16 (two revolutions of slack), no new id appeared, and the live
count matches getEnemyCount(); that must hold FreshStreakTicks=3 consecutive
ticks. Tracking then bang-bang sweeps the wraparound-aware covering arc
(350+10 -> 20 through 0) widened by MarginDeg=20 each end, at up to 45 deg/tick.
Fallbacks return to acquisition: any stale enemy, any new id, or an arc >= 300
deg. Enter 270 / Exit 300 gives 30 deg of hysteresis so it cannot flap.

Adds EnemyInfo.lastSeenTick (additive) so coverage is judged on staleness, not
mere knowledge - without it an enemy that slipped behind the sweep would keep
contributing its own stale bearing, which is self-confirming. The offline range
now round-trips that field from the fixture 'lst'.

COMPANION FIX, and it matters: the radar-mode switch used the TRACKER's known
enemy count, so in melee the bot saw one enemy before scanning the second, locked
to 1v1, and the melee radar never ran at all. Now uses getEnemyCount() (server
truth), so melee mode persists until one enemy is genuinely left.

41 new unit checks (wraparound arcs, straddle at 0/360, single/empty enemies,
the 45 deg/tick cap, every phase transition and fallback). melee_scan is kept
but marked DEPRECATED; nothing in the rack imports it.

Non-regression: 33 gun-harness checks, vbullet metric, power selection, and
12/12 offline==online acceptance all pass.
2026-09-21 21:35:22 +02:00
SirStone 2cc2a3bd87 fix(ModularBot): ram loop prevention, dead-target guards, cleaner logging
- 30-tick cooldown after ghost-stuck/timeout ram exit prevents re-entry loop
- enemy_tracker.update() skips dead bots to prevent same-tick scan resurrection
- TFIL graphics cleared when ramming is active movement
- [config] logs: white base with green-highlighted changes only
- [ram:enter] logs trigger reason and key values on false→true transition
- [death] and [target-invalid] logs retained for diagnostics
2026-09-20 20:44:45 +02:00
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