An orbit that comes back round, out of gravity minus the swing

The relief version could never make one. It only ever SUBTRACTED from
gravity, so a lander a little too slow sank for ever and one a little
too fast rose for ever - nothing in it could turn a fall around, because
nothing in it ever pushed up. There was no periapse to have.

Gravity minus the swing outwards has a sign change in it, and that is
the whole mechanic. Below orbital speed the pull wins and the lander
falls; above it the swing wins and the lander climbs; at 64 sixteenths
they cancel and it circles. Falling buys sideways speed and climbing
spends it, so a fall carries the lander past orbital and turns into a
climb, and the climb pays it back and turns into a fall.

The trade is the quarter square multiply, because the rate has to be
the PRODUCT of the two speeds. Set by the vertical speed alone it drained
a climb to nothing, and any minimum to stop that became a trap the climb
spent its way into - measured freezing at 23 with a gate of 24 and at 3
with a gate of 4. With the product in it there is no gate: as the
sideways speed goes to nothing the trade stops by itself.

Half the product rather than a quarter or the high half. The high half
alone is nought below a product of 256, which is a dead patch exactly
where the turn begins, and a quarter still ran the lander into the roof
before it came round - the whole sky is about 145 pixels.

Measured, placed at 80 sideways and left alone: apoapse at -1024 with 59
sideways, periapse at -124 with 71, and round again at 165, 241, 299 and
369 ticks with no sign of decay. A period of about 22 seconds.

The ceiling also spends one sideways when it wipes a climb. Without that
it was a trap with no way out: the pin wipes the climb, so the trade sees
neither fall nor climb and never touches the speed that is pushing the
lander up. Measured pinned at the top with 117 sideways, unmoving, for
the whole of a four minute flight.

