Landing pads, carved rather than looked for
A random walk does not leave flat ground and a lander wants some. Four pads are cut into the moon after it is generated, each four columns levelled to whatever height its first column happened to have - so they sit in the landscape rather than on a shelf above it. The moon decides where they are; this only decides that they are flat. Searching for flat spots was the alternative and it can fail, which means a fallback that carves anyway - the carving, plus a search nobody needed. They are marked by an ATTRIBUTE and not a tile of their own, which costs no art at all: a nibble is added to every index in a tile, so one solid block is grey moon or a cyan pad depending on the byte beside it. Which columns are pads is an array, because asking has to be one lookup. Four comparisons per column per row is 12,800 of them for one screen, and the landing verdict asks the same question again. THE LANDER STARTS ABOVE ONE, because that is where a porter's day begins. Starting in the middle of nowhere meant a straight descent landed in the middle of nowhere, which is a fine thing to be able to do and a poor thing to have to. That change cost the crash test its teeth, and the way it did is worth keeping. It held nothing at all and let the lander fall - and a short drop onto the high ground of the base you started above is survivable, which is correct, and left the test saying nothing. It holds Right now: lateral speed has no limit and nothing slows it, so a slide always ends badly however the rest is tuned. 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
6073086584
commit
7257ad369c
@@ -68,6 +68,7 @@ start:
|
||||
|
||||
CALL putTiles
|
||||
CALL makeMoon
|
||||
CALL carvePads
|
||||
CALL drawMoon
|
||||
CALL putLander
|
||||
CALL putGauge
|
||||
@@ -223,6 +224,73 @@ makeNext:
|
||||
BNQ makeColumn
|
||||
RET
|
||||
|
||||
; ---- Somewhere to put it down ----
|
||||
;
|
||||
; A random walk does not leave flat ground, and a lander wants some. So four pads are CARVED
|
||||
; after the moon is made rather than looked for in it: searching can fail, and a fallback that
|
||||
; carves anyway is the carving plus a search nobody needed.
|
||||
;
|
||||
; Each is four columns levelled to the height the first of them happened to have, so the pads
|
||||
; sit in the landscape rather than on a shelf above it - the moon decides where they are, and
|
||||
; this only decides that they are flat.
|
||||
;
|
||||
; The columns are marked in an array of their own. Asking "is this a pad" while drawing has to
|
||||
; be one lookup: four comparisons per column per row is 12,800 of them for a screen.
|
||||
carvePads:
|
||||
SETD.3 PadTable
|
||||
INIA 0d4
|
||||
SETD.1 PadsLeft
|
||||
STA.1
|
||||
|
||||
carveOne:
|
||||
; The height this pad is levelled to, which is whatever its first column already was.
|
||||
LDA.3
|
||||
SETD.1 Terrain
|
||||
DPUA.1
|
||||
LDA.1
|
||||
SETD.1 PadHeight
|
||||
STA.1
|
||||
|
||||
RSTA
|
||||
SETD.1 PadWide
|
||||
STA.1
|
||||
carveColumn:
|
||||
; This column of the pad: levelled, and marked as somewhere to land.
|
||||
LDA.3
|
||||
SETD.1 PadWide
|
||||
LDB.1
|
||||
CCF
|
||||
ADD
|
||||
MVQA ; The pad's first column plus how far along this is.
|
||||
PSHA
|
||||
SETD.1 Terrain
|
||||
DPUA.1
|
||||
SETD.0 PadHeight
|
||||
LDA.0
|
||||
STA.1
|
||||
POPA
|
||||
SETD.1 IsPad
|
||||
DPUA.1
|
||||
INIA 0x01
|
||||
STA.1
|
||||
|
||||
SETD.1 PadWide
|
||||
LDA.1
|
||||
INCA
|
||||
STA.1
|
||||
INIB 0d4
|
||||
CCF
|
||||
SUB
|
||||
BNQ carveColumn
|
||||
|
||||
INCD.3
|
||||
SETD.1 PadsLeft
|
||||
LDA.1
|
||||
DECA
|
||||
STA.1
|
||||
BNA carveOne
|
||||
RET
|
||||
|
||||
; The shift register. Q comes back the new value, because Q is what survives a RET.
|
||||
nextRandom:
|
||||
SETD.1 Seed
|
||||
@@ -284,11 +352,31 @@ drawCell:
|
||||
CCF
|
||||
SUB
|
||||
BRC drawSky ; Borrowed: this row is above the surface, so it is sky.
|
||||
BRQ drawSurface ; Equal: this row IS the surface, which may be somewhere to land.
|
||||
drawGround:
|
||||
INIA 0xC8
|
||||
OUTA 0xE9 ; Tile 200, the ground block.
|
||||
RSTA
|
||||
OUTA 0xE9 ; Attribute nought: grey on black, which is a fine moon.
|
||||
BRI drawNextCell
|
||||
|
||||
; ---- The top of a pad, in a colour that says so ----
|
||||
;
|
||||
; The same solid tile in a different scheme, which costs no art at all: an attribute is a
|
||||
; nibble added to every index in the tile, so one block is a grey moon and a cyan landing pad
|
||||
; depending on the byte beside it.
|
||||
drawSurface:
|
||||
SETD.1 IsPad
|
||||
SETD.0 Column
|
||||
LDA.0
|
||||
DPUA.1
|
||||
LDA.1
|
||||
BRA drawGround ; Not a pad, so it is ordinary moon.
|
||||
INIA 0xC8
|
||||
OUTA 0xE9
|
||||
INIA 0x06
|
||||
OUTA 0xE9 ; Scheme six, which is cyan against everything else out there.
|
||||
BRI drawNextCell
|
||||
drawSky:
|
||||
RSTA ; A is still this column's height, from the comparison above.
|
||||
OUTA 0xE9
|
||||
@@ -850,6 +938,8 @@ touchdown:
|
||||
INIB 0x7F
|
||||
AND ; The moon is 128 columns, so seven bits of it.
|
||||
MVQA
|
||||
SETD.1 LandColumn
|
||||
STA.1 ; Kept, because the verdict below wants it too.
|
||||
SETD.1 Terrain
|
||||
DPUA.1 ; Terrain plus the column, which is the row its surface is on.
|
||||
LDA.1
|
||||
@@ -920,6 +1010,20 @@ touchdown:
|
||||
SUB
|
||||
BNC touchdownCrash
|
||||
|
||||
; ---- Down safely, and whether it was anywhere useful ----
|
||||
;
|
||||
; 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
|
||||
touchdownCrash:
|
||||
@@ -1059,10 +1163,15 @@ waitFrame:
|
||||
#Base 0x3000
|
||||
|
||||
; Sixteenths of a pixel, low half first, because that is the order the sums above walk in.
|
||||
; ---- Which is over a base, because that is where a day starts ----
|
||||
;
|
||||
; 0x14A0 sixteenths is 330 pixels, which is column 41 - inside the pad carved at 40. Starting
|
||||
; in the middle of nowhere meant a straight descent landed in the middle of nowhere, which is
|
||||
; a fine thing to be able to do and a poor thing to have to.
|
||||
AcrossLow:
|
||||
0x00
|
||||
0xA0
|
||||
AcrossHigh:
|
||||
0x0F ; Somewhere near the middle of the moon to start.
|
||||
0x14
|
||||
DownLow:
|
||||
0x00
|
||||
DownHigh:
|
||||
@@ -1173,8 +1282,27 @@ Flying:
|
||||
Terrain:
|
||||
#Reserve 0d128
|
||||
|
||||
; One byte a column: whether a lander touching down there is at a base. Written by the carving
|
||||
; and read while drawing and while landing, which is the whole reason it is an array rather
|
||||
; than four comparisons done again every time somebody asks.
|
||||
IsPad:
|
||||
#Reserve 0d128
|
||||
|
||||
PadTable:
|
||||
0d8 0d40 0d72 0d104 ; Four bases, evenly round a moon 128 columns about.
|
||||
PadsLeft:
|
||||
0x00
|
||||
PadWide:
|
||||
0x00
|
||||
PadHeight:
|
||||
0x00
|
||||
LandColumn:
|
||||
0x00
|
||||
|
||||
LandedText:
|
||||
"Down safely."
|
||||
"Down safely, in the middle of nowhere."
|
||||
AtBaseText:
|
||||
"Down safely at a base."
|
||||
CrashedText:
|
||||
"Crashed."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user