j147 results: 180-battle live A/B on the frozen 15-opponent panel

Within-mover references (the only comparison that isolates the knob): tfil_lag1
-0.04 wins/run, strafe_lag1 +0.18 wins/run, both far under the reported MDEs
(0.33 / 0.41) -> NOT distinguishable, so TR_FIRE_LAG stays default 0. Incoming
hit rate also unmoved (+0.94 / +0.33 pp). The one significant result is the
mover (strafe_lag1 vs tfil_off +0.38 wins/run p=0.0386, hit rate -4.67pp
p=0.0074), which is the known strafe-over-tfil gap and exactly why the
within-mover reference was pre-registered.

Also a cosmetic no-op refactor of the two spawn sites (compute velX/velY once;
bit-identical, and it keeps the default-parity claim exact).
This commit is contained in:
2026-09-26 23:20:36 +02:00
parent d21f7ce5f5
commit 32ec040e90
4 changed files with 104 additions and 12 deletions
@@ -137,10 +137,10 @@ proc detect*(t: var FireTracker, id: int, energy: float,
import std/[math, os, strutils]
## ── j147: the DETECTION LAG back-date (`TR_FIRE_LAG`, default 0) ─────────────
## MEASURED LIVE (`common_libs/tests/measure_fire_ghost_lag.py`, 1171/1171 ghost
## spawns over two movers x 4 rounds, `TR_FIRE_DIAG=1`): the server dispatches a
## turn's fire AFTER our `go()` for that same turn, so the energy drop of a
## turn-T shot first reaches our scan at turn T+1 (our bot tick T). A bullet
## MEASURED LIVE (`common_libs/tests/measure_fire_ghost_lag.py`, 4 sessions,
## 1777 matched ghost spawns over both movers, `TR_FIRE_DIAG=1`): the server
## dispatches a turn's fire AFTER our `go()` for that same turn, so the energy
## drop of a turn-T shot first reaches our scan at turn T+1 (our bot tick T). A bullet
## takes its FIRST step during the turn it is fired, so by then the true bullet
## is already `speed` px (11..20 px, one whole bullet step) downrange and the
## arrival deadline is a full tick shorter than the ghost's. Both movers place