tools: wait_flight was testing a pixel that is 40 rows outside the HUD
It tested one named pixel, (450,640), described as "inside the SHIELD bar". It is not inside anything. `screenshot` crops to the GAME SURFACE, 1279x675, while those constants were chosen for a 1280x720 window: measured on a frame that was unmistakably in flight (TIME 01:18.05, REMAINING OB 004), the SHIELD bar's green rows are 590-605 and the ARMOR bar's are 650-670, and (450,640) sits in the gap between them reading (64,66,116) - blue. That is why the corpus already carried "wait_flight.sh reported NEVER REACHED FLIGHT while the game was plainly in flight" as an unexplained note, and it is exactly the failure screen_id.py's own header warns about. Reproduced live here: the script sat for five minutes reporting nothing while tapping A into the cockpit every six seconds. Now classified by whole-image statistics - screen_id.py's "flight" class, green fraction 1.3-1.5% against <0.1% on every menu - which no crop or scale can move. Two consecutive frames are required so an explosion in a cutscene cannot pass, and the A tapping (which dismisses the objective card) STOPS once flight is seen, because in the cockpit A is a weapon press and not a "continue". Tested against the running game before being believed: 0 with "IN FLIGHT at 19s" on the same session the old test had been failing on, and then in the unattended launch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
@@ -5,23 +5,34 @@
|
||||
# stage load and the objective card. Under lavapipe that is not a constant: one
|
||||
# run needed 75 s, the next was still in Raymond's dialogue at 140 s, so the A
|
||||
# meant for the OBJECTIVE card was swallowed by the cutscene and the card sat
|
||||
# there forever.
|
||||
# there forever. So poll, and tap A every few seconds until the HUD appears
|
||||
# (which dismisses the objective card whenever it happens to be up).
|
||||
#
|
||||
# The in-flight HUD is unmistakable: the SHIELD bar is a solid bright green
|
||||
# block at the bottom of the screen, and no cutscene or menu has anything green
|
||||
# there. So poll that pixel, and tap A every few seconds until it appears (which
|
||||
# dismisses the objective card whenever it happens to be up).
|
||||
# 🔴 REWRITTEN 2026-08-23. This script used to test ONE NAMED PIXEL, (450,640),
|
||||
# "inside the SHIELD bar". It is not inside anything: `screenshot` crops to the
|
||||
# GAME SURFACE, which is **1279x675**, while those constants were picked for a
|
||||
# 1280x720 window — (450,640) lands in the gap between the SHIELD bar (green rows
|
||||
# 590-605) and the ARMOR bar (650-670) and reads (64,66,116), blue. Measured on a
|
||||
# frame that was unmistakably in flight, `TIME 01:18.05`, while this script sat
|
||||
# there reporting nothing and tapping A into the cockpit every six seconds. That
|
||||
# is exactly the failure `screen_id.py`'s own header warns about, and it is why
|
||||
# the corpus already carried "wait_flight.sh reported NEVER REACHED FLIGHT while
|
||||
# the game was plainly in flight" as an unexplained note.
|
||||
#
|
||||
# So classify by WHOLE-IMAGE statistics instead, which no crop or scale can move:
|
||||
# the flight HUD paints green over the entire frame (green fraction 1.3-1.5 %,
|
||||
# against <0.1 % on every menu), and that is `screen_id.py`'s `flight` class.
|
||||
#
|
||||
# Same liveness rule as skip_intro.sh, for the same reason: a failed screenshot
|
||||
# leaves r/g/b unset, they default to 0, the green test fails, and waiting for
|
||||
# the HUD becomes indistinguishable from waiting for a dead emulator.
|
||||
# leaves the classification unset and waiting for the HUD becomes
|
||||
# indistinguishable from waiting for a dead emulator.
|
||||
set -u
|
||||
export HOME=/sylph-home/re
|
||||
DISP="${DISPLAY:-:98}"
|
||||
SD="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; }
|
||||
DEADLINE=$(( SECONDS + ${1:-240} ))
|
||||
PX=450; PY=640 # inside the SHIELD bar of the flight HUD
|
||||
last_tap=0
|
||||
hits=0; last_tap=0
|
||||
while [ $SECONDS -lt $DEADLINE ]; do
|
||||
rm -f /tmp/wf.png
|
||||
if ! screenshot /tmp/wf.png >/dev/null 2>&1 || [ ! -s /tmp/wf.png ]; then
|
||||
@@ -30,16 +41,20 @@ while [ $SECONDS -lt $DEADLINE ]; do
|
||||
sleep 2; continue
|
||||
fi
|
||||
[ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s"; exit 4; }
|
||||
read -r r g b < <(convert /tmp/wf.png -format \
|
||||
"%[fx:int(255*p{$PX,$PY}.r)] %[fx:int(255*p{$PX,$PY}.g)] %[fx:int(255*p{$PX,$PY}.b)]" info:)
|
||||
if [ "${g:-0}" -gt 140 ] && [ $(( g - r )) -gt 60 ] && [ $(( g - b )) -gt 60 ]; then
|
||||
echo "IN FLIGHT at ${SECONDS}s (HUD shield bar visible)"
|
||||
exit 0
|
||||
fi
|
||||
if [ $(( SECONDS - last_tap )) -ge 6 ]; then
|
||||
python3 "$(dirname "${BASH_SOURCE[0]}")/pad.py" tap A 0.3
|
||||
last_tap=$SECONDS
|
||||
cls="$(python3 "$SD/screen_id.py" /tmp/wf.png | awk '{print $1}')"
|
||||
if [ "$cls" = "flight" ]; then
|
||||
hits=$(( hits + 1 ))
|
||||
# Two consecutive frames: one green-heavy frame could be an explosion in a
|
||||
# cutscene. Do not tap A once flight has been seen — in the cockpit that is
|
||||
# a weapon/target press, not a "continue".
|
||||
[ $hits -ge 2 ] && { echo "IN FLIGHT at ${SECONDS}s (screen_id: flight)"; exit 0; }
|
||||
else
|
||||
hits=0
|
||||
if [ $(( SECONDS - last_tap )) -ge 6 ]; then
|
||||
python3 "$SD/pad.py" tap A 0.3
|
||||
last_tap=$SECONDS
|
||||
fi
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "NO FLIGHT HUD within ${1:-240}s"; exit 1
|
||||
echo "NO FLIGHT HUD within ${1:-240}s (last: ${cls:-none})"; exit 1
|
||||
|
||||
Reference in New Issue
Block a user