- determinism oracle regenerated and byte-identical (bb4fd9ac / 978041ac) - the four phase-23/33 draw-bearing tail callees run EVERY turn; the three inner functions holding the draws run zero times -- the gate is inside each outer body - CreateRaidEncounter is called (2 on one turn) and draws nothing: candidate list empty - Zuul: 7 calls / 7 words per trade-raid Chance site, 14 not 16, as predicted - EncounterDetect_Run receives an EMPTY record vector, so ProcessTeamRecord and AssignContacts never run; the 2-word detection residual is in 0x007d5150's subtree - a MinHook detour on 0x00893290 changes the game's output; bisected over six runs. The un-instrumented game and lane Z's instrument agree, so lane Z's numbers stand - lane AI1 insert: P2 held across two fresh processes, Rung B stays as written
93 lines
3.8 KiB
Python
93 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Lane H: the entry-counter table and the encounter-detection records from a probe trace.
|
|
|
|
Two things the word-count reports cannot say, printed side by side with the words so they are read
|
|
together:
|
|
|
|
* `probe_entries` -- how many times control ENTERED each of the tail callees lane V2 proved can
|
|
reach the strategic generator, and the two trade-raid functions. A row with `calls > 0` and no
|
|
matching draw-site row is "reached and gated"; a row with `calls == 0` is "not reached". Eight
|
|
turns of `tail words = 0` could not distinguish those, and they have opposite consequences.
|
|
`installed=false` is printed as **NOT INSTALLED**, never as a zero (method rule 1).
|
|
|
|
* `ProcessTeamRecord` -- the gate predicate, contact count and detector count recomputed from the
|
|
record at hook entry, beside the words the call actually cost. When the gate is false, the
|
|
counts are a prediction of a call that will not happen; when it is true, `AssignContacts` fires
|
|
and prints the callee's own numbers, and the two can be compared.
|
|
|
|
uv run python3 tools/probe_report.py <trace.jsonl>
|
|
"""
|
|
import json
|
|
import sys
|
|
|
|
|
|
def val(tv):
|
|
return None if tv is None else tv.get("v")
|
|
|
|
|
|
def sv(struct_tv, key):
|
|
if struct_tv is None or struct_tv.get("t") != "struct":
|
|
return None
|
|
return val(struct_tv["v"].get(key))
|
|
|
|
|
|
def words_of(rec):
|
|
rng = rec.get("side", {}).get("rng", {})
|
|
wb, wa = sv(rng.get("before"), "words"), sv(rng.get("after"), "words")
|
|
return (wa - wb) if (wa is not None and wb is not None) else None
|
|
|
|
|
|
turn_no = 0
|
|
for line in open(sys.argv[1]):
|
|
d = json.loads(line)
|
|
if "hook" not in d:
|
|
continue
|
|
hook = d["hook"]
|
|
args = {a.get("n"): a for a in d.get("args", []) if a.get("n")}
|
|
|
|
if hook.endswith("ProcessTeamRecord") or hook.endswith("AssignContacts"):
|
|
w = words_of(d)
|
|
short = hook.split("::")[-1]
|
|
if short == "ProcessTeamRecord":
|
|
flags = [
|
|
(sv(e, "fb"), sv(e, "fc"), sv(e, "fc_dword"))
|
|
for e in (val(args.get("entry_flags")) or [])
|
|
]
|
|
print(
|
|
f" [{short}] call {d['call_id']} depth {d.get('depth')}: "
|
|
f"entries={val(args.get('entries'))} gate={val(args.get('gate'))} "
|
|
f"contacts={val(args.get('pred_contacts'))} "
|
|
f"detectors={val(args.get('pred_detectors'))} "
|
|
f"neither={val(args.get('pred_neither'))} "
|
|
f"max_trials={val(args.get('pred_max_trials'))} "
|
|
f"fc_byte_vs_dword_disagreements={val(args.get('fc_byte_vs_dword_disagreements'))} "
|
|
f"WORDS={w}"
|
|
)
|
|
if flags:
|
|
print(" entry flags (fb, fc, fc_dword): " + ", ".join(
|
|
f"({a},{b},0x{c:x})" for a, b, c in flags))
|
|
else:
|
|
print(
|
|
f" [{short}] call {d['call_id']} depth {d.get('depth')}: "
|
|
f"detectors={val(args.get('detectors'))} contacts={val(args.get('contacts'))} "
|
|
f"max_trials={val(args.get('max_trials'))} WORDS={w}"
|
|
)
|
|
continue
|
|
|
|
if not hook.endswith("Autosave"):
|
|
continue
|
|
if val(args.get("end_turn")) is not False:
|
|
continue
|
|
turn_no += 1
|
|
probes = val(args.get("probe_entries"))
|
|
print(f"\n=== post-turn autosave #{turn_no} (call {d['call_id']}) ===")
|
|
if probes is None:
|
|
print(" probe_entries: ABSENT -- this trace is from a build without lane H's counters")
|
|
continue
|
|
for p in probes:
|
|
name = sv(p, "name")
|
|
calls = sv(p, "calls")
|
|
total = sv(p, "calls_since_launch")
|
|
inst = sv(p, "installed")
|
|
state = f"calls={calls:<4} since_launch={total}" if inst else "**NOT INSTALLED**"
|
|
print(f" 0x{sv(p, 'rva') + 0x400000:08x} {name:<52} {state}")
|