Files
Sylpheed/tools/re-capture/wave4_probe.py
Sylpheed RE agent 08352d09ac re: add a hunting pilot; withdraw the "10 of 116 records are dynamic" result
The user asked for an actively hunting pilot, since a player who kills nothing
cannot trigger an event-gated wave and both previous runs used the survival
pilot.

pilot.py gains SYLPH_HUNT=1. The substantive change is which contacts ENGAGE may
shoot: it previously skipped every "hard" target -- "turrets and hulls are not
the objective" -- and stood off 2500 units from turrets, on the assumption that
an e007 Turret is an AA mount on a capital ship. It is a craft, one of the main
enemy types of the first six missions, and at 100 HP the cheapest kill on the
field. Under SYLPH_HUNT it is a target and the keep-out drops to 600. The run
confirms the pilot engages: steady ENGAGE, fire=1, committed to an
e010_ADAN_Attacker_S at ~2.2 km, hull and escorted asset untouched over 160 s.

Withdrawn: "only 10 of 116 records ever changed a byte in 170 s". This run
measured 41-56 records changing in every 10 s tick. The old figure does not
reproduce.

I cannot say why, because I changed two variables at once -- the record bound
(fixed 0x200 to bounded-by-next-record) and the pilot (survival to hunting).
Either explains it. That is a design error, and the honest outcome is a
retraction without a replacement explanation rather than a story that fits.
The conclusion it had supported is unaffected: the roster identity now rests on
the exact 10-of-10 unit-composition match measured independently.

Still open, and explicitly not concluded: the pilot's own entity scan shows ADAN
drifting 147 -> 129 -> 142, and the late rise has the shape of an arrival, but
the sample-to-sample swing is +/-10, the same size as the effect. AGENT.md warns
that polling faster than the guest updates manufactures a curve out of noise, so
no wave conclusion is drawn. The run probably did not kill anything either
(fc=0, asset at 100%), so it does not test the event-gated model. A stable
per-record liveness field and a working kill counter are both needed first;
REMAINING OB at 0xbdb59668 still does not read as a counter.
2026-08-24 12:45:43 +00:00

55 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Hunting run: does killing things make more records go active?
Uses the labelling and the MEASURED stride from wave3_probe.py -- each record is
bounded by the next record's address, not by a constant. Reports, per tick, how
many records changed and which unit types they are, so a rise in activity can be
tied to the hunt rather than to the clock.
"""
import os, sys, time, struct, collections, importlib.util
SD = __file__.rsplit('/', 1)[0]
spec = importlib.util.spec_from_file_location('gmem', SD + '/gmem.py')
gmem = importlib.util.module_from_spec(spec); spec.loader.exec_module(gmem)
w3 = importlib.util.spec_from_file_location('w3', SD + '/wave3_probe.py')
wave3 = importlib.util.module_from_spec(w3); w3.loader.exec_module(wave3)
MAXREC = 0x400
def main():
secs = int(sys.argv[1]) if len(sys.argv) > 1 else 200
every = int(sys.argv[2]) if len(sys.argv) > 2 else 10
path = gmem.mem_path()
fd = os.open(path, os.O_RDONLY); size = os.fstat(fd).st_size
f = os.fdopen(os.dup(fd), 'rb')
offs = wave3.find_records(f, fd, size)
if not offs: print('NO ENTITY RECORDS'); return 2
lens = [min(MAXREC, offs[i+1] - offs[i]) for i in range(len(offs)-1)] + [0x100]
ids = [wave3.resolve_id(f, size, o)[0] or '?' for o in offs]
print('records: %d, labelled %d' % (len(offs), sum(1 for i in ids if i != '?')))
print('composition:', collections.Counter(ids).most_common(6))
prev = [wave3.rd(f, o, l) for o, l in zip(offs, lens)]
log = open('/tmp/wave4-activity.tsv', 'w'); log.write('t\tactive\tunits\n')
t0 = time.time(); series = []
while time.time() - t0 < secs:
time.sleep(every)
el = round(time.time() - t0)
act = []
for k, (o, l) in enumerate(zip(offs, lens)):
cur = wave3.rd(f, o, l)
if cur != prev[k]: act.append(k)
prev[k] = cur
types = collections.Counter(ids[k] for k in act)
series.append((el, len(act)))
line = '%d\t%d\t%s\n' % (el, len(act), dict(types))
log.write(line); log.flush()
print(' t=%4ds active=%3d %s' % (el, len(act),
[(u.replace('UN_',''), c) for u, c in types.most_common(5)]), flush=True)
log.close()
print('\nactive-record series:', series)
a = [n for _, n in series]
if a: print('active: min=%d max=%d first=%d last=%d' % (min(a), max(a), a[0], a[-1]))
return 0
if __name__ == '__main__':
sys.exit(main())