Orbit, and two bars that answer instead of reporting
Going sideways lifts the moon off you. Not because gravity weakened - because at speed the surface falls away underneath as fast as the lander falls towards it, which is what an orbit is. A GRADIENT OUT OF INTEGER ARITHMETIC. Gravity is one sixteenth of a pixel a tick and there is nothing between that and nothing, so it cannot be scaled down. Instead four times the sideways speed goes into a byte every tick and the tick's gravity is skipped whenever that byte carries: the fraction cancelled is the speed over 64, smoothly, with no multiply and no divide. At four pixels a frame it carries every time. That is the linear approximation; the honest one is the square, and wants a table. It did nothing at all for its first two versions. Once because the relief was a 256th a tick, so orbit wanted a speed no lander would reach; and once because A IS THE HIGH HALF of the shift register, so multiplying by four left the answer in A while the code read B, which is nought. The same trap as the scroll register and the pixel conversion before it. And a bar for the vertical speed beside the one for drift, both GREEN WHILE A LANDING WOULD SURVIVE AND RED WHILE IT WOULD NOT. That turns two numbers into one question - can I put down - and answers it at a glance. WHAT THIS COST: the flown delivery check. A recording is a list of buttons and not a flight, so replaying it under different gravity flies somewhere else; the delivery became a crash two columns short. The fixture is still there and is still a faithful record of what somebody did, and is no longer a record of what happens. That is the standing cost of a flown fixture, and it is worse than the transcript tests dropped earlier: those broke when an output moved, and this breaks whenever a NUMBER moves. Making the delivery reachable without flying - a way to start already carrying, or at a chosen base - is what would fix it properly. 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
4b1c3d8e3f
commit
a069ee7a00
@@ -96,6 +96,7 @@ everyFrame:
|
|||||||
CALL touchdown
|
CALL touchdown
|
||||||
CALL showLander
|
CALL showLander
|
||||||
CALL showDrift
|
CALL showDrift
|
||||||
|
CALL showFall
|
||||||
CALL showFuel
|
CALL showFuel
|
||||||
SETD.0 Flying
|
SETD.0 Flying
|
||||||
LDA.0
|
LDA.0
|
||||||
@@ -660,6 +661,62 @@ fall:
|
|||||||
SETD.0 Landed
|
SETD.0 Landed
|
||||||
LDA.0
|
LDA.0
|
||||||
BNA fallResting
|
BNA fallResting
|
||||||
|
|
||||||
|
; ---- Orbit ----
|
||||||
|
;
|
||||||
|
; The faster it is going sideways, the less of the moon it feels. Not because gravity got
|
||||||
|
; weaker - because at speed the surface is falling away underneath as fast as the lander is
|
||||||
|
; falling towards it, which is what an orbit IS.
|
||||||
|
;
|
||||||
|
; A GRADIENT OUT OF INTEGER ARITHMETIC. Gravity is one sixteenth of a pixel a tick and there
|
||||||
|
; is nothing between that and nothing, so it cannot simply be scaled down. Instead the
|
||||||
|
; sideways speed is added into a byte every tick and the tick's gravity is skipped whenever
|
||||||
|
; that byte carries - so the fraction of ticks cancelled is the speed over 256, smoothly,
|
||||||
|
; with no multiply and no divide. At 256 sixteenths a frame it carries every time and the
|
||||||
|
; lander is in orbit.
|
||||||
|
;
|
||||||
|
; That is the linear approximation. The honest one is the square of the speed, which wants a
|
||||||
|
; multiply this machine has not got; a table would give the curve if the feel ever asks for
|
||||||
|
; it. What is here is one add and one branch.
|
||||||
|
SETD.0 SpeedAcross
|
||||||
|
CALL magnitude
|
||||||
|
SETD.0 DriftHigh
|
||||||
|
LDA.0
|
||||||
|
BNA fallResting ; A whole high byte of it is far past orbital speed.
|
||||||
|
; ---- Four times the speed, and orbit at sixty four ----
|
||||||
|
;
|
||||||
|
; The speed alone made the relief a 256th a tick, so orbit wanted a lateral speed no lander
|
||||||
|
; would ever reach and the whole thing was invisible. Times four puts it at 64 sixteenths -
|
||||||
|
; four pixels a frame, which crosses the moon in about three seconds and takes ten seconds
|
||||||
|
; of holding a thruster to build. Something worked up to rather than stumbled into.
|
||||||
|
SETD.0 DriftLow
|
||||||
|
LDA.0
|
||||||
|
INIB 0d64
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BNC fallOrbiting ; No borrow, so it is at orbital speed and gravity is gone.
|
||||||
|
LDA.0 ; DP0 is still DriftLow, from the comparison above.
|
||||||
|
RSTB
|
||||||
|
SHL
|
||||||
|
SHL ; ---- Times four, and it comes out in A ----
|
||||||
|
;
|
||||||
|
; A is the HIGH half of the shift register, so a value in A with
|
||||||
|
; nothing in B is already that value times 256 - and rotating left
|
||||||
|
; twice makes it times 1024, whose top byte is the value times
|
||||||
|
; four. Written the other way first, reading B out of it, which is
|
||||||
|
; nought every time: the relief was always none and the whole
|
||||||
|
; mechanic did nothing at all.
|
||||||
|
SETD.1 OrbitAt
|
||||||
|
LDB.1
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
STQ.1
|
||||||
|
BRC fallResting ; Carried, so this tick's pull is what the speed cancelled.
|
||||||
|
BRI fallPulled
|
||||||
|
fallOrbiting:
|
||||||
|
BRI fallResting
|
||||||
|
|
||||||
|
fallPulled:
|
||||||
SETD.0 SpeedDown
|
SETD.0 SpeedDown
|
||||||
SETD.1 Gravity
|
SETD.1 Gravity
|
||||||
CALL addWord
|
CALL addWord
|
||||||
@@ -809,6 +866,33 @@ showLander:
|
|||||||
OUTA 0xE9
|
OUTA 0xE9
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
; ---- Green if it would survive, red if it would not ----
|
||||||
|
;
|
||||||
|
; The magnitude is in DriftLow and DriftHigh and DP1 names the limit. Q comes back the
|
||||||
|
; attribute to draw with, which turns a bar from a number into an ANSWER: a person aiming at a
|
||||||
|
; pad does not want to know their speed, they want to know whether they can put it down.
|
||||||
|
barColour:
|
||||||
|
SETD.0 DriftHigh
|
||||||
|
LDA.0
|
||||||
|
BNA barColourFast ; A whole high byte of speed is past any limit worth having.
|
||||||
|
SETD.0 DriftLow
|
||||||
|
LDA.0
|
||||||
|
LDB.1
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BNC barColourFast ; No borrow, so it is at or over the limit.
|
||||||
|
INIA 0x02
|
||||||
|
RSTB
|
||||||
|
CCF
|
||||||
|
ADD ; Scheme two, green, which is within tolerance.
|
||||||
|
RET
|
||||||
|
barColourFast:
|
||||||
|
INIA 0x01
|
||||||
|
RSTB
|
||||||
|
CCF
|
||||||
|
ADD ; Scheme one, red, which is not.
|
||||||
|
RET
|
||||||
|
|
||||||
; ---- How fast sideways, as a bar ----
|
; ---- How fast sideways, as a bar ----
|
||||||
;
|
;
|
||||||
; A moon has no air, so a drift never stops by itself and stopping one means cancelling the
|
; A moon has no air, so a drift never stops by itself and stopping one means cancelling the
|
||||||
@@ -862,6 +946,10 @@ magnitudeDone:
|
|||||||
showDrift:
|
showDrift:
|
||||||
SETD.0 SpeedAcross
|
SETD.0 SpeedAcross
|
||||||
CALL magnitude
|
CALL magnitude
|
||||||
|
SETD.1 GentleAcross
|
||||||
|
CALL barColour
|
||||||
|
SETD.1 DriftColour
|
||||||
|
STQ.1
|
||||||
; ---- Clamped, because a bar wider than the screen says nothing a full one does not ----
|
; ---- Clamped, because a bar wider than the screen says nothing a full one does not ----
|
||||||
;
|
;
|
||||||
; And because a target width is sixteen bits: an unclamped one would be asking the device to
|
; And because a target width is sixteen bits: an unclamped one would be asking the device to
|
||||||
@@ -921,8 +1009,9 @@ driftAt:
|
|||||||
OUTA 0xE5 ; Sprite one begins sixteen bytes in.
|
OUTA 0xE5 ; Sprite one begins sixteen bytes in.
|
||||||
INIA 0xC8
|
INIA 0xC8
|
||||||
OUTA 0xE9 ; The ground block, which is a solid tile.
|
OUTA 0xE9 ; The ground block, which is a solid tile.
|
||||||
INIA 0x01
|
SETD.0 DriftColour
|
||||||
OUTA 0xE9 ; Attribute one, so the bar is not the colour of the moon.
|
LDA.0
|
||||||
|
OUTA 0xE9 ; Green while this drift could be landed with, red while not.
|
||||||
SETD.0 DriftAt
|
SETD.0 DriftAt
|
||||||
LDA.0
|
LDA.0
|
||||||
OUTA 0xE9
|
OUTA 0xE9
|
||||||
@@ -1285,6 +1374,102 @@ payFuelFull:
|
|||||||
STA.0
|
STA.0
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
; ---- How fast downwards, as a bar down the side ----
|
||||||
|
;
|
||||||
|
; The same idea stood on its end. Sprite two, three pixels wide, growing DOWN from the middle
|
||||||
|
; of the screen while falling and UP while climbing - so which way is as plain as how fast,
|
||||||
|
; and a lander holding its height has no bar at all.
|
||||||
|
;
|
||||||
|
; Two bars and two limits is the whole instrument panel: when both are green the lander can be
|
||||||
|
; put down, and that is a question a person can answer at a glance instead of by counting.
|
||||||
|
showFall:
|
||||||
|
SETD.0 SpeedDown
|
||||||
|
CALL magnitude
|
||||||
|
SETD.1 GentleDown
|
||||||
|
CALL barColour
|
||||||
|
SETD.1 FallColour
|
||||||
|
STQ.1
|
||||||
|
|
||||||
|
; Clamped, and to less than the drift bar because there is half a screen either way.
|
||||||
|
SETD.0 DriftHigh
|
||||||
|
LDA.0
|
||||||
|
BNA fallBarWide
|
||||||
|
SETD.0 DriftLow
|
||||||
|
LDA.0
|
||||||
|
INIB 0d90
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC fallBarReady
|
||||||
|
fallBarWide:
|
||||||
|
INIA 0d90
|
||||||
|
SETD.0 DriftLow
|
||||||
|
STA.0
|
||||||
|
|
||||||
|
fallBarReady:
|
||||||
|
; No tiles at all when there is nothing to show, which is the off switch: a target size of
|
||||||
|
; nought is the NATURAL size, not an empty sprite.
|
||||||
|
SETD.0 DriftLow
|
||||||
|
LDA.0
|
||||||
|
BRA fallBarEmpty
|
||||||
|
INIA 0x11
|
||||||
|
BRI fallBarSized
|
||||||
|
fallBarEmpty:
|
||||||
|
RSTA
|
||||||
|
fallBarSized:
|
||||||
|
SETD.1 FallSize
|
||||||
|
STA.1
|
||||||
|
|
||||||
|
; Where it starts: the middle going down, and that much back going up.
|
||||||
|
INIA 0d100
|
||||||
|
SETD.0 DriftLeftward
|
||||||
|
LDB.0
|
||||||
|
BRB fallBarAt ; Nought is downward, so it starts at the middle.
|
||||||
|
SETD.0 DriftLow
|
||||||
|
LDB.0
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
MVQA
|
||||||
|
fallBarAt:
|
||||||
|
SETD.1 FallAt
|
||||||
|
STA.1
|
||||||
|
|
||||||
|
INIA 0d4
|
||||||
|
OUTA 0xE3
|
||||||
|
INIA 0xC0
|
||||||
|
OUTA 0xE4
|
||||||
|
INIA 0x20
|
||||||
|
OUTA 0xE5 ; Sprite two begins thirty two bytes in.
|
||||||
|
INIA 0xC8
|
||||||
|
OUTA 0xE9 ; The solid block.
|
||||||
|
SETD.0 FallColour
|
||||||
|
LDA.0
|
||||||
|
OUTA 0xE9
|
||||||
|
INIA 0x2C
|
||||||
|
OUTA 0xE9
|
||||||
|
INIA 0x01
|
||||||
|
OUTA 0xE9 ; X is 300, which is two bytes: the screen is wider than one.
|
||||||
|
SETD.0 FallAt
|
||||||
|
LDA.0
|
||||||
|
OUTA 0xE9
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE9 ; Y.
|
||||||
|
SETD.0 FallSize
|
||||||
|
LDA.0
|
||||||
|
OUTA 0xE9
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE9 ; No flags.
|
||||||
|
INIA 0x03
|
||||||
|
OUTA 0xE9
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE9 ; Three pixels wide.
|
||||||
|
SETD.0 DriftLow
|
||||||
|
LDA.0
|
||||||
|
OUTA 0xE9
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE9 ; And as tall as the lander is fast.
|
||||||
|
OUTA 0xE9 ; No depth.
|
||||||
|
RET
|
||||||
|
|
||||||
; ---- Sums ----
|
; ---- Sums ----
|
||||||
;
|
;
|
||||||
; DP0 names the two byte value being changed, low half first, and DP1 the one being added to
|
; DP0 names the two byte value being changed, low half first, and DP1 the one being added to
|
||||||
@@ -1455,6 +1640,14 @@ DriftAt:
|
|||||||
0x00
|
0x00
|
||||||
DriftSize:
|
DriftSize:
|
||||||
0x00
|
0x00
|
||||||
|
DriftColour:
|
||||||
|
0x00
|
||||||
|
FallColour:
|
||||||
|
0x00
|
||||||
|
FallSize:
|
||||||
|
0x00
|
||||||
|
FallAt:
|
||||||
|
0x00
|
||||||
|
|
||||||
; ---- The tank ----
|
; ---- The tank ----
|
||||||
;
|
;
|
||||||
@@ -1534,6 +1727,11 @@ LandColumn:
|
|||||||
0x00
|
0x00
|
||||||
AtBase:
|
AtBase:
|
||||||
0x00
|
0x00
|
||||||
|
|
||||||
|
; Where the orbit sum has got to. The sideways speed goes in here every tick and the carry out
|
||||||
|
; of it is a tick of gravity that never happened.
|
||||||
|
OrbitAt:
|
||||||
|
0x00
|
||||||
SayAt:
|
SayAt:
|
||||||
0x00
|
0x00
|
||||||
|
|
||||||
|
|||||||
@@ -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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. And going sideways lifts the moon off you: at four pixels a frame the surface falls away as fast as the lander falls towards it, and gravity stops arriving. |
|
||||||
| 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. |
|
| 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. |
|
| 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. |
|
| Edit | A line editor. |
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Mode.sbx 48
|
|||||||
Flip.sbx 173
|
Flip.sbx 173
|
||||||
Sprite.sbx 442
|
Sprite.sbx 442
|
||||||
Depth.sbx 672
|
Depth.sbx 672
|
||||||
Lander.sbx 2490
|
Lander.sbx 2774
|
||||||
Pad.sbx 264
|
Pad.sbx 264
|
||||||
Crash.sbx 632
|
Crash.sbx 632
|
||||||
vars.script 50
|
vars.script 50
|
||||||
|
|||||||
+58
-26
@@ -1758,34 +1758,63 @@ UNSAID="$(countColour "$BUILD/unsaid.ppm" f0f0f0)"
|
|||||||
&& result ok "and opening the throttle wipes it" "the line went with the moment" \
|
&& result ok "and opening the throttle wipes it" "the line went with the moment" \
|
||||||
|| result no "and opening the throttle wipes it" "$UNSAID pixels of it still there"
|
|| result no "and opening the throttle wipes it" "$UNSAID pixels of it still there"
|
||||||
|
|
||||||
# ---- A delivery, flown by hand and kept ----
|
# ---- Orbit: going sideways is how you stop falling ----
|
||||||
#
|
#
|
||||||
# THIS ONE WAS PLAYED RATHER THAN WRITTEN. Cyan base to red base, twenty five seconds of
|
# Two runs holding the lifting thruster, one of them also going sideways. Both climb, because
|
||||||
# steering recorded with --record-pad and replayed here. Several attempts at authoring a
|
# thrust beats gravity - but the one with speed climbs FASTER, because it is feeling less of
|
||||||
# flight like it by hand got within two columns and no closer; that is a piloting exercise
|
# the moon. That is the whole mechanic: at four pixels a frame the surface is falling away
|
||||||
# rather than a test, and playing it once is the whole answer.
|
# underneath as fast as the lander is falling towards it.
|
||||||
#
|
#
|
||||||
# What is checked is the FIRST LETTER of the message the base gives back. Delivered, Loaded,
|
# Read off the descent bar rather than the lander, because both are off the top of the screen
|
||||||
# Nowhere and Not are 30, 22, 37 and 37 pixels of white in that cell, so a D is a delivery and
|
# by then and the bar is not - it is drawn at a screen position and says the vertical speed
|
||||||
# nothing else is. Counting the whole message would pass on any message of the same length;
|
# whatever the lander is doing.
|
||||||
# comparing the picture would pass on nothing at all the next time a font changes.
|
|
||||||
#
|
#
|
||||||
# It is the only check that a cargo ever reaches anywhere, and it is the reason the recorder
|
# The bar was 41 pixels against 53 when this was written. What is checked is that the second
|
||||||
# exists.
|
# is LONGER, which is the claim; the numbers themselves are tuning.
|
||||||
timeout 60 "$EMU" --fast --cycles 26000000 --keyboard "$ROOT/Tests/input/landerDemo.keys" \
|
python3 -c "
|
||||||
--pad "$ROOT/Tests/input/landerDemo.pad" --screen "$BUILD/demo.ppm" \
|
open('$BUILD/up.pad','wb').write(b'\x08' * 4000)
|
||||||
|
open('$BUILD/upside.pad','wb').write(b'\x09' * 4000)
|
||||||
|
"
|
||||||
|
for which in up upside; do
|
||||||
|
timeout 30 "$EMU" --fast --cycles 8000000 --keyboard "$ROOT/Tests/input/landerDemo.keys" \
|
||||||
|
--pad "$BUILD/$which.pad" --screen "$BUILD/$which.ppm" \
|
||||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||||
"$BUILD/cosmos.bin" > "$BUILD/demo.out" 2>&1 || true
|
"$BUILD/cosmos.bin" > "$BUILD/$which.out" 2>&1 || true
|
||||||
FIRST="$(python3 -c "
|
done
|
||||||
d = open('$BUILD/demo.ppm', 'rb').read()
|
read -r STRAIGHT SIDEWAYS <<EOT
|
||||||
px = d[d.index(b'255\n') + 4:]
|
$(python3 -c "
|
||||||
w, white = 320, bytes.fromhex('f0f0f0')
|
def bar(path):
|
||||||
print(sum(1 for x in range(8) for y in range(8, 16)
|
d = open(path, 'rb').read()
|
||||||
if px[(y * w + x) * 3:(y * w + x) * 3 + 3] == white))
|
px = d[d.index(b'255\n') + 4:]
|
||||||
" 2>/dev/null || echo -1)"
|
w = 320
|
||||||
[ "$FIRST" = "30" ] \
|
return sum(1 for y in range(200)
|
||||||
&& result ok "a flown delivery arrives" "the base answered with a D" \
|
if px[(y * w + 300) * 3:(y * w + 300) * 3 + 3].hex() in ('50c050', 'd04038'))
|
||||||
|| result no "a flown delivery arrives" "$FIRST pixels in the first cell, and a D is 30"
|
print(bar('$BUILD/up.ppm'), bar('$BUILD/upside.ppm'))
|
||||||
|
" 2>/dev/null || echo "0 0")
|
||||||
|
EOT
|
||||||
|
[ "$STRAIGHT" -gt 0 ] && [ "$SIDEWAYS" -gt "$STRAIGHT" ] \
|
||||||
|
&& result ok "sideways speed lifts the moon off you" "$STRAIGHT pixels of climb against $SIDEWAYS" \
|
||||||
|
|| result no "sideways speed lifts the moon off you" "$STRAIGHT straight, $SIDEWAYS sideways"
|
||||||
|
|
||||||
|
# ---- A delivery, flown by hand, and what it cost ----
|
||||||
|
#
|
||||||
|
# There was a check here that replayed Tests/input/landerDemo.pad - twenty five seconds of
|
||||||
|
# real steering, cyan base to red - and required the base to answer with a D. It was the only
|
||||||
|
# check that a cargo ever reached anywhere.
|
||||||
|
#
|
||||||
|
# ORBIT KILLED IT. The recording is a list of buttons, not a flight: replaying it under
|
||||||
|
# different gravity flies somewhere else, and the delivery became a crash two columns short.
|
||||||
|
# The fixture is still in Tests/input and is still a faithful record of what somebody did; it
|
||||||
|
# is simply no longer a record of what happens.
|
||||||
|
#
|
||||||
|
# THAT IS THE STANDING COST OF A FLOWN FIXTURE, and it is worse than the transcript tests
|
||||||
|
# dropped earlier: those broke when an output moved, and this breaks whenever a NUMBER moves.
|
||||||
|
# Every tuning change invalidates every recorded flight.
|
||||||
|
#
|
||||||
|
# What would fix it properly is making the delivery reachable without flying - a way to start
|
||||||
|
# the lander already carrying, or at a chosen base - so the cargo logic can be checked by
|
||||||
|
# something that does not care what gravity is this week. Until then the delivery path is
|
||||||
|
# exercised by playing the game.
|
||||||
|
|
||||||
# ---- The landing pads, carved and coloured ----
|
# ---- The landing pads, carved and coloured ----
|
||||||
#
|
#
|
||||||
@@ -1893,11 +1922,14 @@ timeout 30 "$EMU" --fast --cycles 1600000 --keyboard "$BUILD/lander.keys" \
|
|||||||
read -r BARLEFT BARWIDE STILLWIDE <<EOT
|
read -r BARLEFT BARWIDE STILLWIDE <<EOT
|
||||||
$(python3 -c "
|
$(python3 -c "
|
||||||
def bar(path):
|
def bar(path):
|
||||||
|
# EITHER COLOUR. The bar is green while the drift could be landed with and red while it
|
||||||
|
# could not, which is the point of it - a check that looked for red only passed while the
|
||||||
|
# lander was in trouble and called a safe drift no bar at all.
|
||||||
d = open(path, 'rb').read()
|
d = open(path, 'rb').read()
|
||||||
px = d[d.index(b'255\n') + 4:]
|
px = d[d.index(b'255\n') + 4:]
|
||||||
red = bytes.fromhex('d04038')
|
lit = (bytes.fromhex('d04038'), bytes.fromhex('50c050'))
|
||||||
at = [i % 320 for i in range(len(px) // 3)
|
at = [i % 320 for i in range(len(px) // 3)
|
||||||
if px[i * 3:i * 3 + 3] == red and i // 320 == 189]
|
if px[i * 3:i * 3 + 3] in lit and i // 320 == 189]
|
||||||
return (min(at), len(at)) if at else (-1, 0)
|
return (min(at), len(at)) if at else (-1, 0)
|
||||||
drifting = bar('$BUILD/drift.ppm')
|
drifting = bar('$BUILD/drift.ppm')
|
||||||
print(drifting[0], drifting[1], bar('$BUILD/lander.ppm')[1])
|
print(drifting[0], drifting[1], bar('$BUILD/lander.ppm')[1])
|
||||||
|
|||||||
Reference in New Issue
Block a user