|
|
|
@@ -3571,3 +3571,92 @@ Panel: the FROZEN 15-opponent `tools/ab/panel_movement.txt`. Harness:
|
|
|
|
|
retract the geometric measurement, and does NOT change `TR_MOVEMENT=strafe`.
|
|
|
|
|
|
|
|
|
|
*(results appended below after the battles)*
|
|
|
|
|
|
|
|
|
|
### MEASURED — gate B: the guard (`test_tfil_commit_env.nim`, 77 -> 87 checks)
|
|
|
|
|
|
|
|
|
|
All 87 pass, including the byte-for-byte golden replay of the shipped mover with
|
|
|
|
|
`TR_FIRE_LAG` unset (check 1). The j147 ones:
|
|
|
|
|
|
|
|
|
|
* `TR_FIRE_LAG` unset -> `FireLag 0`, and the ghost lands EXACTLY on the scanned
|
|
|
|
|
enemy (`b.x == ei.x` bit for bit — the position is only touched when `lag > 0`).
|
|
|
|
|
* `=1` -> the ghost is exactly one bullet step (17 px at power 1.0) downrange on
|
|
|
|
|
its own heading; `=2` -> exactly two; the step length is the true
|
|
|
|
|
`20 - 3*power`, not a scaled one.
|
|
|
|
|
* **the arrival deadline**: the mover's eta equals the TRUE remaining flight
|
|
|
|
|
(10.764706 vs 10.764706) where the lag-0 eta was 11.764706 — a full tick late;
|
|
|
|
|
at `lag=2` the deadline shortens by exactly 2 ticks.
|
|
|
|
|
* a junk or negative value degrades to the shipped lag 0 (never a negative
|
|
|
|
|
back-date); clearing the knob restores the shipped spawn exactly.
|
|
|
|
|
* end to end: the ghost is reaped (`dot < 0`, the geometric arrival the mover
|
|
|
|
|
actually uses) **exactly one tick earlier** — 12 -> 11 ticks.
|
|
|
|
|
* `test_env_report` + `test_env_dotenv` green with `TR_FIRE_LAG` registered in
|
|
|
|
|
`env_report.nim` + `knownEnvNames()` + `.env.example` + `docs/env_reference.md`.
|
|
|
|
|
|
|
|
|
|
### MEASURED — gate C: the live A/B, 180 battles
|
|
|
|
|
|
|
|
|
|
> **Provenance.** Session `/tmp/ab/j147_firelag`, frozen binary `d21f7ce`
|
|
|
|
|
> (sha256 `29571d4d…`), panel `tools/ab/panel_movement.txt` (15 opponents,
|
|
|
|
|
> FROZEN), arms file `tools/ab/arms_fire_lag.txt` registered above BEFORE any of
|
|
|
|
|
> these battles ran. **4 arms x 15 opponents x 3 runs x 3 rounds = 180 battles,
|
|
|
|
|
> 0 failed, 0 never started, 473 s.** The MDEs the analyzer actually reported at
|
|
|
|
|
> 3 runs/arm: **12.2-15.1 damage/run, 0.33-0.55 wins/run, 1.4-2.9 hit-rate
|
|
|
|
|
> points** — the pre-registered estimate (~16 / ~0.36 / ~1.9) was right.
|
|
|
|
|
|
|
|
|
|
**Pooled dashboard (descriptive, NOT the verdict):**
|
|
|
|
|
|
|
|
|
|
| arm | runs | dmg/run | dmg taken/run | wins/run | round wins | win rate | incoming hit rate | mean distance |
|
|
|
|
|
|---|---:|---:|---:|---:|---:|---:|---:|---:|
|
|
|
|
|
| `tfil_off` | 45 | 109.7 | 187.8 | 1.24 | 56/135 | 41.5% | 16.91% | 394 |
|
|
|
|
|
| `tfil_lag1` | 45 | 111.8 | 192.9 | 1.20 | 54/135 | 40.0% | 17.45% | 396 |
|
|
|
|
|
| `strafe_off` | 45 | 106.3 | 160.1 | 1.44 | 65/135 | 48.1% | 12.84% | 434 |
|
|
|
|
|
| `strafe_lag1` | 45 | 110.1 | 159.0 | **1.62** | **73/135** | **54.1%** | 13.21% | 428 |
|
|
|
|
|
|
|
|
|
|
**Verdict layer, each mover against ITS OWN reference (the only comparison that
|
|
|
|
|
isolates the knob):**
|
|
|
|
|
|
|
|
|
|
| arm | metric | mean Δ | 95% CI | sign test | p(sign) | p(sign-flip) | Wilcoxon p | MDE |
|
|
|
|
|
|---|---|---:|---|---:|---:|---:|---:|---:|
|
|
|
|
|
| `tfil_lag1` vs `tfil_off` | damage | +2.08 | [-7.22, +11.38] | 6/15 | 0.6072 | 0.6375 | 0.9773 | 12.15 |
|
|
|
|
|
| `tfil_lag1` vs `tfil_off` | wins | -0.04 | [-0.29, +0.21] | 4/9 | 1 | 0.8516 | 0.5923 | 0.33 |
|
|
|
|
|
| `tfil_lag1` vs `tfil_off` | hit_rate | +0.94 | [-0.93, +2.81] | 10/15 | 0.3018 | 0.2984 | 0.222 | 2.45 |
|
|
|
|
|
| `strafe_lag1` vs `strafe_off` | damage | +3.77 | [-6.98, +14.53] | 9/15 | 0.6072 | 0.4598 | 0.6701 | 14.04 |
|
|
|
|
|
| `strafe_lag1` vs `strafe_off` | wins | +0.18 | [-0.13, +0.49] | 5/9 | 1 | 0.3359 | 0.1723 | 0.41 |
|
|
|
|
|
| `strafe_lag1` vs `strafe_off` | hit_rate | +0.33 | [-0.73, +1.39] | 9/15 | 0.6072 | 0.5403 | 0.5509 | 1.38 |
|
|
|
|
|
|
|
|
|
|
### VERDICT — plain
|
|
|
|
|
|
|
|
|
|
1. **Was it only the drawing? NO. The decision was late, by exactly one bullet
|
|
|
|
|
step, and the fix is now in.** Measured live on 1777 matched ghost spawns
|
|
|
|
|
across both movers: the detection lag is **+1 tick on 100%** of them, the
|
|
|
|
|
ghost-vs-observer displacement is **19.1 px mean / 22.0 p90** (tfil) and
|
|
|
|
|
**16.1 / 21.8** (strafe), and the arrival deadline the mover reads is
|
|
|
|
|
**0.99 / 0.77 ticks late**. With `TR_FIRE_LAG=1` the displacement is
|
|
|
|
|
**5.4 / 9.0 px** and the deadline error **0.06 ticks** — the residue is the
|
|
|
|
|
ENEMY's own scan staleness (<= 8 px, its top speed), which is the floor this
|
|
|
|
|
design can reach because the ghost's origin is the enemy's *scanned* position.
|
|
|
|
|
The draw/advance order was checked and is correct, so the GUI was faithfully
|
|
|
|
|
drawing a wrong field.
|
|
|
|
|
2. **The live OUTCOME is null, and that is recorded as "not distinguishable".**
|
|
|
|
|
`tfil_lag1` is -0.04 wins/run and `strafe_lag1` is +0.18 wins/run — both far
|
|
|
|
|
under the MDEs the analyzer reported (0.33 and 0.41). Nothing reaches the
|
|
|
|
|
pre-registered bar, so under the campaign's rule **nothing is changed**:
|
|
|
|
|
`TR_FIRE_LAG` stays **default 0** and both movers ship exactly as before. The
|
|
|
|
|
knob is there, measured and documented, for anyone who wants the arm.
|
|
|
|
|
3. **The live MECHANISM did not move either** — incoming hit rate +0.94 pp (tfil)
|
|
|
|
|
and +0.33 pp (strafe), neither significant. This is the fourth consecutive
|
|
|
|
|
movement job where a real, measured mechanism change does not show up as fewer
|
|
|
|
|
hits taken. Two readings, both worth keeping: the dodge is limited by the
|
|
|
|
|
1-tick-stale enemy POSITION and by the 8-px scan staleness of the ghost's
|
|
|
|
|
origin, not by a 19-px translation of a field whose core is 18 px and whose
|
|
|
|
|
corridor is 40 px wide; and at 3 runs/arm a real few-percent effect in hit
|
|
|
|
|
rate sits under the ~1.4-point MDE. **What the fix does buy, provably, is
|
|
|
|
|
the arrival deadline**: every mover's heat, corridor and reap are now timed
|
|
|
|
|
off the bullet's real position, which is the input the next arrival-commit /
|
|
|
|
|
time-indexed-heat work needs to be correct at all.
|
|
|
|
|
4. **The one significant live result in this batch is the MOVER, not the knob**:
|
|
|
|
|
`strafe_lag1` vs `tfil_off` is +0.38 wins/run (sign 10/12, p = 0.0386) with
|
|
|
|
|
the incoming hit rate **-4.67 pp (sign 2/15, p = 0.0074, sign-flip
|
|
|
|
|
p = 0.0007, Wilcoxon p = 0.0024)** and mean distance +34 px (14/15). That is
|
|
|
|
|
the known strafe-over-tfil gap reproducing itself, and it is exactly why the
|
|
|
|
|
pre-registration demanded the within-mover reference: read against `tfil_off`
|
|
|
|
|
alone, the knob looks like a winner it is not.
|
|
|
|
|