A quarter-tank warning that says it once, and a gauge that keeps saying it
Two halves of the same number. The warning is the moment it happened and the colour is how things stand: it fires on the way down through a quarter of a tank and then holds its peace, and the gauge stays red until a base fills the lander up, which also allows the warning again. Once, because a lander is at its most careful in the last few seconds before it touches, and something repeating in its ear through that is not a warning, it is a distraction. Checked where the fuel actually moves rather than once a frame - the tank only changes in takeFuel and payFuel, so there is nowhere else it can cross a threshold. Channel two, with the crash on three. Separate channels rather than one reused, because a crash while the warning is still sounding should not cut it off, and on a machine with four voices there is no reason to be clever. Half and a tenth are the obvious next thresholds and are deliberately not here: one is enough to find out whether being told at all is welcome. ---- And the crash sound is the one that was designed for it ---- Crash.json, which carries voice_gate itself, so the program's own trigger write is gone - it would have masked a deliberate choice rather than backing one up. The note moved from 24 to 60 by ear, and the comment saying it was low went with it. ---- A check that could not tell a beep from a nag ---- Counting bursts of sound cannot: without the latch the warning fires every tick the tank drops, far faster than the sound decays, so the beeps run into each other and a burst counter sees one long burst either way. It measures the LENGTH now - 26,944 samples against 490,348 - which is the difference between six tenths of a second and ten seconds of it.
This commit is contained in:
@@ -2714,6 +2714,70 @@ EOT
|
||||
&& result ok "and it is loudest at the front" "which is what makes it a bang" \
|
||||
|| result no "and it is loudest at the front" "louder in the second half than the first"
|
||||
|
||||
# ---- A quarter of a tank, said once ----
|
||||
#
|
||||
# ONCE is the whole design of it. A lander is at its most careful in the last few seconds
|
||||
# before it touches, and something repeating in its ear through that is not a warning, it is a
|
||||
# distraction. So it fires on the way DOWN through a quarter tank and then holds its peace,
|
||||
# and filling up at a base allows it again.
|
||||
#
|
||||
# The gauge says the same thing the other way round: the sound is the moment it happened, the
|
||||
# colour is how things stand. Both off the same number, so they cannot disagree.
|
||||
python3 -c "
|
||||
import struct
|
||||
# Seventy of two hundred and fifty five, which is a few ticks of thruster above the quarter.
|
||||
open('$BUILD/lowfuel.state','wb').write(struct.pack('<hhhhhhBBBB',
|
||||
0x14A0, 0, 0, 0, 0x14A0, 2600, 70, 0, 0, 0))
|
||||
"
|
||||
cp "$ROOT/Tests/build/disks/cosmos.img" "$BUILD/lowfuel.img"
|
||||
"$ROOT/SplitDisk" put "$BUILD/lowfuel.img" "$BUILD/lowfuel.state" /lander.state > /dev/null
|
||||
python3 -c "open('$BUILD/burn.pad','wb').write(b'\x08' * 40000)"
|
||||
for when in 1700000 2400000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/burn.pad" --screen "$BUILD/fuel$when.ppm" \
|
||||
--disk "$BUILD/lowfuel.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/fuel.out" 2>&1 || true
|
||||
done
|
||||
timeout 60 "$EMU" --fast --cycles 12000000 --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/burn.pad" --sound "$BUILD/warn.raw" \
|
||||
--disk "$BUILD/lowfuel.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/warn.out" 2>&1 || true
|
||||
read -r ABOVE BELOW WARNINGS <<EOT
|
||||
$(python3 -c "
|
||||
def gauge(path):
|
||||
d = open(path, 'rb').read()
|
||||
width = int(d[:40].split()[1])
|
||||
px = d[d.index(b'255\n') + 4:]
|
||||
def cells(colour):
|
||||
c = bytes.fromhex(colour)
|
||||
# The top row of the window, which is where the gauge is drawn.
|
||||
return sum(1 for i in range(len(px) // 3)
|
||||
if px[i * 3:i * 3 + 3] == c and i // width < 8) // 64
|
||||
return '%d,%d' % (cells('50c050'), cells('d04038'))
|
||||
import struct
|
||||
raw = open('$BUILD/warn.raw', 'rb').read()
|
||||
s = struct.unpack('<%dh' % (len(raw) // 2), raw)
|
||||
# ---- HOW LONG it sounds for, not how many times it starts ----
|
||||
#
|
||||
# Counting bursts cannot tell one beep from a nag. Without the latch the warning fires on
|
||||
# every tick the tank goes down, which is once every ten frames - far faster than the sound
|
||||
# decays, so the beeps run into each other and a burst counter sees ONE long burst either way.
|
||||
# The length is what differs: six tenths of a second against ten seconds of it.
|
||||
loud = [i for i, x in enumerate(s) if abs(x) > 300]
|
||||
span = (loud[-1] - loud[0]) if loud else 0
|
||||
print(gauge('$BUILD/fuel1700000.ppm'), gauge('$BUILD/fuel2400000.ppm'), span)
|
||||
" 2>/dev/null || echo "none none -1")
|
||||
EOT
|
||||
# Green cells then red cells, and none of the other colour either time.
|
||||
[ "$ABOVE" = "8,0" ] && [ "$BELOW" = "0,7" ] \
|
||||
&& result ok "the fuel gauge goes red at a quarter" "eight green became seven red" \
|
||||
|| result no "the fuel gauge goes red at a quarter" "$ABOVE above, $BELOW below"
|
||||
# Twelve seconds of holding the thruster, which empties the tank entirely and keeps it empty.
|
||||
# The warning is under a second of that, or it is a nag rather than a warning.
|
||||
[ "$WARNINGS" -gt 0 ] && [ "$WARNINGS" -lt 48000 ] \
|
||||
&& result ok "and the warning sounds once, not once a tick" "$WARNINGS samples of it in twelve seconds of running dry" \
|
||||
|| result no "and the warning sounds once, not once a tick" "$WARNINGS samples of warning"
|
||||
|
||||
# ---- Dust on landing, and gas on letting go ----
|
||||
#
|
||||
# The same six pieces as the explosion, thrown differently: dust goes sideways and UP off the
|
||||
|
||||
Reference in New Issue
Block a user