From 1928275f87e048aff35ae24242448de4c8eb6afc Mon Sep 17 00:00:00 2001 From: Anachronaut Date: Fri, 4 Sep 2026 10:51:01 -0400 Subject: [PATCH] A state can be placed, which four things were queued behind Lander reads sixteen bytes from /lander.state if the disk has one and starts from those: position, velocity, where the station is, fuel, and which screen to be in. A disk without the file is the game as it always was, which is every other flight in the suite. It exists because some states cannot be flown to. A successful dock needs the lander alongside the station and matched, and NINETY SIX pad files failed to get there - not for want of trying, but because climbing spends sideways speed, so a lander cannot rise while matched and arrives slower than orbital every time. Reaching it wants two burns and a phase. The orbit check had already been deleted for the same reason, and the strike check was flown on a nineteen frame window, which is the sort of fixture that ends up measuring the boot time rather than the physics. Binary, because that is what a file is on this machine. A tool to build one from readable text is a small job for another day; until then the tests write the bytes with the fields named, which reads plainly enough. ---- The buffer is a whole block, and that is not caution ---- osFileRead lands a file in Data Memory and a file is stored in blocks of 256, so reading sixteen bytes into sixteen bytes of room writes over whatever follows. It did: the first version put the buffer in front of the view tables, and the program read its state, wiped the numbers every gauge draws from, and left immediately - "finished" and back to the prompt, with nothing on the screen to say why. Four checks, each seen to fail on its own break: a state file places the lander (row 192 and twelve cells of gauge, against thirty one with no file), a matched approach docks and is paid once and not once a frame, it then rides the station a tile under it, and the same approach unmatched is a wreck. The flown strike fixture and its narrow window are gone. --- Programs/CosmOS/Apps/Lander.asm | 107 ++++++++++++++++++++++++ Programs/CosmOS/README.md | 2 +- Tests/expected/cosmosCrossDisk.out | 2 +- Tests/expected/cosmosDrives.out | 2 +- Tests/expected/cosmosFault.out | 2 +- Tests/expected/cosmosFlip.out | 2 +- Tests/expected/cosmosGrid.out | 2 +- Tests/expected/cosmosMonitor.out | 2 +- Tests/expected/cosmosMonitorRun.out | 2 +- Tests/expected/cosmosRun.out | 2 +- Tests/expected/cosmosSlowDisk.out | 2 +- Tests/expected/cosmosSprite.out | 2 +- Tests/video.sh | 122 ++++++++++++++++++---------- 13 files changed, 198 insertions(+), 53 deletions(-) diff --git a/Programs/CosmOS/Apps/Lander.asm b/Programs/CosmOS/Apps/Lander.asm index 571bcda..1531070 100644 --- a/Programs/CosmOS/Apps/Lander.asm +++ b/Programs/CosmOS/Apps/Lander.asm @@ -48,6 +48,7 @@ start: ; floor the system gives every program does not. SWI osTakeScreen + CALL loadState ; Before the view, because a state may say which view to be in. CALL setView ; The block every gauge below reads its screen numbers out of. SETD.0 Wide LDA.0 @@ -2172,6 +2173,75 @@ showHeightSized: OUTA 0xE9 ; And no depth, A being nought already. RET +; ---- A state, placed rather than flown to ---- +; +; Sixteen bytes read straight over the numbers the program would otherwise start with. If the +; file is not there nothing happens and the defaults stand, so a disk without one is the game +; as it has always been. +; +; ---- Which exists because some things cannot be flown to ---- +; +; A successful dock needs the lander alongside the station and matched, and NINETY SIX pad +; files failed to get there - not for want of trying, but because climbing spends sideways +; speed, so a lander cannot rise while matched and arrives slower than orbital every time. +; Reaching it wants two burns and a phase, which is a real manoeuvre rather than something a +; straight line of button presses stumbles into. The same was true of the orbit, whose check +; had to be deleted for measuring the boot time instead of the physics, and of the ride, and +; of the strike, whose window is nineteen frames wide. Four things queued behind one facility. +; +; BINARY, because that is what a file is on this machine. A tool to build one from readable +; text is a small job for another day; until then the tests write the bytes, which is plain +; enough while the fields are named. +loadState: + SETD.0 StateName + SETD.1 StateBuffer + SWI osFileRead + BNQ loadStateNone ; Not there, or would not read, and either way the defaults stand. + + SETD.0 StateAcross + SETD.1 AcrossLow + CALL copyWord + SETD.0 StateDown + SETD.1 DownLow + CALL copyWord + SETD.0 StateSpeedAcross + SETD.1 SpeedAcross + CALL copyWord + SETD.0 StateSpeedDown + SETD.1 SpeedDown + CALL copyWord + SETD.0 StateStation + SETD.1 StationLow + CALL copyWord + SETD.0 StateStationDown + SETD.1 StationDownLow + CALL copyWord + + SETD.0 StateFuel + LDA.0 + SETD.1 Fuel + STA.1 + SETD.0 StateWide + LDA.0 + SETD.1 Wide + STA.1 + SETD.0 StateLanded + LDA.0 + SETD.1 Landed + STA.1 +loadStateNone: + RET + +; Two bytes, from where DP0 says to where DP1 does. +copyWord: + LDA.0 + STA.1 + INCD.0 + INCD.1 + LDA.0 + STA.1 + RET + ; ---- Two zoom levels, which the device turns out to have already had ---- ; ; Forty columns and eighty are the same map, the same 8x8 cells and the same engine; only how @@ -2882,6 +2952,43 @@ ViewWide: ; Which of the two is up. Nought is forty columns, which is what the program starts in. Wide: 0x00 + +; ---- The sixteen bytes a state file holds, in the order it holds them ---- +; +; Named rather than numbered, so whatever writes one and this that reads it are describing the +; same fields. Low byte first, the way every other word here is. +StateName: +"/lander.state" +StateBuffer: +StateAcross: + 0x00 0x00 ; Where round the moon, in sixteenths. +StateDown: + 0x00 0x00 ; And how far down, which is negative above the origin. +StateSpeedAcross: + 0x00 0x00 +StateSpeedDown: + 0x00 0x00 +StateStation: + 0x00 0x00 ; Where the station is, so a rendezvous can start alongside one. +StateStationDown: + 0x00 0x00 +StateFuel: + 0x00 +StateWide: + 0x00 ; Which screen to start in: some of this is only visible wide. +StateLanded: + 0x00 +StateSpare: + 0x00 ; Room, because sixteen is a rounder number than fifteen. + +; ---- And a whole block of room after them ---- +; +; osFileRead lands a file in Data Memory and a file is stored in blocks of 256, so reading +; sixteen bytes into sixteen bytes of room writes over whatever follows. It did: the first +; version of this put the buffer in front of the view tables and the program read its state, +; wiped the numbers every gauge draws from, and left immediately - "finished" and back to the +; prompt, with nothing on the screen to say why. + #Reserve 0d240 ; What B was doing last frame, because a pad says what is held and not what was pressed. ZoomWas: 0x00 diff --git a/Programs/CosmOS/README.md b/Programs/CosmOS/README.md index d686294..e850d09 100644 --- a/Programs/CosmOS/README.md +++ b/Programs/CosmOS/README.md @@ -727,7 +727,7 @@ from every assembly file in it. Several are old programs written for the bare ma | Grid | The first program to use the screen as a screen. Redefines a tile above the font, fills all 128 map rows, and scrolls it diagonally a pixel at a time. | | Sprite | Moves a ball across the shell's own text, writing not one byte of the map to do it. It leaves the sprite in the table on the way out, because clearing them is the system's job - see below. | | Pad | Says what the controllers are doing, printing a line whenever one changes. It tells apart the three things that look identical from inside a game that is not responding: a pad nobody noticed, a pad mapped to nothing, and a mapping that is wrong. | -| Lander | Lunar Porter, rung one: a lander over a moon that wraps. Flown with a controller if there is one - a held thruster burns every tick it is held for - and with the arrow keys if there is not, where one press is one burn and that is the most the console can say. A bar at the bottom is the sideways drift, drawn as a sprite stretched to the speed - a moon has no air, so a drift never stops by itself and stopping one means cancelling it exactly, which is hard to do blind. It lands or crashes on arrival, and what decides is the speed at the moment it touches: gentler than three quarters of a pixel a frame downwards and half of one sideways, or it is a lander on its side. A fuel gauge sits in the window layer, where the moon turning underneath cannot scroll it away, and every thruster costs a unit of fuel every tick it fires. An empty tank is not an ending: it is a lander still flying that can no longer do anything about where. Four landing pads are carved into the moon after it is generated, levelled to whatever height their first column happened to have, and marked in cyan by an attribute rather than a tile of their own. The lander starts above one, because that is where a porter's day begins. Each pad is a base, told apart by the colour it is drawn in, and landing at one either loads cargo for the base across the moon or delivers what is aboard and pays eighty units of fuel. A landing is not an ending: the lander rests where it is until the throttle opens again, and A or Start says "read it" as readily as a key does. What a base says goes in the window rather than out of the console: the console draws into the map, so a message printed while flying is one the lander then flies over, and printing scrolls the whole world up a row. Opening the throttle wipes the line. Two bars read the speeds and are green while a landing would survive and red while it would not, so "can I put down" is a glance rather than a sum. A third runs up the left edge and is how much sky is under the lander, half a pixel of bar to a pixel of it; it reads nought the moment the lander is down, and it exists because the orbit takes the lander off the top of the screen and a panel that only works while the ground is in sight is no use above it. And gravity here is the pull MINUS the swing outwards, which is what makes an orbit rather than a one way trip: under four pixels a frame sideways the pull wins and the lander falls, over it the swing wins and the lander climbs, and at it they cancel and it circles. Falling buys sideways speed and climbing spends it - at a rate set by the product of the two, so the trade stops by itself as the sideways speed runs out - and that is the cycle: a fall carries the lander past orbital speed and becomes a climb, the climb pays it back and becomes a fall, periapse and apoapse, round and round. Orbital speed is marked on the drift bar, sixty four pixels either side of the middle, because a number nothing points at is folklore. Gravity never falls off and the moon wraps, so a circular orbit is the same length at any height and one orbital speed serves everywhere. There is a ceiling 192 pixels above the world's origin, which is the top of the wide view - it was sixty four while sixty four was all the sky a forty column screen had over the origin, which was a fact about the view rather than about the world. It pins rather than ends: leaving upward is recoverable, so the lander is held there and told so, and one sideways is spent every tick it tries to climb - without that the pin wiped the climb, the trade saw neither fall nor climb, and the speed pushing it up never changed. What kills you out here is running dry a long way from the ground. B, or z on the keyboard, swaps the screen between forty columns and eighty, which is the same map, the same cells and the same engine at half the size: nearly two thirds of the moon at once for the orbit, and twice as big for the landing. The twenty extra rows that buys go to the SKY and not to the moon - the wide view starts twenty four rows above the world's origin rather than at it, so the ground sits near the bottom and the whole flyable band is on the screen. Drawn down from the origin instead it was 71 per cent rock, which is a zoom that shows you more of the thing you cannot fly through. A lander at the ceiling is off the top of a forty column screen, which is where the orbit lives and why the altitude bar had to exist; zoomed out it is in the picture. And there is a station up there, twelve rows above the world's origin - about two thirds of the way from the ground to the ceiling, clear of work near the surface - going round at orbital speed - which needs no physics of its own, because a body at 64 sixteenths is exactly what a circular orbit IS under these rules, at any height, since gravity never falls off and the moon wraps. It is off the top of a forty column screen too, so it is somewhere to go that the zoom is needed to see. Docking it is landing on something that is moving: close enough, and slow enough RELATIVE TO THE STATION, or it is a wreck. Its speed is orbital speed, which is the number the marks on the drift bar point at, so the instrument for it was on the screen before there was anything to dock with. A dock pays eighty units of fuel and holds the lander a tile under the station until a thruster lets go. Getting there is a two burn manoeuvre and not a straight line: climbing SPENDS sideways speed, so a lander cannot rise while matched - it arrives slower than orbital every time, and has to raise the far side of its orbit and then circularise at the top. Down is a retro thruster at half the strength of up - one sixteenth a tick against two, which is exactly gravity's own step, so it can stop a climb and hurry a descent and can never turn a landing approach into a crash faster than letting go would. Arresting a rise otherwise meant a sideways burn and a wait for the orbit to come round, which is how a rendezvous really is flown and a lot to ask of somebody who has not flown one. It does nothing at all to a lander on the ground, which is not politeness: touchdown has already had its say and will not speak again, so without that guard a landed lander holding it goes straight through the moon. | +| Lander | Lunar Porter, rung one: a lander over a moon that wraps. Flown with a controller if there is one - a held thruster burns every tick it is held for - and with the arrow keys if there is not, where one press is one burn and that is the most the console can say. A bar at the bottom is the sideways drift, drawn as a sprite stretched to the speed - a moon has no air, so a drift never stops by itself and stopping one means cancelling it exactly, which is hard to do blind. It lands or crashes on arrival, and what decides is the speed at the moment it touches: gentler than three quarters of a pixel a frame downwards and half of one sideways, or it is a lander on its side. A fuel gauge sits in the window layer, where the moon turning underneath cannot scroll it away, and every thruster costs a unit of fuel every tick it fires. An empty tank is not an ending: it is a lander still flying that can no longer do anything about where. Four landing pads are carved into the moon after it is generated, levelled to whatever height their first column happened to have, and marked in cyan by an attribute rather than a tile of their own. The lander starts above one, because that is where a porter's day begins. Each pad is a base, told apart by the colour it is drawn in, and landing at one either loads cargo for the base across the moon or delivers what is aboard and pays eighty units of fuel. A landing is not an ending: the lander rests where it is until the throttle opens again, and A or Start says "read it" as readily as a key does. What a base says goes in the window rather than out of the console: the console draws into the map, so a message printed while flying is one the lander then flies over, and printing scrolls the whole world up a row. Opening the throttle wipes the line. Two bars read the speeds and are green while a landing would survive and red while it would not, so "can I put down" is a glance rather than a sum. A third runs up the left edge and is how much sky is under the lander, half a pixel of bar to a pixel of it; it reads nought the moment the lander is down, and it exists because the orbit takes the lander off the top of the screen and a panel that only works while the ground is in sight is no use above it. And gravity here is the pull MINUS the swing outwards, which is what makes an orbit rather than a one way trip: under four pixels a frame sideways the pull wins and the lander falls, over it the swing wins and the lander climbs, and at it they cancel and it circles. Falling buys sideways speed and climbing spends it - at a rate set by the product of the two, so the trade stops by itself as the sideways speed runs out - and that is the cycle: a fall carries the lander past orbital speed and becomes a climb, the climb pays it back and becomes a fall, periapse and apoapse, round and round. Orbital speed is marked on the drift bar, sixty four pixels either side of the middle, because a number nothing points at is folklore. Gravity never falls off and the moon wraps, so a circular orbit is the same length at any height and one orbital speed serves everywhere. There is a ceiling 192 pixels above the world's origin, which is the top of the wide view - it was sixty four while sixty four was all the sky a forty column screen had over the origin, which was a fact about the view rather than about the world. It pins rather than ends: leaving upward is recoverable, so the lander is held there and told so, and one sideways is spent every tick it tries to climb - without that the pin wiped the climb, the trade saw neither fall nor climb, and the speed pushing it up never changed. What kills you out here is running dry a long way from the ground. B, or z on the keyboard, swaps the screen between forty columns and eighty, which is the same map, the same cells and the same engine at half the size: nearly two thirds of the moon at once for the orbit, and twice as big for the landing. The twenty extra rows that buys go to the SKY and not to the moon - the wide view starts twenty four rows above the world's origin rather than at it, so the ground sits near the bottom and the whole flyable band is on the screen. Drawn down from the origin instead it was 71 per cent rock, which is a zoom that shows you more of the thing you cannot fly through. A lander at the ceiling is off the top of a forty column screen, which is where the orbit lives and why the altitude bar had to exist; zoomed out it is in the picture. And there is a station up there, twelve rows above the world's origin - about two thirds of the way from the ground to the ceiling, clear of work near the surface - going round at orbital speed - which needs no physics of its own, because a body at 64 sixteenths is exactly what a circular orbit IS under these rules, at any height, since gravity never falls off and the moon wraps. It is off the top of a forty column screen too, so it is somewhere to go that the zoom is needed to see. Docking it is landing on something that is moving: close enough, and slow enough RELATIVE TO THE STATION, or it is a wreck. Its speed is orbital speed, which is the number the marks on the drift bar point at, so the instrument for it was on the screen before there was anything to dock with. A dock pays eighty units of fuel and holds the lander a tile under the station until a thruster lets go. Getting there is a two burn manoeuvre and not a straight line: climbing SPENDS sideways speed, so a lander cannot rise while matched - it arrives slower than orbital every time, and has to raise the far side of its orbit and then circularise at the top. Which is also why it reads /lander.state if the disk has one: sixteen bytes of position, velocity, station, fuel and screen, laid straight over the numbers it would otherwise start with, so a rendezvous can be examined without flying one first. A disk without the file is the game as it always was. The buffer is a whole block wide because osFileRead lands a file in blocks of 256, and sixteen bytes of room for it wrote over everything that followed. Down is a retro thruster at half the strength of up - one sixteenth a tick against two, which is exactly gravity's own step, so it can stop a climb and hurry a descent and can never turn a landing approach into a crash faster than letting go would. Arresting a rise otherwise meant a sideways burn and a wait for the orbit to come round, which is how a rendezvous really is flown and a lot to ask of somebody who has not flown one. It does nothing at all to a lander on the ground, which is not politeness: touchdown has already had its say and will not speak again, so without that guard a landed lander holding it goes straight through the moon. | | Depth | Four pillars at four distances and a ball walking past them, behind the near ones and in front of the far ones. The ball is sprite nought and every pillar is numbered after it, so table order puts it in front of all four - what actually decides is the depth buffer, asked a column at a time. | | Flip | Draws a whole screen into the bank that is not being shown, waits, and then shows it in one byte out of one port. It writes nothing else at all - not a tile, not a colour - so it does not ask for the screen to be saved, and the line it printed is still there when it comes back. It deliberately does not put the displayed screen back either, because that is the system's to restore: a program that faulted while flipped could not have. | | Edit | A line editor. | diff --git a/Tests/expected/cosmosCrossDisk.out b/Tests/expected/cosmosCrossDisk.out index 7c3fc00..98e6376 100644 --- a/Tests/expected/cosmosCrossDisk.out +++ b/Tests/expected/cosmosCrossDisk.out @@ -25,7 +25,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosDrives.out b/Tests/expected/cosmosDrives.out index 474b47d..a354d6a 100644 --- a/Tests/expected/cosmosDrives.out +++ b/Tests/expected/cosmosDrives.out @@ -15,7 +15,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosFault.out b/Tests/expected/cosmosFault.out index 85951e2..62fde1c 100644 --- a/Tests/expected/cosmosFault.out +++ b/Tests/expected/cosmosFault.out @@ -32,7 +32,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosFlip.out b/Tests/expected/cosmosFlip.out index bac6449..5363f2e 100644 --- a/Tests/expected/cosmosFlip.out +++ b/Tests/expected/cosmosFlip.out @@ -22,7 +22,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosGrid.out b/Tests/expected/cosmosGrid.out index 16c9ccc..08940b5 100644 --- a/Tests/expected/cosmosGrid.out +++ b/Tests/expected/cosmosGrid.out @@ -22,7 +22,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosMonitor.out b/Tests/expected/cosmosMonitor.out index f598191..358afee 100644 --- a/Tests/expected/cosmosMonitor.out +++ b/Tests/expected/cosmosMonitor.out @@ -108,7 +108,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosMonitorRun.out b/Tests/expected/cosmosMonitorRun.out index b3021c8..96670ca 100644 --- a/Tests/expected/cosmosMonitorRun.out +++ b/Tests/expected/cosmosMonitorRun.out @@ -27,7 +27,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosRun.out b/Tests/expected/cosmosRun.out index a0075b4..4227e64 100644 --- a/Tests/expected/cosmosRun.out +++ b/Tests/expected/cosmosRun.out @@ -15,7 +15,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosSlowDisk.out b/Tests/expected/cosmosSlowDisk.out index 2884e2e..f39f062 100644 --- a/Tests/expected/cosmosSlowDisk.out +++ b/Tests/expected/cosmosSlowDisk.out @@ -13,7 +13,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/expected/cosmosSprite.out b/Tests/expected/cosmosSprite.out index ee199f5..b680e8e 100644 --- a/Tests/expected/cosmosSprite.out +++ b/Tests/expected/cosmosSprite.out @@ -22,7 +22,7 @@ Mode.sbx 48 Flip.sbx 173 Sprite.sbx 442 Depth.sbx 672 -Lander.sbx 6290 +Lander.sbx 6692 Pad.sbx 264 Crash.sbx 632 vars.script 50 diff --git a/Tests/video.sh b/Tests/video.sh index 3953391..d9dfafe 100755 --- a/Tests/video.sh +++ b/Tests/video.sh @@ -2347,52 +2347,90 @@ MOVED=$(( X3 - X2 )) && result ok "and round the back of the moon and out again" "gone, then back at $X7" \ || result no "and round the back of the moon and out again" "$X5 at five million, $X7 at seven" -# ---- Docking, and the half of it that can be flown to ---- +# ---- Docking, from a state placed rather than flown to ---- # -# The same shape as touchdown: close enough, and slow enough, or it is a wreck. What makes it -# a different skill is that "slow enough" is measured against the STATION, which is doing -# orbital speed - the number the marks on the drift bar already point at. +# The same shape as touchdown: close enough, and slow enough RELATIVE TO THE STATION, or it is +# a wreck. Its speed is orbital speed, which is what the marks on the drift bar point at. # -# ---- A NARROW FIXTURE, and it is written down rather than hidden ---- +# ---- Placed, because this cannot be flown to ---- # -# The climb here has to arrive at the station's altitude just as the station arrives at the -# lander, and the window measured 496 to 514 frames - about nineteen. 505 sits in the middle -# of it. That is thinner than this suite likes and it is the same shape as the orbit check -# that had to be deleted for measuring the boot time, so: IF THIS EVER FAILS, re-measure the -# window before believing the code is broken. +# Ninety six pad files were tried and every one either hit the moon or was run down on the way +# up, which is not the search's fault: climbing SPENDS sideways speed, so a lander cannot rise +# while matched and arrives slower than orbital every time. Reaching the station wants two +# burns and a phase. # -# It was not always narrow. The station used to orbit four rows up, where anything climbing -# away from the surface had to pass, and a strike could be had with any climb between 135 and -# 300 frames - eleven of this suite's other flights were being run down as collateral. Moving -# it to twelve rows and the ceiling to twenty four fixed all eleven at once, and made the -# station properly hard to blunder into. The narrow window is the price of that, and it is the -# right way round. -python3 -c "open('$BUILD/struck.pad','wb').write(b'\x08' * 505 + b'\x00' * 60000)" -timeout 60 "$EMU" --fast --cycles 40000000 --keyboard "$BUILD/fly.keys" \ - --pad "$BUILD/struck.pad" --disk "$ROOT/Tests/build/disks/cosmos.img" \ - --ram-disk 2048 "$BUILD/cosmos.bin" > "$BUILD/struck.out" 2>&1 || true -grep -q "Wrecked against the station" "$BUILD/struck.out" \ - && result ok "the station runs down a lander in its lane" "at 64 sixteenths of relative speed" \ - || result no "the station runs down a lander in its lane" "no wreck in the transcript" - -# ---- And the half that is not checked here ---- -# -# THE SUCCESSFUL DOCK IS NOT FLOWN. It was measured working, from a build that PLACED the -# lander alongside the station and matched: the tank went from 100 to 180, once and not once a -# frame, the message went up, and the pair then held together - lander at 316,168 and station -# at 320,160, one tile apart and unmoving for two hundred and forty frames, which is what -# riding looks like. A thrust in any direction let go of it. -# -# What could not be found was a pad file that flies there. Ninety six were tried and every one -# either hit the moon or was run down on the way UP, which turns out not to be the search's -# fault: climbing SPENDS sideways speed, by the exchange that makes the orbit work at all, so -# a lander cannot rise while matched - it arrives slower than orbital every time. Docking needs -# two burns, one to raise the far side of the orbit and one to circularise at the top, and no -# straight line of button presses stumbles into that. -# -# So it wants either a hand flown recording or, better, a way to PLACE the lander at a chosen -# position and velocity before the loop starts - which is now wanted by this, by the orbit -# above, by the ride, and by the narrow window three paragraphs up. +# So Lander reads sixteen bytes from /lander.state if the disk has one, and starts from those +# instead. A disk without one is the game as it always was, which is every other flight in +# this file. The strike below used to be flown, on a climb whose window was nineteen frames +# wide - the sort of fixture that ends up measuring the boot time. It is placed now and exact. +python3 -c " +import struct +def state(across, down, vx, vy, stationX, stationDown, fuel, wide, landed): + return struct.pack(' /dev/null +done +python3 -c "open('$BUILD/ackonly.pad','wb').write(b'\x00' * 200 + b'\x10' * 8 + b'\x00' * 60000)" +for run in place:3000000 dock:6000000 dock2:9000000 wreck:3000000; do + which="${run%%:*}"; when="${run##*:}" + timeout 60 "$EMU" --fast --cycles "$when" --keyboard "$BUILD/fly.keys" \ + --pad "$BUILD/ackonly.pad" --screen "$BUILD/$which.ppm" \ + --disk "$BUILD/${which%2}.img" --ram-disk 2048 \ + "$BUILD/cosmos.bin" > "$BUILD/$which.out" 2>&1 || true +done +# And the same moment with no state file at all, which is the contrast that says the file did it. +timeout 60 "$EMU" --fast --cycles 3000000 --keyboard "$BUILD/fly.keys" \ + --pad "$BUILD/ackonly.pad" --screen "$BUILD/nostate.ppm" \ + --disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \ + "$BUILD/cosmos.bin" > "$BUILD/nostate.out" 2>&1 || true +read -r PLACEDY PLACEDFUEL PLAINFUEL DOCKFUEL DOCK2FUEL RIDESHIP RIDESTATION </dev/null || echo "-1 -1 -1 -1 -1 none none") +EOT +# Placed at the world's origin with a hundred units: row 192 is the origin in the wide view, +# and twelve cells of gauge is a hundred. The plain disk at the same moment has a full tank, +# which is what says the FILE moved these and not the flight. +[ "$PLACEDY" = "192" ] && [ "$PLACEDFUEL" = "12" ] && [ "$PLAINFUEL" != "12" ] \ + && result ok "a state file places the lander" "row 192 and $PLACEDFUEL cells, against $PLAINFUEL with no file" \ + || result no "a state file places the lander" "row $PLACEDY, $PLACEDFUEL cells, plain disk $PLAINFUEL" +# A hundred plus eighty is a hundred and eighty, which is twenty two cells - and it is still +# twenty two three thousand cycles later, so it was paid ONCE and not once a frame. +[ "$DOCKFUEL" = "22" ] && [ "$DOCK2FUEL" = "22" ] \ + && result ok "a matched approach docks and is paid" "a hundred became a hundred and eighty, once" \ + || result no "a matched approach docks and is paid" "$DOCKFUEL cells, then $DOCK2FUEL" +# Held to it, one tile under, rather than merely paid by it. +[ "$RIDESHIP" = "316,104" ] && [ "$RIDESTATION" = "320,96" ] \ + && result ok "and rides it, a tile under" "lander $RIDESHIP, station $RIDESTATION" \ + || result no "and rides it, a tile under" "lander $RIDESHIP, station $RIDESTATION" +grep -q "Wrecked against the station" "$BUILD/wreck.out" \ + && result ok "and the same approach unmatched is a wreck" "64 sixteenths, eight times the limit" \ + || result no "and the same approach unmatched is a wreck" "no wreck in the transcript" # ---- Clearing puts the cursor back at the top ---- #