Lunar Porter moves into a directory of its own
The first application with things of its own, and the first customer for all three rungs before it at once. /Apps/Lander a launcher /Packages/app.Lander/Lander.sbx the program /Packages/app.Lander/splash.tune its tune Typing "Lander" starts the launcher, which needs no new rule: the shell runs what it reads, so a launcher beginning "#!" and Say.sbx beginning "SBEX" go down the same road and neither the shell nor the person has to know which kind of thing they started. It passes on what it was told with $args, and says #quiet, because a launcher is machinery and not narration. The game then asks where it came from and joins its tune's name to that, so nothing anywhere names /splash.tune. Every recorded Lander test still types just "Lander" and knows nothing about any of this, which is exactly the claim. ---- Why the directory is not in /Apps ---- A launcher and a directory of the same name cannot both be there; SBFS refuses the second. And /Apps is the directory the shell walks for every word it does not know and Tab walks for every first word, so doubling what is in it is a cost on the path that runs most. The "app." goes in FRONT rather than behind because Tab matches the start of a name: a prefix is a namespace and a suffix is a collision. Copy.app beside Copy.sbx makes "Copy" and Tab complete to the shared "Copy." and hand you a broken word. The launcher names drive 0, so a game started from a disk of your own is looked for where the game is rather than where you are - its lines run on your disk, which is what makes everything else in a script work. /lander.state stays at the root. A saved position belongs to whoever saved it and is found where they are standing; a tune belongs to the program and is found beside it. That pair is the whole distinction. ---- And what it cost ---- Two hundred thousand cycles, about twelve frames, between the machine starting and the game drawing: a script opened, a deeper path walked. Six video captures moved out by that much. The drift bar needed something else - its pad is counted from the MACHINE starting rather than the game, so the burn is now twelve frames shorter from the game's point of view, and the recording holds the button longer instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
2defbb49e2
commit
94bdf71356
+30
-24
@@ -1623,7 +1623,7 @@ for i in range(400):
|
||||
keys += b'\x80' + b'\x00' * 47
|
||||
open('$BUILD/lander.keys','wb').write(keys + b'\x00' * 8000)
|
||||
"
|
||||
timeout 30 "$EMU" --fast --cycles 900000 --keyboard "$BUILD/lander.keys" \
|
||||
timeout 30 "$EMU" --fast --cycles 1100000 --keyboard "$BUILD/lander.keys" \
|
||||
--screen "$BUILD/lander.ppm" --disk "$ROOT/Tests/build/disks/cosmos.img" \
|
||||
--ram-disk 2048 "$BUILD/cosmos.bin" > "$BUILD/lander.out" 2>&1 || true
|
||||
read -r MOON SKY SHIP SHIPLEFT SHIPRIGHT <<EOT
|
||||
@@ -1698,7 +1698,7 @@ print(sum(1 for o in range(0, len(px), 3) if px[o:o + 3] == moon))
|
||||
# thrusters. The gap between the two captures is what the check is made of, and it is the
|
||||
# same gap.
|
||||
python3 -c "open('$BUILD/lander.pad','wb').write(b'\x00' * 40 + b'\x08' * 400)"
|
||||
for when in 1000000 1800000; do
|
||||
for when in 1200000 2000000; do
|
||||
timeout 30 "$EMU" --fast --cycles $when --keyboard "$BUILD/lander.keys" \
|
||||
--pad "$BUILD/lander.pad" --screen "$BUILD/held$when.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
@@ -1712,7 +1712,7 @@ def top(path):
|
||||
ship = bytes.fromhex('d8c048')
|
||||
ys = [i // 320 for i in range(len(px) // 3) if px[i * 3:i * 3 + 3] == ship]
|
||||
return min(ys) if ys else -1
|
||||
print(top('$BUILD/held1000000.ppm'), top('$BUILD/held1800000.ppm'))
|
||||
print(top('$BUILD/held1200000.ppm'), top('$BUILD/held2000000.ppm'))
|
||||
" 2>/dev/null || echo "-1 -1")
|
||||
EOT
|
||||
[ "$EARLY" -gt 0 ] && [ "$LATE" -gt 0 ] && [ "$LATE" -lt "$EARLY" ] \
|
||||
@@ -1827,7 +1827,7 @@ open('$BUILD/fly.keys','wb').write(b'Lander\n' + SKIP + b'\x00' * 8000)"
|
||||
python3 -c "open('$BUILD/none.pad','wb').write(b'\x00' * 60000)"
|
||||
cp "$ROOT/Tests/build/disks/cosmos.img" "$BUILD/orbit.img"
|
||||
"$ROOT/SplitDisk" put "$BUILD/orbit.img" "$BUILD/orbit.state" /lander.state > /dev/null
|
||||
for when in 3000000 13000000 25000000 37000000; do
|
||||
for when in 3200000 13200000 25200000 37200000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/none.pad" --screen "$BUILD/orbit$when.ppm" \
|
||||
--disk "$BUILD/orbit.img" --ram-disk 2048 \
|
||||
@@ -1842,8 +1842,8 @@ def height(path):
|
||||
ship = [i // width for i in range(len(px) // 3)
|
||||
if px[i * 3:i * 3 + 3] == bytes.fromhex('d8c048')]
|
||||
return min(ship) if ship else -1
|
||||
print(height('$BUILD/orbit3000000.ppm'), height('$BUILD/orbit13000000.ppm'),
|
||||
height('$BUILD/orbit25000000.ppm'), height('$BUILD/orbit37000000.ppm'))
|
||||
print(height('$BUILD/orbit3200000.ppm'), height('$BUILD/orbit13200000.ppm'),
|
||||
height('$BUILD/orbit25200000.ppm'), height('$BUILD/orbit37200000.ppm'))
|
||||
" 2>/dev/null || echo "-1 -1 -1 -1")
|
||||
EOT
|
||||
# A smaller row is higher up. Fifty pixels of change either way, against turning points that
|
||||
@@ -1976,11 +1976,17 @@ EOT
|
||||
# is the drift: it grows right from the middle of the screen for a rightward one and left for
|
||||
# a leftward one, and NOUGHT DRAWS NOTHING, so "stopped" is the state with no bar at all.
|
||||
#
|
||||
# The recording holds Right for eighty frames and then nothing. Checked in two places: with a
|
||||
# drift, where the bar starts at the middle and runs right; and with none, where a sprite of
|
||||
# no width is a sprite that is not drawn.
|
||||
python3 -c "open('$BUILD/drift.pad','wb').write(b'\x00' * 20 + b'\x01' * 80 + b'\x00' * 400)"
|
||||
timeout 30 "$EMU" --fast --cycles 1600000 --keyboard "$BUILD/lander.keys" \
|
||||
# The recording holds Right for a hundred and twenty frames and then nothing. Checked in two
|
||||
# places: with a drift, where the bar starts at the middle and runs right; and with none,
|
||||
# where a sprite of no width is a sprite that is not drawn.
|
||||
#
|
||||
# IT WAS EIGHTY, AND THE PAD IS COUNTED FROM THE MACHINE STARTING rather than from the game
|
||||
# starting. A launcher put twelve frames between those two, so the game saw twelve fewer
|
||||
# frames of the burn and drew a narrower bar - which is a real reading of a real drift, and
|
||||
# nothing to do with what this check is about. Longer, so that what is being asked about is
|
||||
# whether a drift draws a bar rather than how long the pilot held the button.
|
||||
python3 -c "open('$BUILD/drift.pad','wb').write(b'\x00' * 20 + b'\x01' * 120 + b'\x00' * 400)"
|
||||
timeout 30 "$EMU" --fast --cycles 1800000 --keyboard "$BUILD/lander.keys" \
|
||||
--pad "$BUILD/drift.pad" --screen "$BUILD/drift.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/drift.out" 2>&1 || true
|
||||
@@ -2343,13 +2349,13 @@ python3 -c "
|
||||
pad = bytearray(b'\x08' * 3000)
|
||||
pad[100:108] = b'\x28' * 8 # Up and B together, so the climb is not interrupted.
|
||||
open('$BUILD/hoverwide.pad','wb').write(bytes(pad) + b'\x00' * 20000)"
|
||||
for when in 2000000 3000000 5000000 7000000; do
|
||||
for when in 2200000 3200000 5200000 7200000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/hoverwide.pad" --screen "$BUILD/station$when.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/station.out" 2>&1 || true
|
||||
done
|
||||
timeout 60 "$EMU" --fast --cycles 3000000 --keyboard "$BUILD/fly.keys" \
|
||||
timeout 60 "$EMU" --fast --cycles 3200000 --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/hovernarrow.pad" --screen "$BUILD/stationnarrow.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/stationnarrow.out" 2>&1 || true
|
||||
@@ -2366,11 +2372,11 @@ def station(path, band):
|
||||
if px[i * 3:i * 3 + 3] == blue and i // width < band]
|
||||
return len(at), (min(x for x, y in at) if at else -1)
|
||||
narrow = station('$BUILD/stationnarrow.ppm', 70)
|
||||
seen, x3 = station('$BUILD/station3000000.ppm', 200)
|
||||
seen, x3 = station('$BUILD/station3200000.ppm', 200)
|
||||
print(narrow[0], seen,
|
||||
station('$BUILD/station2000000.ppm', 200)[1], x3,
|
||||
station('$BUILD/station5000000.ppm', 200)[1],
|
||||
station('$BUILD/station7000000.ppm', 200)[1])
|
||||
station('$BUILD/station2200000.ppm', 200)[1], x3,
|
||||
station('$BUILD/station5200000.ppm', 200)[1],
|
||||
station('$BUILD/station7200000.ppm', 200)[1])
|
||||
" 2>/dev/null || echo "0 0 -1 -1 -1 -1")
|
||||
EOT
|
||||
# Forty pixels is the whole of the art, so none of it is clipped and it is the tile meant.
|
||||
@@ -2640,7 +2646,7 @@ open('$BUILD/crash.state','wb').write(struct.pack('<hhhhhhBBBB',
|
||||
"
|
||||
cp "$ROOT/Tests/build/disks/cosmos.img" "$BUILD/crash.img"
|
||||
"$ROOT/SplitDisk" put "$BUILD/crash.img" "$BUILD/crash.state" /lander.state > /dev/null
|
||||
for when in 1200000 1600000 2200000; do
|
||||
for when in 1400000 1800000 2400000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/none.pad" --screen "$BUILD/burst$when.ppm" \
|
||||
--disk "$BUILD/crash.img" --ram-disk 2048 \
|
||||
@@ -2658,8 +2664,8 @@ def bits(path):
|
||||
return 0, 0
|
||||
xs = [x for x, y in at]
|
||||
return len(at), max(xs) - min(xs)
|
||||
e = bits('$BUILD/burst1200000.ppm'); l = bits('$BUILD/burst1600000.ppm')
|
||||
print(e[0], e[1], l[0], l[1], bits('$BUILD/burst2200000.ppm')[0])
|
||||
e = bits('$BUILD/burst1400000.ppm'); l = bits('$BUILD/burst1800000.ppm')
|
||||
print(e[0], e[1], l[0], l[1], bits('$BUILD/burst2400000.ppm')[0])
|
||||
" 2>/dev/null || echo "0 0 0 0 -1")
|
||||
EOT
|
||||
# Forty pixels in one eight wide block is the lander; anything else in its colour is what is
|
||||
@@ -2671,7 +2677,7 @@ EOT
|
||||
&& result ok "and they carry on outwards" "$EARLYWIDE pixels apart, then $LATEWIDE" \
|
||||
|| result no "and they carry on outwards" "$EARLYWIDE pixels apart, then $LATEWIDE"
|
||||
# And they are gone by the time the verdict is up, rather than hanging over the words.
|
||||
[ "$AFTERBITS" = "0" ] && grep -q "Crashed" "$BUILD/burst2200000.out" \
|
||||
[ "$AFTERBITS" = "0" ] && grep -q "Crashed" "$BUILD/burst2400000.out" \
|
||||
&& result ok "and are gone before the verdict" "nothing left over the words" \
|
||||
|| result no "and are gone before the verdict" "$AFTERBITS pixels still there"
|
||||
|
||||
@@ -2933,7 +2939,7 @@ done
|
||||
# And a plain fall onto the pad it starts over, which lands rather than crashes.
|
||||
# Eight frames later than they used to be: the landing latch plays its two notes before the
|
||||
# dust goes up, and runPend waits for the second of them.
|
||||
for when in 2900000 3050000 3300000; do
|
||||
for when in 3100000 3250000 3500000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/none.pad" --screen "$BUILD/dust$when.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
@@ -2953,8 +2959,8 @@ def look(path):
|
||||
puff = len([1 for x, y in where('f0f0f0') if y > 20])
|
||||
ship = where('d8c048')
|
||||
return puff, (min(y for x, y in ship) if ship else -1)
|
||||
print(look('$BUILD/dust2900000.ppm')[0], look('$BUILD/dust3050000.ppm')[0],
|
||||
look('$BUILD/dust3300000.ppm')[0],
|
||||
print(look('$BUILD/dust3100000.ppm')[0], look('$BUILD/dust3250000.ppm')[0],
|
||||
look('$BUILD/dust3500000.ppm')[0],
|
||||
look('$BUILD/gas9900000.ppm')[0], look('$BUILD/gas10150000.ppm')[0],
|
||||
look('$BUILD/gas10800000.ppm')[0],
|
||||
look('$BUILD/gas10150000.ppm')[1], look('$BUILD/gas10800000.ppm')[1])
|
||||
|
||||
Reference in New Issue
Block a user