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:
Anachronaut
2026-09-03 16:25:56 -04:00
co-authored by Claude Opus 5
parent 4b1c3d8e3f
commit a069ee7a00
13 changed files with 270 additions and 40 deletions
+200 -2
View File
@@ -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