j146 TFIL: the bullet's own heat becomes tunable (TR_TFIL_BULLET_CORE/AURA, default 10/5 = today) and the field-shape A/B is pre-registered

This commit is contained in:
2026-09-26 22:16:06 +02:00
parent 5dd921c26b
commit 298ea6d586
5 changed files with 164 additions and 3 deletions
+93
View File
@@ -3218,3 +3218,96 @@ nothing.
**The shipped default is untouched.** `TR_MOVEMENT=strafe` remains the default
(`ModularBot_garage/src/ModularBot.nim:129`); both new knobs default to
off-effect, so `TR_MOVEMENT=tfil` still means today's tfil, byte-for-byte.
---
# Batch 7 — TFIL field shape (j146)
*Pre-registered BEFORE any battle of this batch was launched. No battle of this
batch existed when this section was written; the frozen binary for it is the
commit that adds the two bullet-heat knobs.*
## The cause this batch fixes
Two consecutive tfil fixes (j144 `d2005ab` arrival + no-rev, j145 `39c90fd`
turn-bias) improved the MECHANISM and the live outcome stayed an under-powered
null. j145's offline gate then found the UPSTREAM cause, on the same fixture:
1. **58.8% of tfil's picks have no safe set to tie-break in** — fewer than two
reachable tiles under `PathDangerThreshold = 10`.
2. `TR_TFIL_CORRIDOR_HEAT = 20` is **twice** that threshold, so ONE far bullet's
corridor marks a wide swath unsafe by itself; j145 measured `filter broken` on
**59%** of picks.
3. In tfil **the bullet's own heat is inert**: `BulletCore = 10.0` /
`BulletAura = 5.0` were Nim `const`s, and 10 is exactly the threshold, so a
bullet is never dangerous on its own and the corridor carries all the weight.
The SHAPE was already measured — but on **strafe**, in j119 batch 4, where the
engine and the field differ. `field_strong` (corridor 20, wall 30/10, i.e. exactly
what tfil ships) was **-0.29 wins/run, p=0.039**; `field_off` was **-0.47
wins/run, p=0.0063**; the reference strafe shape — bullet core 20 / aura 10,
corridor 10, wall 15 / radiance 5 — was the champion. **Both extremes lose and
the middle wins, and tfil has never been run on the middle shape.**
## The treatment (Task A)
`BulletCore` / `BulletAura` in `the_floor_is_lava.nim` go from `const` to
env-overridable `var`s, the exact pattern j119/j134 already used for
`CorridorHeat` / `WallHotness` / `WallRadiance`:
| knob | default | meaning |
|---|---|---|
| `TR_TFIL_BULLET_CORE` | `10.0` (= today's `const`) | lava per bullet-overlapping tile |
| `TR_TFIL_BULLET_AURA` | `5.0` (= today's `const`) | lava for the bullet's aura ring |
**Default-off-effect**: the defaults are today's `const`s, so the default path is
byte-for-byte unchanged and the golden in `test_tfil_commit_env.nim` is not
regenerated.
## Arms (frozen, all `TR_MOVEMENT=tfil`, j144 ON in every arm)
j144's recommended `.env` (`TR_TFIL_COMMIT_ARRIVAL=1 TR_TFIL_NOREV_SPEED=4`) is
ON in **every** arm, so the shape is isolated **on top of the current best tfil**.
The virtual pillar is OFF (shipped 0/0) in every arm. Columns are
corridor / wall hotness / wall radiance / bullet core / bullet aura.
| # | arm | shape | what it isolates |
|---|---|---|---|
| 1 | `shape_shipped` | 20/30/10/10/5 | **the reference** — today's field, on j144 |
| 2 | `shape_middle` | 10/15/5/20/10 | the shape strafe won on |
| 3 | `shape_corr10` | 10/30/10/10/5 | "corridor alone was the problem" |
| 4 | `shape_bullets` | 20/30/10/20/10 | "bullets made dangerous themselves" |
| 5 | `shape_nofield` | 0/0/0/20/10 | the "field off" control strafe measured as WORSE |
`shape_nofield` is here so a `shape_middle` win cannot be a FALSE WINNER: it
separates "the middle shape is right" from "any less lava is right". Note that
`TR_TFIL_WALL_HOTNESS=0` is what zeroes the wall (radiance 0 would paint a FLAT
field over the whole arena — the opposite of "no walls"). The enemy body/aura
heat (`EnemyCore 40` / `EnemyAura 10`) is a `const` with no knob and is present in
every arm; "field off" therefore means no **corridor/wall** field.
Panel: the FROZEN 15-opponent `tools/ab/panel_movement.txt`. Harness:
`tools/ab/tournament_run.sh` + `tournament_analyze.py`. Arms file
`tools/ab/arms_tfil_shape.txt`.
## Pre-registered prediction and decision rule
* **Prediction.** `shape_middle` > `shape_shipped` on damage/run and round wins
(it is the shape strafe measured as best, and it is the only arm that both
halves the corridor AND makes the bullet itself dangerous, which is what
should restore a real safe set). `shape_corr10` and `shape_bullets` should
each move part of the way. `shape_nofield` should be the WEAKEST arm, matching
strafe's `field_off` — if `shape_nofield` ties `shape_middle` on the primary
metrics, the win is "less lava", not "this shape", and that is recorded as a
wrong prediction.
* **Mechanism, not verdict.** The **offline `filter broken` rate and the mean
safe-candidate count** are the mechanism. The **incoming hit rate** is the
live mechanism. The **verdict is damage/run and round wins** under the
campaign's pre-registered rule 2: the cross-opponent sign test p < 0.05 on one
primary metric with the other not down, with SD/SE/95% CI/MDE reported.
* **If nothing separates**, the verdict is *not distinguishable* and the shape is
**not changed**. The pre-registered bar is not re-interpreted afterwards.
* **A null does NOT retract j144's mechanism result** and does not change the
shipped `TR_MOVEMENT=strafe` default.
*(results appended below after the battles)*