--- title: "Star Lander" id: 57520 type: "computer_media" slug: "star-lander" url: "http://localhost/computer_media/star-lander/" markdown_url: "http://localhost/computer_media/star-lander.md" published_at: "2024-10-05T21:23:48+00:00" modified_at: "2026-03-30T21:17:29+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/275_SL.png" excerpt: "Guide a lunar lander to a safe touchdown by balancing thrust, fuel, and velocity in this inverse-video ZX81 lander game with a blinking prompt." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56737 title: "Timex Sinclair Public Domain Library Tape 1006" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1006/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/275_SL.png" media_type_tags: "Game, Software" --- This is a lunar lander simulation game in which the player must guide a spacecraft to a safe touchdown by managing thrust, fuel, and vertical velocity. Each game round randomly initialises fuel (100–400 units), velocity (1–150), and altitude (500 units). The player enters a thrust value each turn; velocity changes by 5 minus thrust, altitude decreases by the new velocity, and fuel is consumed by the absolute thrust value. A safe landing requires vertical velocity of 10 or less on touchdown; excess fuel remaining is added to the score. The subroutine at line 275 implements a crude delay loop with a flashing “INPUT THRUST” prompt rendered in three alternating states using inverse-video characters. *** ## Program Analysis ### Program Structure The program is organised into a main game loop and several subroutines: 1. **Initialisation (lines 5–40):** Calls the screen-fill subroutine at 211, then sets up game variables: column `K=5`, fuel `F` (100–400), velocity `V` (1–150), and altitude `H=500`. 2. **Display loop (lines 50–105):** Draws the ground line, status bar, border frame, terrain, and lander sprite, then calls the blinking prompt subroutine. 3. **Game logic (lines 110–150):** Reads thrust `T`, updates velocity and altitude, deducts fuel, checks termination conditions. 4. **End states (lines 160–200):** Prints either a “LANDED” score or “CRASHED” message, pauses, and restarts. 5. **Screen fill subroutine (lines 211–235):** Fills all 512 character cells with inverse-video space pairs to create a starfield background. 6. **Star-twinkle subroutine (lines 240–270):** Scatters two random inverse dots on the upper half of the screen each frame. 7. **Blinking prompt subroutine (lines 275–325):** Cycles “INPUT THRUST” through inverse, normal, and blank forms using a delay loop, then falls through to `INPUT T` at line 110. 8. **Delay subroutine (lines 335–350):** A tight loop that counts to 2 before returning, providing a minimal timing pause. 9. **Save block (lines 360–380):**`CLEAR` followed by `SAVE` and `RUN`, used to store the program. ### Game Mechanics Each turn the player supplies a thrust value `T`. The physics update is: - `V = V + 5 - T` — gravity adds 5 per turn; thrust subtracts. - `H = H - V` — altitude decreases by current velocity. - `F = F - ABS(T)` — fuel consumed equals absolute thrust. The landing row is computed as `(600-H)/50`, mapping altitude 0–500 to screen rows 2–12. The terrain row uses the same formula scaled from `Z` (the previous altitude), producing a brief trace of where the lander was. The score on safe landing is `F - V`, rewarding both fuel conservation and a gentle touchdown. ### Display Techniques The starfield background is created at startup by printing 512 inverse-space characters (the `%` sequence) in a nested loop (lines 215–235). This runs in `FAST` mode for speed. The `SLOW` command at line 68 re-enables the display driver for the animated portion. The lander sprite at line 90 is `%<\..%>`, a three-character combination of inverse angle-brackets and a block graphic, giving a simple capsule silhouette. The ground line at line 50 uses a row of `\..\..` lower-half block graphics to simulate lunar terrain. The blinking prompt at lines 280–310 prints “INPUT THRUST” in three alternating styles — inverse video, normal text, and a blank — cycling four times before accepting input, creating a flashing effect without any timer hardware. ### Notable Techniques - **Altitude-to-row mapping:** The expression `(600-H)/50` converts altitude linearly to a screen row. At `H=500` the lander appears near the top (row 2); at `H≈0` it sits near row 12, just above the status bar. - **Lateral drift:**`K = K + RND` at line 80 slowly drifts the lander’s column position rightward each frame, adding a cosmetic horizontal motion element. - **Dual-call twinkle:** Subroutine 240 is called once via `GOSUB 240` at line 115 and is shared with the star-fill loop exit (line 270 `RETURN`), placing two random star dots per frame. - **Minimal delay loop:** Lines 335–350 count `T` to 2 before returning; at ZX81 speed this provides a short, roughly consistent pause between prompt flash states. - **Prompt-flow re-entry:** After four flash cycles, line 320 jumps to line 110 (`INPUT T`) rather than falling through, so the blinking subroutine at 275 never issues `INPUT` itself — the main loop owns that statement. ### Bugs and Anomalies - **Variable collision in delay loop:** The delay subroutine at lines 335–350 reuses `T` as its counter variable. Since `T` holds the last thrust input, calling this subroutine after line 110 overwrites it before it is used in the physics at line 120. On the first call from line 115 this is harmless (thrust has not yet been entered), but the structure is fragile. - **Score can go negative:** The landing score `F - V` at line 170 is not clamped; a very slow, fuel-heavy approach can yield a negative displayed score. - **No input validation:**`INPUT T` does not constrain thrust to a sensible range, so a large positive or negative value can teleport the lander or make velocity deeply negative (rising indefinitely). - **Lander can leave the screen:** If `K` drifts past column 29 the `PRINT AT` at line 90 will wrap or cause an error, since the sprite is three characters wide. - **Fuel check uses `F<1` not `F<=0`:** Because thrust is integer but fuel is not validated to remain non-negative, the condition `F<1` (line 145) triggers the crash branch even when exactly 0 fuel remains on the final burn, which is the intended behaviour but slightly unintuitive. ### Variable Summary | Variable | Role | | --- | --- | | `K` | Lander column (drifts right each turn) | | `F` | Fuel remaining | | `V` | Vertical velocity (descent rate) | | `H` | Altitude (counts down to 0) | | `Z` | Previous altitude (for terrain ghost) | | `T` | Player thrust input / delay counter | | `A`, `B` | Loop counters for starfield fill | | `P` | Flash-cycle counter in prompt subroutine | ## Source Code ``` 1 REM % %S%T%A%R% %L%A%N%D%E%R% 5 GOSUB 211 10 LET K=5 20 LET F=100+INT (RND*300)+1 25 LET V=INT (RND*150)+1 30 LET H=500 40 LET Z=H 50 PRINT AT 13,9;"\..\..\..\..\..\..\..\..\..\..\..\..\..\.." 60 PRINT AT 16,13;"F ";F;" ";TAB 13;"H ";H;" ";TAB 13;"V ";V;" " 61 PRINT AT 19,12;"% % % % % % % % " 63 PRINT AT 16,12;"% ";TAB 19;"% " 64 PRINT AT 17,12;"% ";TAB 19;"% " 65 PRINT AT 18,12;"% ";TAB 19;"% " 68 SLOW 70 PRINT AT (600-Z)/50,K;"% % % " 80 LET K=K+RND 90 PRINT AT (600-H)/50,K;"%<\..%>" 100 LET Z=H 105 GOSUB 275 110 INPUT T 115 GOSUB 240 120 LET V=V+5-T 130 LET H=H-V 140 LET F=F-ABS (T) 145 IF F<1 THEN GOTO 190 150 IF H>0 THEN GOTO 60 160 IF V>10 THEN GOTO 190 170 PRINT AT 2,8;"%L%A%N%D%E%D% ";F-V;"% %P%O%I%N%T%S% "; 180 GOTO 200 190 PRINT AT 2,6;"% %C%R%A%S%H%E%D% %A%T% ";V;"%F%E%E%T" 200 PAUSE 500 205 CLS 210 RUN 211 FAST 215 FOR A=1 TO 16 220 FOR B=1 TO 32 225 PRINT "% "; 230 NEXT B 235 NEXT A 240 PRINT AT RND*9,RND*31;"%." 246 PRINT AT RND*9,RND*31;"%." 270 RETURN 275 PRINT AT 14,10;" " 280 PRINT AT 14,10;"%I%N%P%U%T% %T%H%R%U%S%T" 285 LET P=0 290 GOSUB 335 295 PRINT AT 14,10;"INPUT THRUST" 300 GOSUB 335 305 PRINT AT 14,10;"% % % % % % % % % % % % " 310 GOSUB 335 315 LET P=P+1 320 IF P=4 THEN GOTO 110 325 GOTO 295 335 LET T=0 340 LET T=T+1 345 IF T=2 THEN RETURN 350 GOTO 340 360 CLEAR 370 SAVE "1027%5" 380 RUN ```