Tests/makedisks.sh needed the library path, since Lander now includes
math.asm, and the app went from 2,924 bytes to 4,651 - mostly the 1,022
byte table - which is what the listing expectations move for.
This commit is contained in:
Anachronaut
2026-09-03 19:15:50 -04:00
parent f5642f52b5
commit c514d5328e
13 changed files with 295 additions and 60 deletions
+259 -36
View File
@@ -66,6 +66,7 @@ start:
OUTA 0x34
OUTA 0x38 ; No fraction of a cell downwards either.
CALL mulReady ; The quarter square table, once. The orbit below needs a product.
CALL putTiles
CALL makeMoon
CALL carvePads
@@ -662,64 +663,112 @@ fall:
LDA.0
BNA fallResting
; ---- Orbit ----
CALL exchange
; ---- Orbit, which is gravity MINUS the swing outwards ----
;
; 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.
; The first version of this only ever SUBTRACTED from gravity, and that is why it never
; behaved like an orbit. Cancelling some of the pull can stop a fall from getting worse; it
; can never turn one round, because nothing in it ever pushes up. A lander a little too slow
; sank for ever and a lander a little too fast rose for ever, and both of them were right.
;
; 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.
; What actually happens is a difference between two things. Gravity pulls in and going round
; throws out, and which of them wins depends on the sideways speed:
;
; 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.
; below orbital speed the pull wins and the lander falls
; at orbital speed they cancel and the lander circles
; above orbital speed the swing wins and the lander climbs
;
; That sign change is the whole mechanic. Falling buys sideways speed (see the exchange
; above), so a fall carries the lander past orbital speed and the swing turns it into a
; climb: a periapse. Climbing spends that speed back, drops it below orbital, and the pull
; turns the climb into a fall: an apoapse. Round and round, which is what an orbit is.
;
; ---- A gradient out of integer arithmetic ----
;
; The step is one sixteenth of a pixel a tick and there is nothing between that and nothing,
; so the strength cannot be scaled down directly. Instead the distance from orbital speed is
; added into a byte every tick and the step is taken only when that byte carries - so the
; fraction of ticks that act is the distance over 256, smoothly, with no divide.
;
; Times four, because the speed alone put orbit at a lateral speed no lander would ever
; reach. At four it lands on 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 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.
BNA fallOutFull ; A whole high byte of it: far past orbital, and thrown outwards.
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.
BRC fallInward ; Borrowed, so it is short of orbital speed and the pull wins.
; ---- Above orbital speed, so the swing wins ----
MVQA ; Q is how far past, from the comparison just above.
CCF
SUB ; B is still 64, from that same comparison.
BNC fallOutFull
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.
SHL ; Times four; A is the high half, so the answer comes out in A.
BRI fallOutStep
fallOutFull:
INIA 0xFF
fallOutStep:
SETD.1 OrbitStep
STA.1
INIA 0x01
SETD.1 Outward
STA.1
BRI fallSwing
; ---- Below orbital speed, so the pull wins ----
fallInward:
MVQA ; Q is the shortfall, less its sign.
NOTA
MVQA
INCA
INIB 0d64
CCF
SUB
BNC fallInFull
RSTB
SHL
SHL
BRI fallInStep
fallInFull:
INIA 0xFF ; Standing still, which is the whole of gravity and no swing.
fallInStep:
SETD.1 OrbitStep
STA.1
RSTA
SETD.1 Outward
STA.1
fallSwing:
SETD.0 OrbitStep
LDA.0
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:
BNC fallResting ; No carry, so this tick is one of the ones that does nothing.
SETD.0 Outward
LDA.0
BNA fallPushed
SETD.0 SpeedDown
SETD.1 Gravity
CALL addWord
BRI fallResting
fallPushed:
SETD.0 SpeedDown
SETD.1 Lift
CALL addWord
fallResting:
; ---- And whatever is being leaned on, on the same tick ----
@@ -773,6 +822,142 @@ fallNotLeft:
fallDone:
RET
; ---- Falling buys sideways speed; climbing spends it ----
;
; What the first orbit was missing. Cancelling gravity by speed lets a fast lander stop
; falling and gives it no way back: a little too slow and it sank for ever, faster and faster,
; because ALTITUDE DID NOTHING. Nothing turned height into speed or speed into height.
;
; A real orbit is that exchange. Falling towards periapse trades height for speed, which buys
; more relief, which turns the fall into a climb; climbing towards apoapse pays it back and
; the climb becomes a fall. That cycle is the whole character of an orbit.
;
; ---- And the rate is the PRODUCT, which is why this needed a multiply ----
;
; The first attempt traded at a rate set by the vertical speed alone, and it drained a climb
; all the way to nought: a lander that climbed long enough had no sideways speed left to buy
; relief with, and sank. Gating it above a minimum made it worse - the climb spent its way
; down to the gate and locked itself out, frozen there for ever.
;
; The honest rate is proportional to BOTH speeds, and that is what fixes it: as the sideways
; speed falls towards nought the trade stops by itself. The product is its own gate, and no
; threshold is needed or wanted.
exchange:
SETD.0 SpeedAcross
CALL magnitude
SETD.0 DriftHigh
LDA.0
BNA exchangeQuick ; A whole high byte of sideways speed: take the largest step.
SETD.0 DriftLow
LDA.0
SETD.1 MulA
STA.1
SETD.0 DriftLeftward
LDA.0
SETD.1 AcrossWasLeft
STA.1 ; Which way it is going, before the next magnitude overwrites it.
SETD.0 SpeedDown
CALL magnitude
SETD.0 DriftHigh
LDA.0
BNA exchangeQuick
SETD.0 DriftLow
LDA.0
SETD.1 MulB
STA.1
CALL mul8
; ---- Half the product ----
;
; The product reaches 65,025 and the accumulator is a byte, so what is wanted is a window
; into the middle of it. The high half alone was tried first and it was both too weak and
; too coarse: a lander at 80 sideways falling at 2 has a product of 160, whose high half is
; nought, so the trade did not happen at all until the fall was already fast. A dead patch
; right where the turn is supposed to begin.
;
; Half keeps the low bits, so the trade starts as soon as there is any fall at all, and it
; is eight times stronger besides. That is what closes the loop inside the height of the
; screen rather than somewhere off the top of it: the whole sky here is about 145 pixels
; between the ground and the ceiling, and a quarter - tried in between - still ran the
; lander into the roof before the turn came round.
SETD.0 MulHigh
LDA.0
INIB 0d02
CCF
SUB
BNC exchangeQuick ; 512 or more, which saturates the step whatever the low half.
RSTB
SHL
SHL
SHL
SHL
SHL
SHL
SHL ; Times a hundred and twenty eight, which comes out in A.
SETD.1 ExchangeStep
STA.1
SETD.0 MulLow
LDA.0
RSTB
SHR ; And the low half halved, which is the rest of the window.
LDB.1 ; DP1 still names the step, from the store just above.
CCF
ADD ; At most 128 plus 127, so this cannot carry.
MVQA
BRI exchangeAdd
exchangeQuick:
INIA 0xFF
exchangeAdd:
SETD.1 ExchangeAt
LDB.1
CCF
ADD
STQ.1
BNC exchangeDone ; No carry, so there is nothing to trade this tick.
; ---- Which way the step goes ----
;
; Falling grows the sideways speed and climbing shrinks it, which is a step AWAY from nought
; or TOWARDS it depending on which way the lander is already going. Both signs are the top
; bit a magnitude left behind, so the exclusive or of them is the whole decision: the same
; means grow, different means shrink.
SETD.0 DriftLeftward
LDA.0
SETD.1 AcrossWasLeft
LDB.1
XOR
BNQ exchangeSlower
SETD.0 SpeedAcross
SETD.1 StepUp
CALL addWord
RET
exchangeSlower:
SETD.0 SpeedAcross
SETD.1 StepDown
CALL addWord
exchangeDone:
RET
; One sideways, towards standing still, whichever way it is going.
spendAcross:
SETD.0 SpeedAcross
CALL magnitude
SETD.0 DriftLeftward
LDA.0
BNA spendAcrossLeft
SETD.0 SpeedAcross
SETD.1 StepDown
CALL addWord
RET
spendAcrossLeft:
SETD.0 SpeedAcross
SETD.1 StepUp
CALL addWord
RET
; ---- One unit, if there is one ----
;
; Q comes back nought when the tank is empty, and the thruster that asked does not fire. There
@@ -888,6 +1073,20 @@ moveAdrift:
SETD.0 SpeedDownHigh
STA.0
; ---- And the sideways speed that bought the climb ----
;
; Without this the ceiling was a trap with no way out. A lander held here has its climb
; wiped every time, so the exchange below sees no fall and no climb, trades nothing, and the
; sideways speed that is pushing it up NEVER CHANGES: above orbital speed the swing pushes
; up, the pin wipes it, and round again for ever. Measured: pinned at the top with 117
; sideways, unmoving, for the whole of a four minute flight.
;
; So the pin spends one sideways as well, which is only reached on the ticks the lander is
; actually trying to climb - about one frame in ten. Six seconds of scraping along the roof
; brings it back under orbital speed and it falls away on its own. Pushing against the top
; of the sky costs the speed that got you there.
CALL spendAcross
moveAdriftSaid:
; Said once rather than sixty times a second.
SETD.0 Adrift
@@ -1816,6 +2015,28 @@ AtBase:
; of it is a tick of gravity that never happened.
OrbitAt:
0x00
; How hard the swing is pulling or pushing this tick, and which way. And one step upwards,
; which is the only thing here that gravity did not already need.
OrbitStep:
0x00
Outward:
0x00
Lift:
0xFF 0xFF
; Where the height-for-speed trade has got to, and which way the lander was going when the
; product was worked out. One step of sideways speed, either way.
ExchangeAt:
0x00
ExchangeStep:
0x00
AcrossWasLeft:
0x00
StepUp:
0x01 0x00
StepDown:
0xFF 0xFF
SayAt:
0x00
@@ -1862,3 +2083,5 @@ LanderArt:
LanderArtAt:
#Reserve 0d2
#Include math.asm