Cargo: bases with names, and a landing that is not an ending

Four bases, told apart by the scheme their pad is drawn in, so "the cyan
one" is a thing a person can say and a thing the machine already knows.
Yellow is missing on purpose: it is the lander, and a base the same colour
as the thing landing on it would be a poor joke.

Land empty at a base and it loads cargo for the base ACROSS THE MOON, two
along - so the pairs are cyan with red and green with blue, and the
wrapping surface is a route rather than scenery. Land carrying at the
right one and it takes the cargo and pays eighty units of fuel. Land at
the wrong one and nothing happens, which is why the destination will want
to be on the screen.

A LANDING NO LONGER ENDS THE RUN. The lander rests where it is, exactly on
the surface with both speeds zeroed, until the throttle opens again -
which is the only way to stop being landed. Gravity does not pull on
something already sitting down, and a base does not hand out cargo sixty
times a second to a lander parked on it.

The pad array holds the base's number plus one rather than a flag. Nought
still means no pad, so it is still one lookup, and a flag would have to be
followed by "and which of the four" - the same walk done twice for an
answer already in hand.

Pads are eight columns rather than four. Four was 32 pixels in a moon 1024
round, which is a target somebody flying by feel misses over and over.

WHAT IS NOT COVERED, and why: the delivery and wrong-base paths need a
lander flown from one base to another, and hand-authoring a recorded pad
input that hits an eight column pad across a 128 column moon is a piloting
exercise rather than a correctness one. Several attempts got within two
columns. Loading, crashing, landing off a pad and running dry are all
covered; delivery is built and flown by hand.

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 12:04:27 -04:00
co-authored by Claude Opus 5
parent 7257ad369c
commit bfb515e23b
14 changed files with 240 additions and 51 deletions
+221 -30
View File
@@ -271,14 +271,29 @@ carveColumn:
POPA
SETD.1 IsPad
DPUA.1
INIA 0x01
; ---- WHICH base, and not merely that there is one ----
;
; The number plus one, so nought still means no pad and the array is still one lookup. A
; flag would have to be followed by "and which of the four", which is the same walk done
; twice for an answer that was already in hand.
INIA 0d4
SETD.0 PadsLeft
LDB.0
CCF
SUB
MVQA ; Four less what is left to carve, which counts up from nought.
INCA
STA.1
SETD.1 PadWide
LDA.1
INCA
STA.1
INIB 0d4
INIB 0d8 ; ---- Eight columns, not four ----
;
; Four was 32 pixels of pad in a moon 1024 round, which is a
; target somebody flying by feel misses over and over. Eight is
; still small and is somewhere a person can aim at.
CCF
SUB
BNQ carveColumn
@@ -372,10 +387,13 @@ drawSurface:
DPUA.1
LDA.1
BRA drawGround ; Not a pad, so it is ordinary moon.
DECA ; Back to the base's own number.
SETD.1 PadColour
DPUA.1
INIA 0xC8
OUTA 0xE9
INIA 0x06
OUTA 0xE9 ; Scheme six, which is cyan against everything else out there.
OUTA 0xE9 ; The solid block again.
LDA.1
OUTA 0xE9 ; And this base's scheme, which is the whole of its name.
BRI drawNextCell
drawSky:
RSTA ; A is still this column's height, from the comparison above.
@@ -638,9 +656,14 @@ fall:
LDA.1
SETD.1 FallTick
STA.1
; Gravity does not pull on a lander that is already sitting on the ground.
SETD.0 Landed
LDA.0
BNA fallResting
SETD.0 SpeedDown
SETD.1 Gravity
CALL addWord
fallResting:
; ---- And whatever is being leaned on, on the same tick ----
;
@@ -657,6 +680,9 @@ fall:
BRQ fallNotUp
CALL takeFuel
BRQ fallNotUp ; Nothing in the tank, so nothing out of the engine.
RSTA
SETD.0 Landed
STA.0 ; Lifting off, which is the only way to stop being landed.
SETD.0 SpeedDown
SETD.1 PadUp
CALL addWord
@@ -979,6 +1005,13 @@ touchdown:
SUB
BRC touchdownDone ; Borrowed: the feet are still above the surface.
; Already sitting on it, so there is nothing new to say. Without this the arrival happens
; again every frame the lander rests, which is a base handing out cargo sixty times a
; second.
SETD.0 Landed
LDA.0
BNA touchdownDone
; ---- Arrived. Now, how ----
;
; Both speeds, and both have to be gentle. A landing that was soft downwards and sliding
@@ -1010,22 +1043,34 @@ touchdown:
SUB
BNC touchdownCrash
; ---- Down safely, and whether it was anywhere useful ----
; ---- Down safely, which is not the end of anything ----
;
; A pad is where a base is, and the rest of the moon is somewhere a lander can survive
; arriving at and do nothing about. The difference is one lookup, because the carving wrote
; an array rather than leaving four comparisons to be done again here.
SETD.1 IsPad
SETD.0 LandColumn
LDA.0
DPUA.1
LDA.1
BRA touchdownNowhere
SETD.0 AtBaseText
BRI touchdownStop
touchdownNowhere:
SETD.0 LandedText
BRI touchdownStop
; The view settles, the arrival is dealt with, and the lander sits where it is until
; somebody opens the throttle again. A landing used to stop the program, which is fine for a
; game about landing once and wrong for one about carrying things between four places.
RSTA
OUTA 0x37
OUTA 0x38
CALL arrive
CALL waitKey
; Sitting still, exactly on the surface. Both speeds go, because a lander that kept a
; hundredth of a pixel a frame would drift off its pad while nobody was looking.
RSTA
SETD.0 SpeedDown
STA.0
INCD.0
STA.0
SETD.0 SpeedAcross
STA.0
INCD.0
STA.0
CALL restOnSurface
INIA 0x01
SETD.0 Landed
STA.0
RET
touchdownCrash:
SETD.0 CrashedText
touchdownStop:
@@ -1051,19 +1096,136 @@ touchdownStop:
; The verdict was printed and the program then left immediately, taking the screen with it -
; so the one thing anybody wanted to see, the lander sitting on the ground it had just
; arrived at, was replaced by a shell prompt before it could be looked at.
touchdownWait:
INA 0x01
INIB 0x01 ; READY
AND
BRQ touchdownWait
INA 0x00
CALL waitKey
RSTA
SETD.1 Flying
STA.1 ; Which ends the loop, and the program tidies up as it always did.
touchdownDone:
RET
; A key, asked for rather than waited on, so one already pressed counts.
waitKey:
INA 0x01
INIB 0x01 ; READY
AND
BRQ waitKey
INA 0x00
RET
; ---- Put down exactly on the ground ----
;
; The feet are the top plus eight, so the top is the surface less eight - times sixteen, which
; is what the position is measured in. Three turns left of the shift register with the pixels
; in the low half, and the answer needs both halves because a screen is taller than 255
; sixteenths.
restOnSurface:
SETD.0 SurfaceAt
LDA.0
INIB 0d8
CCF
SUB
MVQB
RSTA
SHL
SHL
SHL
SHL ; Four turns, which is times sixteen.
SETD.0 DownHigh
STA.0
RSTA
CCF
ADD
MVQA
SETD.0 DownLow
STA.0
RET
; ---- What a base does when a lander arrives ----
;
; Empty and at a base: it hands over cargo for the base ACROSS THE MOON, two along, so the
; pairs are cyan with red and green with blue. Carrying and at the right base: it takes the
; cargo and pays in fuel. Carrying and at the wrong one: nothing, which is the whole reason
; the destination is on the screen.
arrive:
SETD.1 IsPad
SETD.0 LandColumn
LDA.0
DPUA.1
LDA.1
BRA arriveNowhere
DECA
SETD.1 AtBase
STA.1
SETD.0 Carrying
LDA.0
BRA arriveLoad
; Carrying something. Is this where it goes?
DECA
LDB.1 ; DP1 is still AtBase, from storing it above.
CCF
SUB
BNQ arriveWrong
RSTA
STA.0 ; And DP0 is still Carrying, from reading it.
CALL payFuel
SETD.0 DeliveredText
SWI osPrintString
BRI arriveSaid
arriveLoad:
; Two along, round a moon of four bases, which is the far side of it.
SETD.1 AtBase
LDA.1
INIB 0x02
CCF
ADD
MVQA
INIB 0x03
AND
MVQA
INCA ; Plus one, so nought can go on meaning nothing.
SETD.0 Carrying
STA.0
SETD.0 LoadedText
SWI osPrintString
BRI arriveSaid
arriveWrong:
SETD.0 WrongText
SWI osPrintString
BRI arriveSaid
arriveNowhere:
SETD.0 LandedText
SWI osPrintString
arriveSaid:
INIA 0x0A
OUTA 0x00
RET
; ---- Paid ----
;
; Eighty units, and a tank that will not take more than it holds. The carry from a byte's
; worth of adding is what says it went past, which is the same flag a sixteen bit sum uses to
; run one half into the other.
payFuel:
SETD.0 Fuel
LDA.0
INIB 0d80
CCF
ADD
BRC payFuelFull
STQ.0
RET
payFuelFull:
INIA 0xFF
STA.0
RET
; ---- Sums ----
;
; DP0 names the two byte value being changed, low half first, and DP1 the one being added to
@@ -1290,6 +1452,19 @@ IsPad:
PadTable:
0d8 0d40 0d72 0d104 ; Four bases, evenly round a moon 128 columns about.
; ---- Their names, which are colours ----
;
; A base is told from a base by the scheme its pad is drawn in, so "the cyan one" is a thing a
; person can say and a thing the machine already knows. Yellow is missing on purpose: it is
; the lander, and a base the same colour as the thing landing on it would be a poor joke.
;
; Cargo goes to the base ACROSS THE MOON, two along, so the pairs are cyan with red and green
; with blue. That is what makes the wrapping surface a route rather than scenery.
PadColour:
0d2 0d6 0d4 0d1 ; Green, cyan, blue, red.
PadNames:
0x00 ; Room kept: the messages name colours in words below.
PadsLeft:
0x00
PadWide:
@@ -1298,11 +1473,27 @@ PadHeight:
0x00
LandColumn:
0x00
AtBase:
0x00
; ---- What is aboard, and whether the feet are down ----
;
; Carrying is the destination base plus one, so nought means an empty hold and the number is
; still one byte. Landed is what stops a base handing out cargo sixty times a second while a
; lander sits on it.
Carrying:
0x00
Landed:
0x00
LandedText:
"Down safely, in the middle of nowhere."
AtBaseText:
"Down safely at a base."
"Down in the middle of nowhere. Nothing here."
LoadedText:
"Loaded. Take it to the base across the moon."
DeliveredText:
"Delivered. Eighty units of fuel."
WrongText:
"Not the base this cargo is for."
CrashedText:
"Crashed."
+1 -1
View File
@@ -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. |
| 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. |
| 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. |
+1 -1
View File
@@ -25,7 +25,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -15,7 +15,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -32,7 +32,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -22,7 +22,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -22,7 +22,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+4 -5
View File
@@ -1,8 +1,7 @@
CosmOS
> Lander
Down safely at a base.
finished
> exit
halted
Execution halted.
Loaded. Take it to the base across the moon.
Not the base this cargo is for.
Not the base this cargo is for.
Execution stopped. (cycle limit reached)
[exit 0]
+4 -5
View File
@@ -1,8 +1,7 @@
CosmOS
> Lander
Down safely at a base.
finished
> exit
halted
Execution halted.
Loaded. Take it to the base across the moon.
Not the base this cargo is for.
Not the base this cargo is for.
Execution stopped. (cycle limit reached)
[exit 0]
+1 -1
View File
@@ -108,7 +108,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -27,7 +27,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -15,7 +15,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -13,7 +13,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50
+1 -1
View File
@@ -22,7 +22,7 @@ Mode.sbx 48
Flip.sbx 173
Sprite.sbx 442
Depth.sbx 672
Lander.sbx 2108
Lander.sbx 2429
Pad.sbx 264
Crash.sbx 632
vars.script 50