Third Stage 02 run, pilot with SYLPH_PREFER=e010 (312 fire=1 samples), per-class live counts logged every 11s beside the HUD (new tools/re-capture/class_count.py). CONTROL CONFIRMED: the live turret population fell 108 -> 101 -- seven e007 deaths -- and REMAINING OB never decremented, only rose. Previously this was inferred from a run whose kill log happened to be turrets; it is now measured with the classes counted directly. ARRIVAL TIMING n=3: 004 -> 008 in (108.7s, 125.5s] and 008 -> 012 in (204.2s, 221.7s], both brackets containing the predicted 120 and 210. The live e010 count sat at exactly 16 in 20 of 26 samples -- precisely phase 1's e010 roster (ADT102/ADT107/ADT113/ADS151, each n=4) -- an independent runtime corroboration of the static roster. DECREMENT STILL UNPROVEN: the e010 floor never fell, so no marked attacker died and the counter had no chance to move. Three runs have failed to kill one. The blocker is combat effectiveness, not instrumentation. Artifact recorded: six of 26 class samples read 17-28. Spikes are always upward and transient -- the tool dedups on a position triple read just after the pattern scan, so an entity written between the two reads is counted twice.
33 lines
1.1 KiB
Python
33 lines
1.1 KiB
Python
"""Fast per-class live count: search ONE definition pointer, dedup by position."""
|
|
import sys, os, struct, time
|
|
sys.path.insert(0, '/tmp/rc')
|
|
import gmem, gworld, entities2 as E
|
|
|
|
w = gworld.World()
|
|
defs = E.definitions(w)
|
|
want = {nm: pat for pat, nm in defs.items()
|
|
if nm in ('UN_e010_ADAN_Attacker_S', 'UN_e007_ADAN_Turret')}
|
|
lo, hi = gmem.va_to_off(E.ENT_VA_LO), gmem.va_to_off(E.ENT_VA_HI)
|
|
|
|
def count(pat):
|
|
seen = set()
|
|
for a, b in gmem.extents(w.fd, w.size):
|
|
a, b = max(a, lo), min(b, hi)
|
|
if b <= a: continue
|
|
blob = os.pread(w.fd, b - a, a); i = 0
|
|
while True:
|
|
j = blob.find(pat, i)
|
|
if j < 0: break
|
|
off = a + j
|
|
if off % 4 == 0:
|
|
p = off - 0x130
|
|
d = os.pread(w.fd, 12, p)
|
|
if len(d) == 12: seen.add(struct.unpack('>fff', d))
|
|
i = j + 4
|
|
return len(seen)
|
|
|
|
for n in range(int(sys.argv[1])):
|
|
row = ' '.join('%s=%d' % (k.split('_')[1], count(v)) for k, v in sorted(want.items()))
|
|
print('%2d %s' % (n, row), flush=True)
|
|
time.sleep(float(sys.argv[2]))
|