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 showLander
|
||||
CALL showDrift
|
||||
CALL showFall
|
||||
CALL showFuel
|
||||
SETD.0 Flying
|
||||
LDA.0
|
||||
@@ -660,6 +661,62 @@ fall:
|
||||
SETD.0 Landed
|
||||
LDA.0
|
||||
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.1 Gravity
|
||||
CALL addWord
|
||||
@@ -809,6 +866,33 @@ showLander:
|
||||
OUTA 0xE9
|
||||
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 ----
|
||||
;
|
||||
; A moon has no air, so a drift never stops by itself and stopping one means cancelling the
|
||||
@@ -862,6 +946,10 @@ magnitudeDone:
|
||||
showDrift:
|
||||
SETD.0 SpeedAcross
|
||||
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 ----
|
||||
;
|
||||
; 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.
|
||||
INIA 0xC8
|
||||
OUTA 0xE9 ; The ground block, which is a solid tile.
|
||||
INIA 0x01
|
||||
OUTA 0xE9 ; Attribute one, so the bar is not the colour of the moon.
|
||||
SETD.0 DriftColour
|
||||
LDA.0
|
||||
OUTA 0xE9 ; Green while this drift could be landed with, red while not.
|
||||
SETD.0 DriftAt
|
||||
LDA.0
|
||||
OUTA 0xE9
|
||||
@@ -1285,6 +1374,102 @@ payFuelFull:
|
||||
STA.0
|
||||
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 ----
|
||||
;
|
||||
; DP0 names the two byte value being changed, low half first, and DP1 the one being added to
|
||||
@@ -1455,6 +1640,14 @@ DriftAt:
|
||||
0x00
|
||||
DriftSize:
|
||||
0x00
|
||||
DriftColour:
|
||||
0x00
|
||||
FallColour:
|
||||
0x00
|
||||
FallSize:
|
||||
0x00
|
||||
FallAt:
|
||||
0x00
|
||||
|
||||
; ---- The tank ----
|
||||
;
|
||||
@@ -1534,6 +1727,11 @@ LandColumn:
|
||||
0x00
|
||||
AtBase:
|
||||
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:
|
||||
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. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
|
||||
Reference in New Issue
Block a user