re: all 277 base-solver rows classified objectively; 53 are data-table schemas

name_block_bases.py extended with a per-row data-table test; artefact +57/-0,
byte-identical across two runs (now ~2 min 12 s -- it adds a disc-wide pak scan).

The test is objective, not by eye: a row is a data-table schema if its names are
IDXD record/field names on the disc (13450 such names disc-wide).  53 of 277 rows
are >=50 % disc names with >=8 names; the other 224 are engine/XDK vocabulary,
compiled key lists, or noise.

The two axes are independent: against base confidence, solved bases split 34
table / 136 not, round bases 16 / 91.  "Round base" and "not a table" are
different questions.

The 53 contain every loader already known -- that is the control.  Five rows in
the 53 are unowned, each noun grepped and appearing in no docs/re/ file:
sub_823BDAA8 r11 (33) = the S16 boss's muzzle/attach frames (GN_MainGun_*_Muz*);
sub_823BDAA8 r10 (25) = motion names (Motion_stand, Motion_attackA_start), the
EnumMotions family DefTables declares; sub_82315AE8 r11 (20) = the Guardian
record's own fields, i.e. the S16 boss loader; sub_8219E560 r11 (18) = the
leaderboard screen keys; sub_825F2CF0 + sub_825F2F88 r0 (30 each, same base) =
post-processing (FinalPassBG, FogMin/MaxDistance).

Four rows that look new are not, and their disc-overlap says so -- 53-70 % rather
than ~100 %, because they mix arsenal fields the corpus owns (ConditionToDevelop,
WeaponDesc, SilhouetteModel) with literal screen coordinates as strings.

Not settled: none of the five was opened -- this iteration produced the shortlist,
not the findings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Claude (auto)
2026-08-27 23:09:57 +00:00
parent dd6b13c751
commit ced73c5488
4 changed files with 177 additions and 1 deletions

View File

@@ -13,7 +13,7 @@ start. Control: it must recover `r30 = 0x82088F94` for the unit loader
Regenerates docs/re/data/name-block-bases.txt.
"""
import sys, collections, bisect
import sys, os, glob, collections, bisect
DB = '/work/xenia-rs/sylpheed.db'
MIN_GROUP = 8 # displacements needed before a group is worth solving
@@ -99,6 +99,47 @@ def main():
print(" ⚠ the 0x820B0000 cluster is ~60 near-identical functions in"
" 0x8281xxxx-0x8284xxxx that all name the same `rou_e0NN` list.")
# Is a row a DATA-TABLE schema or engine/XDK vocabulary? The objective test
# is whether its names are IDXD record/field names on the disc.
sys.path.insert(0, HERE) if False else None
from unit_substructures import pak_entries
import unitgroup as _U
disc = set()
for pk in sorted(glob.glob('/work/sylph_extract/**/*.pak', recursive=True)):
for _h, b in pak_entries(pk):
if b[:4] != b'IDXD':
continue
try:
rs = _U.parse(b)
except Exception:
continue
for r in rs:
disc.add(r['squadron'])
for _t, n, _v in r['fields']:
if n:
disc.add(n)
print("\n## Is the row a DATA-TABLE schema? (names that are IDXD record/field"
" names on the disc)")
print(" distinct IDXD record+field names disc-wide: %d" % len(disc))
scored = []
for name, reg, B, tot, n in rows:
nm, seen = [], set()
for a, d in order[name][reg]:
t = B + d
if t in txt and t not in seen:
seen.add(t)
nm.append(txt[t])
if not nm:
continue
hit = sum(1 for x in nm if x in disc)
scored.append((hit / len(nm), hit, len(nm), name, reg, B))
tab = [r for r in scored if r[0] >= 0.5 and r[2] >= 8]
print(" rows that are >=50%% disc names and >=8 names: %d / %d"
% (len(tab), len(scored)))
for r in sorted(tab, key=lambda r: (-r[2], r[3])):
print(" %-14s %-4s 0x%08X %4d names %3.0f%% disc"
% (r[3], r[4], r[5], r[2], 100 * r[0]))
print("\n## The schema each one names, in code order")
for name, reg, B, tot, n in rows:
seen, names = set(), []