Files
SplitBit-Emulator/Tests/replay.sh
T
AnachronautandClaude Opus 5 de1857f5f7 Record every pad, not the one that happened to be first
The first recording ever made with this came back 1,766 frames of nothing.
It recorded pad NOUGHT and the controller was somewhere else - which pad
one lands on is an accident of the host, the same accident that made Lunar
Porter read all four in the first place - and a flight flown for the
purpose was lost to it.

So every pad is or-ed into the byte. A demo is a record of what somebody
DID, and on a machine one person is playing the number it arrived on is
not part of that. It plays back on pad nought, where --pad puts the first
file given, and any program that reads more than one pad reads them or-ed
anyway for exactly the same reason.

--record-pad takes one file now rather than filling pads in turn, because
there is nothing left for the second one to mean.

The check for it plays a recording on pad ONE with nought holding nothing
and requires the bytes back. That is the case that was missing: the round
trip was tested and passed, on pad nought, which is the only pad it could
not have gone wrong on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
2026-09-03 14:27:58 -04:00

124 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Checks that what the machine records is what it plays back.
#
# --record-pad writes what a controller held, one byte a frame, in exactly the format --pad
# reads. That symmetry is the whole feature and it is the whole of what is checked here: a
# recording is only worth having if playing it back does what was recorded.
#
# ---- Why it exists ----
#
# Some inputs cannot sensibly be written by hand. Flying a lander from one base to another is
# a few hundred frames of steering that has to arrive somewhere eight cells wide, and several
# attempts at hand-authoring one got within two columns and no closer. That is a piloting
# exercise rather than a test. Playing it once and keeping what happened is the answer, and
# this is what says the keeping works.
#
# Written by Anachronaut
set -u
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
BUILD="$ROOT/Tests/build/replay"
ASM="$ROOT/Assembler"
EMU="$ROOT/SplitBit"
for tool in "$ASM" "$EMU"; do
[ -x "$tool" ] || { echo "$(basename "$tool") is not built."; exit 1; }
done
rm -rf "$BUILD"; mkdir -p "$BUILD"
PASS=0
FAIL=0
FAILED_NAMES=()
GREEN=$'\033[32m'; RED=$'\033[31m'; RESET=$'\033[0m'
[ -t 1 ] || { GREEN=""; RED=""; RESET=""; }
result() {
if [ "$1" = "ok" ]; then
PASS=$((PASS + 1)); printf " [%sok %s] %-40s %s\n" "$GREEN" "$RESET" "$2" "$3"
else
FAIL=$((FAIL + 1)); FAILED_NAMES+=("$2")
printf " [%sFAIL%s] %-40s %s\n" "$RED" "$RESET" "$2" "$3"
fi
}
echo "Checking that a recording plays back as itself."
# A program that reads a pad every frame and stops. It is the one in testPrograms rather than
# a new one, because what is being checked is the recording and not the reading.
"$ASM" "$ROOT/Programs/testPrograms/padTest.asm" -o "$BUILD/padTest.bin" > "$BUILD/asm.log" 2>&1 \
|| { echo "padTest did not assemble."; exit 1; }
# ---- Played and recorded at the same time ----
#
# The strongest form of the claim: the recording is made OF a playback, so if the two formats
# ever drift apart the bytes coming out stop matching the bytes going in.
"$EMU" --fast --pad "$ROOT/Tests/input/padTest.pad" \
--record-pad "$BUILD/roundtrip.pad" "$BUILD/padTest.bin" > "$BUILD/roundtrip.out" 2>&1
SAME="$(python3 -c "
first = open('$ROOT/Tests/input/padTest.pad', 'rb').read()
again = open('$BUILD/roundtrip.pad', 'rb').read()
print('yes' if again[:len(first)] == first else 'no')
" 2>/dev/null || echo error)"
[ "$SAME" = "yes" ] \
&& result ok "a recording of a playback is the playback" "byte for byte, in and out" \
|| result no "a recording of a playback is the playback" "the bytes differ"
# ---- And it does not matter which controller it was ----
#
# The first recording ever made with this came back 1,766 frames of nothing. It recorded pad
# NOUGHT and the controller was somewhere else - which pad one lands on is an accident of the
# host, and the flight had to be flown again for nothing.
#
# So every pad is or-ed into the byte. Here the same recording is played on pad ONE, with
# nought holding nothing, and what comes out has to be what went in.
python3 -c "open('$BUILD/idle.pad','wb').write(b'\x00' * 64)"
"$EMU" --fast --pad "$BUILD/idle.pad" --pad "$ROOT/Tests/input/padTest.pad" \
--record-pad "$BUILD/padone.pad" "$BUILD/padTest.bin" > "$BUILD/padone.out" 2>&1
ELSEWHERE="$(python3 -c "
first = open('$ROOT/Tests/input/padTest.pad', 'rb').read()
again = open('$BUILD/padone.pad', 'rb').read()
print('yes' if again[:len(first)] == first else 'no')
" 2>/dev/null || echo error)"
[ "$ELSEWHERE" = "yes" ] \
&& result ok "a controller on any pad is recorded" "flown on pad one, written all the same" \
|| result no "a controller on any pad is recorded" "the bytes differ"
# ---- One byte a frame, and the frame is the machine's ----
#
# A recording is a TIMELINE. If it were a byte a read, a program that polled twice in one
# frame would record twice as fast as it flew; if it skipped frames nobody looked at, it would
# play back faster than it was flown. So the count is the number of frames the machine ran,
# which at 16,667 cycles a frame is arithmetic rather than a guess.
"$EMU" --fast --cycles 500000 --record-pad "$BUILD/timeline.pad" \
"$BUILD/padTest.bin" > "$BUILD/timeline.out" 2>&1
WROTE="$(wc -c < "$BUILD/timeline.pad" | tr -d ' ')"
# The machine halts of its own accord well before the limit, so what is checked is that the
# count is frames-of-something rather than bytes-of-nothing: more than none, and fewer than
# the limit could possibly hold.
[ "$WROTE" -gt 0 ] && [ "$WROTE" -le 30 ] \
&& result ok "a byte for every frame and no more" "$WROTE frames of it" \
|| result no "a byte for every frame and no more" "$WROTE bytes, which is not a frame count"
# ---- And a machine with no controller records that honestly ----
#
# Nothing held is nought, which is what a pad nobody is touching reports and what a machine
# with no pad at all reports. A recorder that wrote something else would make a fixture that
# pressed buttons nobody pressed.
QUIET="$(python3 -c "
data = open('$BUILD/timeline.pad', 'rb').read()
print('yes' if set(data) <= {0} else 'no')
" 2>/dev/null || echo error)"
[ "$QUIET" = "yes" ] \
&& result ok "and nothing held is written as nothing" "no buttons nobody pressed" \
|| result no "and nothing held is written as nothing" "the recording holds something"
echo
if [ "$FAIL" -eq 0 ]; then
echo "All $PASS replay checks passed."
exit 0
fi
echo "$PASS passed, $FAIL failed: ${FAILED_NAMES[*]}"
exit 1