Moonbase is a lunar-lander simulation in which the player guides a spacecraft to a safe touchdown on the Moon’s surface by entering thrust and drift values each turn. The program tracks velocity, fuel, height, and elapsed time, updating a text-mode display that uses block-graphic characters to draw the lunar terrain and a small lander sprite. A random landing-zone marker (variable M) is placed on the surface each game, and the player must bring the craft down within five units of it horizontally while meeting speed and altitude constraints defined in line 20. Inverse-video characters are used extensively for crash, crater, and success messages, and an infinite PRINT/GOTO loop at lines 362–363 and 402–410 locks the screen on the terminal message after each outcome.
Program Analysis
Program Structure
The program initialises variables at lines 420–510 and then jumps to the main flight loop at line 60 via GOTO 700. The flight loop (lines 50–340) processes one turn per iteration: it scales thrust input, updates velocity and height physics, draws the scene, prints the instrument panel, and solicits new A (thrust) and B (drift) values before looping back to line 50.
- Initialisation – lines 420–510: sets height
H, fuelF, timeT, lander positionZ, thrustA, driftB, landing-zone markerM, velocityV, and previous sprite positionW/X. - Physics update – lines 50–90: thrust is scaled, time advances, velocity and height are recalculated, and fuel is consumed.
- Condition check – lines 20–40 (called as a GOSUB at line 100): tests for successful landing or escape velocity.
- Display – lines 160–210: erases the old sprite, draws the new lander at the computed screen position, and renders the terrain strip.
- Instrument panel & input – lines 280–340: prints velocity, fuel, time, and height, then waits for thrust and drift inputs.
- Outcome screens – lines 350–410: separate branches for crash, successful landing, and escape velocity, each ending in an infinite loop.
Physics Model
The physics are simplified but functional. Thrust input A is first divided by 7 (line 50), then used in a cubic expression A**3 to modify velocity (line 70), producing non-linear sensitivity to large thrust values. Horizontal position H is updated by adding the current velocity plus a random perturbation (line 80). Fuel consumption (line 90) depends on both thrust magnitude ABS(A) and drift magnitude ABS(B/5) scaled by a random factor, making aggressive maneuvering costly.
Landing Condition
The subroutine starting at line 20 checks four simultaneous conditions for a successful landing:
H < 50— low enough altitudeV < 20— downward velocity not excessiveV > -15— not moving upward too fastABS(Z-M) < 5— horizontal position within 5 units of the random landing markerM
If H > 1750 (line 30), the craft has reached escape velocity and branches to line 400. Otherwise the subroutine returns normally (line 40).
Display Techniques
The lander sprite is a four-character string printed using PRINT AT. The previous position is erased by printing spaces at the stored coordinates W,X before drawing the new position (lines 160–190). Screen row is derived from 16-U where U=H/100, mapping height to a row index.
The lunar terrain at line 210 is a single long PRINT AT 16,0 statement containing a dense sequence of block-graphic escape sequences (\.:, \::, \'', etc.). A TO M-1 substring expression trims the string to end just before the landing-zone marker column, providing a visual gap at the target.
Key Variables
| Variable | Role |
|---|---|
H | Height (initialised at 1450) |
V | Vertical velocity |
F | Fuel remaining |
T | Elapsed time |
A | Thrust input (player-supplied each turn) |
B | Drift input (player-supplied each turn) |
Z | Horizontal screen position of lander |
M | Random landing-zone column marker |
W,X | Previous sprite row and column for erase |
U | Derived screen row (H/100) |
Notable Techniques and Idioms
- Absolute-value input guard – line 302 converts any negative thrust input to positive with
LET A=A*-1, preventing the player from exploiting negative thrust. - Delay loops – lines 332–333 and 352–353 use
FOR/NEXTloops with no body as busy-wait delays, giving the player time to read crash or success information before the screen changes. - Infinite outcome loops – lines 362–363 and 402–410 use
PRINTfollowed byGOTOback to the samePRINTline, continuously scrolling the terminal message to fill the screen and prevent further input. - Substring for terrain – the
( TO M-1)slice on the terrain string at line 210 is an elegant way to create a variable-width gap at the landing-zone position without conditional branching. - Landing rating formula – line 380 computes a score as
100*(30-INT ABS V)+INT V, rewarding a slow touchdown with a higher rating.
Bugs and Anomalies
- Lines 140 and 150 are absent from the listing, suggesting they were deleted during revision; the jump from line 130 to 160 is harmless but leaves a visible gap.
- The
GOSUB 20at line 100 calls code that begins with anIFat line 20; if neither condition triggers, execution falls through to line 30, then 40 (RETURN). This works correctly but relies on the fall-through behaviour rather than an explicit jump. - Lines 710–740 (
STOP,CLEAR,SAVE,RUN) are never reachable during normal play because all outcome branches enter infinite loops; they appear to be housekeeping lines intended to be run manually from the editor. - The escape-velocity branch (line 400) prints a message and then falls into the infinite loop at lines 402–410 via natural fall-through, which is intentional but unconventional.
Content
Source Code
0 REM "MOONBASE" BY TIM HARTNELL REVISIONS BY TONY WILLING
5 CLS
10 GOTO 420
20 IF H<50 AND V<20 AND V>-15 AND ABS (Z-M)<5 THEN GOTO 370
30 IF H>1750 THEN GOTO 400
40 RETURN
50 LET A=A/7
60 LET T=T+4+INT (RND*2+1)
70 LET V=V+A**3-12-3*RND
80 LET H=H+V-20+10*RND
90 LET F=F-(ABS (A)+ABS (B/5)*6*RND)
100 GOSUB 20
110 IF H<20 OR F<5 THEN GOTO 350
120 LET U=H/100
130 LET Z=Z+B/2+2-RND*3
160 PRINT AT W,X;" "
170 PRINT AT 16-U,Z+1;"\ .\''\. "
180 LET W=16-U
190 LET X=Z+1
210 PRINT AT 16,0;"\..\;;\!!\. \.'\.'\'.\..% \:'\:.\.:\:'\:'\.'\':\!!\;;\:.\.:\.:"( TO M-1);"\.'\..\,,\..\'."
280 PRINT AT 17,0;"VEL: ";INT V;" ","FUEL: ";INT F;" ","TIME: ";INT T;" ","HEIGHT: ";INT H;" "
290 PRINT "THRUST? ";
300 INPUT A
302 IF A<0 THEN LET A=A*-1
310 PRINT A;" ","DRIFT? ";
320 INPUT B
330 PRINT B
332 FOR K=1 TO 85
333 NEXT K
335 PRINT AT 19,23;" "
340 GOTO 50
350 PRINT "%C%R%A%S%H\ '\ '%S%P%E%E%D ";ABS V," ";
352 FOR K=1 TO 90
353 NEXT K
354 CLS
360 PRINT "%A% %C%R%A%T%E%R% ";INT (ABS V*(RND+1));"% %F%E%E%T% %D%E%E%P% %W%I%L%L% %B%E% % %N%A%M%E%D% %I%N% %Y%O%U%R% %H%O%N%O%R% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
361 PRINT "%T%H%E% %N%E%X%T%-%O%F%-%K%I%N% %W%I%L%L% %B%E% %N%O%T%I%F%I%E%D"
362 PRINT " "
363 GOTO 362
380 PRINT "%S%U%C%C%E%S%S%F%U%L% %L%A%N%D%I%N%G\@@%R%A%T%I%N%G ";100*(30-INT ABS V)+INT V;"\##";
390 GOTO 402
400 PRINT "%Y%O%U% %H%A%V%E% %R%E%A%C%H%E%D% %E%S%C%A%P%E% %V%E%L%O%C%I%T%Y"
402 PRINT " "
410 GOTO 402
420 LET H=1450
430 LET F=827+50*RND
440 LET T=0
450 LET Z=15*RND
460 LET A=1
470 LET B=0
480 LET M=19*RND
490 LET V=0
500 LET W=0
510 LET X=0
700 GOTO 60
710 STOP
720 CLEAR
730 SAVE "1020%1"
740 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
