j150 (diag only): picker loss histogram + sweepable heat cutoff
Measures WHERE the lava picker loses tiles, per pick: reachable hull -> CoolestLevels=2 distinct-value filter -> path heat filter -> draw set -> chosen. TR_TFIL_DIAG (default off) fills TfilLoss*; TR_TFIL_DANGER_THRESHOLD (default 10.0, the shipped const) makes the cutoff sweepable offline. No decision logic changed: the guard test proves the diag-on move stream is byte-for-byte the diag-off one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -955,6 +955,126 @@ when declared(loadTfilCommitEnv):
|
||||
check "j147: clearing the knob restores the shipped spawn exactly",
|
||||
FireLag == 0 and spawnGhost().x == ei.x
|
||||
|
||||
# ── j150: the picker loss-histogram diag + the sweepable heat cutoff ──────────
|
||||
#
|
||||
# TR_TFIL_DIAG 0/1 default 0 — fill TfilLoss* only
|
||||
# TR_TFIL_DANGER_THRESHOLD (float) default 10 — was a proc-local `const`
|
||||
#
|
||||
# Both must be default-off-effect: the whole point of the diag is to measure
|
||||
# the shipped picker, not to change it.
|
||||
proc testJ150() =
|
||||
delEnv("TR_TFIL_DIAG"); delEnv("TR_TFIL_DANGER_THRESHOLD")
|
||||
loadTfilCommitEnv()
|
||||
check "j150: TR_TFIL_DIAG defaults OFF and TR_TFIL_DANGER_THRESHOLD defaults " &
|
||||
"to today's 10.0", (not TfilDiag) and TfilDangerThreshold == 10.0
|
||||
|
||||
# 1. the diag is PURE: identical move stream with it on and off
|
||||
let off = replay(loadStates(), loadRoundStarts())
|
||||
putEnv("TR_TFIL_DIAG", "1")
|
||||
loadTfilCommitEnv()
|
||||
let on = replay(loadStates(), loadRoundStarts())
|
||||
var diff = -1
|
||||
if off.len != on.len: diff = min(off.len, on.len)
|
||||
else:
|
||||
for i in 0..<off.len:
|
||||
if recLine(off[i]) != recLine(on[i]): diff = i; break
|
||||
check "j150: with TR_TFIL_DIAG=1 the move stream is BYTE-FOR-BYTE the " &
|
||||
"diag-off one over " & $off.len & " ticks — the counters are inert",
|
||||
diff < 0
|
||||
|
||||
# 2. the histogram is populated and its stage chain is monotone
|
||||
let st = TfilLoss # kept: step 4 clears the live counter
|
||||
check "j150: the histogram counted picks (" & $st.picks & ") and every " &
|
||||
"stage is non-increasing (reach >= cool-filter >= heat-filter)",
|
||||
st.picks > 0 and st.sReach >= st.sCool and
|
||||
st.sCool >= st.sSafe and st.sSafe <= st.sCand and
|
||||
st.safeHist[0] <= st.picks
|
||||
|
||||
# 3. knob parsing, including the fallbacks
|
||||
putEnv("TR_TFIL_DANGER_THRESHOLD", "18")
|
||||
loadTfilCommitEnv()
|
||||
check "j150: TR_TFIL_DANGER_THRESHOLD=18 is read", TfilDangerThreshold == 18.0
|
||||
putEnv("TR_TFIL_DANGER_THRESHOLD", "junk")
|
||||
loadTfilCommitEnv()
|
||||
check "j150: a malformed value falls back to the DEFAULT 10.0",
|
||||
TfilDangerThreshold == 10.0
|
||||
putEnv("TR_TFIL_DANGER_THRESHOLD", "-4")
|
||||
loadTfilCommitEnv()
|
||||
check "j150: a negative value clamps to 0 (heat can never go backwards)",
|
||||
TfilDangerThreshold == 0.0
|
||||
|
||||
# 4. restore the shipped default for every later check in this process
|
||||
putEnv("TR_TFIL_DIAG", ""); putEnv("TR_TFIL_DANGER_THRESHOLD", "")
|
||||
loadTfilCommitEnv()
|
||||
check "j150: clearing the knobs restores 10.0 / diag off",
|
||||
(not TfilDiag) and TfilDangerThreshold == 10.0 and TfilLoss.picks == 0
|
||||
|
||||
echo "\n j150 picker loss histogram (default build, offline fixture replay):"
|
||||
echo " picks=", st.picks
|
||||
let np = st.picks.float
|
||||
echo " mean reachable hull tiles=", st.sReach.float / np
|
||||
echo " mean after CoolestLevels=2 filter=", st.sCool.float / np
|
||||
echo " mean after the heat filter (pre-promotion)=", st.sSafe.float / np
|
||||
echo " mean draw set=", st.sCand.float / np
|
||||
|
||||
# ── j151: the ARRIVAL bound (TR_TFIL_ARRIVE_TICKS, default 0 = off) ─────────
|
||||
type ArrStats = object
|
||||
picks, beyond, starved: int ## starved = picks made with an empty pool
|
||||
meanTta, meanPool: float
|
||||
|
||||
proc replayJ151(bound: float): ArrStats =
|
||||
putEnv("TR_TFIL_ARRIVE_TICKS", $bound)
|
||||
loadTfilCommitEnv()
|
||||
let states = loadStates()
|
||||
let starts = loadRoundStarts()
|
||||
randomize(Seed)
|
||||
var m = initTFIL()
|
||||
var lastPicks = 0
|
||||
for i in 0..<states.len:
|
||||
if i == 0 or i in starts: m.resetRound()
|
||||
discard m.computeMove(states[i])
|
||||
if m.picks != lastPicks:
|
||||
lastPicks = m.picks
|
||||
let tta = sqrt((m.commitTarget.x - states[i].selfX)^2 +
|
||||
(m.commitTarget.y - states[i].selfY)^2) / MaxSpeed
|
||||
inc result.picks
|
||||
if tta > TfilArriveTicks + 0.001: inc result.beyond
|
||||
if m.lastPickSafe == 0: inc result.starved
|
||||
result.meanTta += tta
|
||||
result.meanPool += m.lastPickSafe.float
|
||||
if result.picks > 0:
|
||||
result.meanTta /= result.picks.float
|
||||
result.meanPool /= result.picks.float
|
||||
|
||||
proc testJ151() =
|
||||
# 8a. the shipped default is OFF — the golden parity check above is the proof
|
||||
delEnv("TR_TFIL_ARRIVE_TICKS")
|
||||
loadTfilCommitEnv()
|
||||
check "j151: the arrival bound defaults to OFF (today's uniform draw over " &
|
||||
"the whole 50-tick hull)", TfilArriveTicks == 0.0
|
||||
|
||||
let off = replayJ151(0.0) # today's behaviour, same seed
|
||||
let on15 = replayJ151(15.0) # = CommitTicks: the horizon we hold a target for
|
||||
delEnv("TR_TFIL_ARRIVE_TICKS")
|
||||
loadTfilCommitEnv()
|
||||
|
||||
check "j151: with the bound on (" & $on15.picks & " picks) NO target is " &
|
||||
"farther than the horizon (" & $on15.beyond & " violations), while " &
|
||||
"off the same fixture has " & $off.beyond & "/" & $off.picks,
|
||||
on15.beyond == 0 and off.beyond > 0
|
||||
check "j151: the mean time-to-arrive falls (" &
|
||||
off.meanTta.formatFloat(ffDecimal, 1) & " -> " &
|
||||
on15.meanTta.formatFloat(ffDecimal, 1) & " ticks) and the pool is " &
|
||||
"not starved (mean safe tiles " &
|
||||
on15.meanPool.formatFloat(ffDecimal, 1) & ", " & $on15.starved &
|
||||
" empty pools)",
|
||||
on15.meanTta < off.meanTta and on15.meanPool >= 1.0 and on15.starved == 0
|
||||
check "j151: the bound is a filter, not a replacement — the pick COUNT is " &
|
||||
"barely reduced (" & $off.picks & " -> " & $on15.picks & ")",
|
||||
on15.picks.float > off.picks.float * 0.9
|
||||
check "j151: clearing the knob restores today's pick stream exactly",
|
||||
replayJ151(0.0).picks == off.picks
|
||||
|
||||
# ── driver ───────────────────────────────────────────────────────────────────
|
||||
|
||||
testDefaultParity()
|
||||
@@ -965,6 +1085,8 @@ when declared(loadTfilCommitEnv):
|
||||
testJ145()
|
||||
testJ146()
|
||||
testJ147()
|
||||
testJ151()
|
||||
testJ150()
|
||||
|
||||
if failures > 0:
|
||||
echo "\n", failures, " check(s) FAILED"
|
||||
|
||||
Reference in New Issue
Block a user