re: the positive control ran, and is still inconclusive

poke_control.sh (self-retrying, succeeded on attempt 1 with no freeze) set the
player's hull at pos+0x154 to 1. Twelve seconds later the game had put
0x447A0000 back.

That establishes an asymmetry worth having: the hull word is continuously
rewritten by the game, while the unit-record fields held our value untouched for
60s. It separates fields the game maintains from fields nobody writes.

But it is not yet a control. The after-frame shows a red WARNING banner -- and
the before-frame already shows MISSILE ALERT, so the ship was under attack in
both and the banner is not attributable to the poke. A value being overwritten
proves the game writes that address, not that it read ours.

Correction: hull at pos+0x154 is 0x447A0000, a FLOAT 1000.0, not the 1500 the
pilot logs -- those are different fields or scales and should not be conflated.

The settling refinement: poke in a tight loop for several seconds so the value is
low whenever the game samples it. If hull is authoritative the ship dies and the
screen goes to GAME OVER; if it survives, the field is a readout.

The reusable part is the harness: boot -> verify animating -> locate -> act, with
a freeze at any step costing one retry rather than the iteration.
This commit is contained in:
Sylpheed RE agent
2026-08-25 17:36:00 +00:00
parent cee5cffebf
commit 77bc300692
2 changed files with 100 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# POSITIVE CONTROL for the poke method: does a write to /dev/shm reach the guest?
#
# Two poke experiments produced no observable effect, and without this control
# "the game ignored it" cannot be told from "the write never arrived"
# (script-runtime-probe.md). The stick test only proves the value persisted in
# the shared-memory FILE.
#
# The control has to be something the GAME visibly reacts to. Hull is ideal:
# it lives at `player position + 0x154`, and dropping it to 1 should destroy the
# player -- an unambiguous screen change, no OCR needed.
#
# Self-retrying, because roughly two runs in three freeze and a freeze was
# costing a whole iteration. Each attempt: boot, check the guest is animating,
# locate the player, poke, look. A freeze at any step costs a retry.
set -u
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
export PYTHONPATH=/sylph-home/.local/lib/python3.12/site-packages
SD="$(cd "$(dirname "$0")" && pwd)"
ATTEMPTS="${1:-3}"
alive_and_moving(){ python3 -c "
import sys; sys.path.insert(0,'$SD')
import frozen; d,_=frozen.frozen(5.0); sys.exit(1 if d else 0)"; }
for a in $(seq 1 "$ATTEMPTS"); do
echo "=== attempt $a/$ATTEMPTS ($(date +%T))"
pkill -9 -x xenia_canary 2>/dev/null; pkill -9 -f '[p]ilot.py' 2>/dev/null; sleep 2
rm -f /tmp/xenia-canary.lock
"$SD/launch_mission.sh" fly >/tmp/pc-boot.log 2>&1 || { echo " boot failed"; continue; }
if ! alive_and_moving; then echo " guest already frozen after boot"; continue; fi
pos=""
for t in 1 2 3; do
python3 "$SD/pad.py" set "rt=1" >/dev/null 2>&1; sleep 4
python3 "$SD/pad.py" clear >/dev/null 2>&1
pos=$(timeout 120 python3 "$SD/entities2.py" self 0x130 2>/dev/null \
| sed -n 's/.*pos va \(0x[0-9a-fA-F]*\).*/\1/p' | head -1)
[ -n "$pos" ] && break
echo " locate attempt $t: no player"
done
[ -n "$pos" ] || { echo " could not locate the player"; continue; }
if ! alive_and_moving; then echo " froze during locate"; continue; fi
hull=$((pos + 0x154))
echo " player pos $pos, hull $(printf '0x%X' $hull)"
before=$(python3 "$SD/gpoke.py" r32 "$hull" 1 2>/dev/null | tail -1)
echo " hull before: $before"
screenshot /tmp/pc-before.png >/dev/null 2>&1
python3 "$SD/gpoke.py" w32 "$hull" 1 2>&1 | tail -2
sleep 12
screenshot /tmp/pc-after.png >/dev/null 2>&1
echo " hull after : $(python3 "$SD/gpoke.py" r32 "$hull" 1 2>/dev/null | tail -1)"
echo " screen before: $(python3 "$SD/screen_id.py" /tmp/pc-before.png | head -1)"
echo " screen after : $(python3 "$SD/screen_id.py" /tmp/pc-after.png | head -1)"
python3 "$SD/frozen.py" --pair /tmp/pc-before.png /tmp/pc-after.png 2>&1 | tail -1
echo "CONTROL RAN"; exit 0
done
echo "CONTROL DID NOT RUN in $ATTEMPTS attempts"; exit 1