re: the Phase_1/2/3 block of the settings family -- mostly per stage, not per phase

72 records, 94 distinct field names, 31 in every one (post-processing core, five
Fog*, three ScreenColor*, SpaceSize, five Supply*, UnderCommandSquadron, the
first BGOperate slot).  Optional families sit in clean tiers: Nebura_* and
ColorLayer* in 69/72, DOF_*/UnsharpMask_*/ExposureKey_* in 15/72, FinalPass* in
3/72.

REFUTED: BGOperateFrameCount is NOT the number of BGOperateFrameName_i slots --
36 of 72.  What holds is Count <= slots, 72/72: a fixed slot array with a live
count, the same shape as MessageCount under the 32-slot clamp.

68 of the fields common to all three phases NEVER differ in any of the 24
objects.  The phase block is a per-stage environment block copied three times;
what a phase change is actually for is the backdrop animation (BGOperate*) and
the supply/command squadron assignment.

MapPath is not in this family -- its 87 records per pack are 29 x 3, the
resource manifest's Phase_N.

Also fixed a non-determinism the verify loop caught: most_common() over a set
iteration ordered ties differently per run; now sorted by (-count, name).

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 18:50:27 +00:00
parent 26b7728ceb
commit 5f764458cd
5 changed files with 177 additions and 7 deletions

View File

@@ -7,7 +7,7 @@ language pack, each holding Score_Easy / Score_Normal / Score_Hard with one
Run: python3 mission_scoring.py > ../../docs/re/data/mission-scoring.txt
"""
import sys, os, glob, collections
import sys, os, re, glob, collections
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from unit_substructures import pak_entries
import unitgroup as U
@@ -120,6 +120,54 @@ def main():
print(' %-36s %2d distinct %s' % (
k, len(c), ' '.join('%s=%d' % (a, b) for a, b in c.most_common(5))[:70]))
# the Phase_1/2/3 block of the settings family
prec = [(h, i, U.named(d['Phase_%d' % i])) for h, d in full for i in (1, 2, 3)
if 'Phase_%d' % i in d]
allf = collections.Counter()
for _, _, n in prec:
for f in n:
allf[f] += 1
core = sorted(f for f, c in allf.items() if c == len(prec))
print()
print('the Phase_1/2/3 block (%d records over %d objects):' % (len(prec), len(full)))
print(' distinct field names : %d' % len(allf))
print(' present in EVERY record : %d' % len(core))
print(' %s' % ' '.join(core))
print(' field-count histogram : %s' % dict(sorted(
collections.Counter(len(n) for _, _, n in prec).items())))
le = 0
slots = collections.Counter()
cnts = collections.Counter()
for _, _, n in prec:
c = int(n['BGOperateFrameCount'])
k = sum(1 for f in n if re.fullmatch(r'BGOperateFrameName_\d+', f))
slots[k] += 1
cnts[c] += 1
le += (c <= k)
eq = sum(1 for _, _, n in prec
if int(n['BGOperateFrameCount'])
== sum(1 for f in n if re.fullmatch(r'BGOperateFrameName_\d+', f)))
print(' BGOperateFrameCount == slots: %d/%d (REFUTED)' % (eq, len(prec)))
print(' BGOperateFrameCount <= slots: %d/%d' % (le, len(prec)))
print(' slot histogram %s ; Count histogram %s' % (
dict(sorted(slots.items())), dict(sorted(cnts.items()))))
moved = collections.Counter()
same = collections.Counter()
for h, d in full:
ns = [U.named(d['Phase_%d' % i]) for i in (1, 2, 3) if 'Phase_%d' % i in d]
if len(ns) != 3:
continue
for f in set(ns[0]) & set(ns[1]) & set(ns[2]):
(moved if len({n[f] for n in ns}) > 1 else same)[f] += 1
never = sorted(f for f in same if f not in moved)
print(' fields that DIFFER between phases (of %d objects):' % len(full))
for f, c in sorted(moved.items(), key=lambda kv: (-kv[1], kv[0])):
print(' %-28s %2d' % (f, c))
print(' fields that NEVER differ between phases: %d' % len(never))
print(' %s' % ' '.join(never))
print()
print('the commonest Normal record:')
for k, v in sorted(dict(base).items()):