This program simulates a lunar lander descent game in which the player must manage fuel burns each second to achieve a safe touchdown velocity below 5 ft/sec. The physics model increments time in one-second steps, applying a constant 5 ft/sec gravitational acceleration and subtracting the player’s chosen burn from the descent velocity each turn. A random engine deterioration mechanic (lines 440–460) uses a deliberately odd conditional — `IF E<9 OR E>6` — which is always true, meaning the subroutine at line 700 fires every turn, steadily degrading the maximum burn limit `L`. Initial altitude, velocity, and maximum burn are all randomized at the start of each game, providing replayability. The POKE at line 30 sets system variable FLAGS2 to enable caps-lock mode, ensuring uppercase input without requiring the player to hold Shift.
Program Analysis
Program Structure
The program is organized into four logical blocks:
- Setup and instructions (lines 10–180): Displays the backstory and rules if the player requests them.
- Initialization (lines 190–330): Randomizes starting altitude, velocity, fuel, and maximum burn, then prints the instrument panel header.
- Main game loop (lines 330–540): Accepts a burn value each second, updates physics, checks for landing or crash, and loops back to line 310.
- Outcome and subroutine block (lines 540–780): Handles out-of-fuel, crash, damaged-landing, and safe-landing messages, plus the engine deterioration subroutine at lines 700–780.
Physics Model
Each iteration of the game loop represents one second of flight. The velocity update at line 420 is V=(V-5)+B, where −5 represents lunar gravity and B is the player’s burn. Height is updated at line 430 as H=H+V. Because velocity is negative (descent), gravity makes it more negative each turn while thrust counters this. The landing outcome is determined by checking whether V+100<=95 (velocity ≤ −5, safe) or V+100<=98 (velocity ≤ −2, capsule survives but is damaged).
Notable Bug: Always-True Deterioration Condition
Line 450 reads IF E<9 OR E>6 THEN GO SUB 700. The variable E is assigned RND*12, giving a value in [0, 12). The condition E<9 OR E>6 is logically equivalent to “any number that is less than 9 or greater than 6,” which covers all real numbers — so the subroutine is called unconditionally every turn. The intent was presumably to give only a partial chance of engine degradation (perhaps E<3 was intended for a 25% failure chance), but as written, the engine always deteriorates each second.
Engine Deterioration Subroutine (Lines 700–780)
The subroutine reduces the maximum burn limit L by a random amount: L=L-(RND*10)+1. If L drops to zero or below (tested with IF L+100<=100), the thrust units are declared completely failed and L is set to 0, after which the player can burn nothing. This progressive degradation is the core tension mechanic, though because the deterioration fires every turn due to the bug above, the engine degrades much faster than intended.
Key BASIC Idioms and Techniques
- Zero-or-negative test via addition:
IF B+100<=100(line 388) andIF L+100<=100(line 710) are idiomatic ways to testB<=0andL<=0without using a negative constant, avoiding parser ambiguities on some Sinclair BASIC dialects. - POKE 23658,8 (line 30): Writes to the FLAGS2 system variable to force caps-lock on, ensuring clean uppercase INPUT without user intervention.
- FLASH 1 / FLASH 0: Used extensively for dramatic emphasis on warnings and congratulations messages.
- PAUSE 60 (line 500): Introduces a one-second delay between display updates, giving the game a real-time feel tied to the 50 Hz frame rate (60 frames ≈ 1.2 seconds at 50 Hz).
- PRINT ”””’: Consecutive apostrophes after PRINT generate multiple blank lines efficiently in a single statement.
Variable Reference
| Variable | Role |
|---|---|
L | Maximum burn limit (ft/sec), degrades over time |
T | Elapsed time in seconds |
H | Current altitude in feet |
V | Current vertical velocity (negative = descending) |
F | Fuel remaining (units) |
B | Player’s chosen burn this turn |
E | Random value used (incorrectly) to trigger engine failure |
Z$ | Player’s yes/no input string |
Input Validation
Burn input validation is minimal. Line 350 clamps B to L if the player over-burns, and line 370 forces B=0 when fuel is exhausted. Line 380 clamps non-positive burn values to zero using the addition idiom. There is no explicit upper-bound check preventing the player from entering a number larger than the fuel remaining, meaning a single large burn can deplete F into negative values — line 390 performs F=F-B without clamping F at zero.
Content
Source Code
10 REM PROGRAM-LUNAR LAND
20 BORDER 3: PAPER 6: INK 9: CLS
30 POKE 23658,8
40 PRINT "DO YOU DESIRE INSTRUCTIONS? TYPE Y FOR YES, N FOR NO ."
50 INPUT Z$
60 IF Z$="N" THEN GO TO 190
70 IF Z$<>"N" THEN GO TO 80
80 REM INSTRUCTION BLOCK
90 PRINT '"WHILE FLYING ON A LOW ORBIT MAPPING MISSION OF THE MOON,YOUR"
100 PRINT "CRAFT HAS HIT A FLYING WOMBAT! (AN AVIAN MAMMAL NATIVE TO THE AREA).": PRINT
110 PRINT "YOU ARE SAFE INSIDE YOUR EJECTEDSURVIVAL CAPSULE WHEN YOU"
120 PRINT "DISCOVER THAT YOUR AUTOMATIC DESCENT COMPUTER IS JAMMED FULL OF WOMBAT FEATHERS & HAS FAILED.": PRINT
130 PRINT "YOUR MAIN THRUST UNIT IS ERRATIC& FALTERING BUT IT MAY GET YOU DOWN SAFELY YET.": PRINT
140 PRINT "TO SAVE THE CAPSULE YOU MUST LAND AT LESS THAN 2 FT/SEC.": PRINT
150 PRINT "TO SURVIVE YOU MUST LAND AT LESSTHAN 5 FT/SEC.": PRINT
160 PRINT "THE CAPSULE INSTRUMENTATION IS FUNCTIONING AND WILL TELL YOU WHERE YOU ARE.": PRINT
170 PRINT "REMEMBER, GRAVITY WILL ADD 5 FT/SEC. TO YOUR DESCENT.": PRINT
180 PRINT '"GOOD LUCK AND HAPPY LANDINGS"
190 REM L=LIMIT OF BURN
200 LET L=RND*10+25
210 PRINT
220 PRINT "YOUR ENGINES ARE CAPABLE OF A MAXIMUM BURN OF ";L;"FT/SEC.": PRINT
230 REM INITIALIZE DATA; T=TIME,H=HEIGHT,V=VELOCITY,F=FUEL LEFT
240 LET T=1
250 LET V=(RND*75)-75
260 LET H=(RND*300)+200
270 LET F=120
280 PRINT
290 FLASH 1: PRINT " MANUAL DESCENT MODE ENGAGED ": FLASH 0
300 PRINT
310 PRINT "TIME ALT. VELOCITY FUEL "
320 PRINT "SEC. (FEET) (FT/SEC) LEFT"
330 PRINT " ";TAB 1;T;TAB 5;H;TAB 16;V;TAB 28;F; : PRINT '
340 INPUT B
350 IF B>L THEN LET B=L
360 REM L=LIMIT OF BURN
370 IF F<=0 THEN LET B=0
380 IF B+100<=100 THEN LET B=0
390 LET F=F-B
400 REM B=BURN
410 LET T=T+1
420 LET V=(V-5)+B
430 LET H=H+V
440 LET E=RND*12
450 IF E<9 OR E>6 THEN GO SUB 700
460 REM VARIABLE "E" DETERMINES THRUST FAILURE
470 IF F<=0 THEN GO TO 550
480 IF H<=0 THEN IF V+100<=95 THEN GO TO 610
490 IF H<=0 THEN IF V+100<=98 THEN GO TO 580
500 PAUSE 60: PRINT '''''''': IF H>0 THEN GO TO 310
510 PRINT " YOU HAVE LANDED SAFELY": PRINT '''': FLASH 1: PRINT " CONGRATULATIONS! ": FLASH 0: PRINT ''''
520 PRINT "YOUR VELOCITY AT TOUCHDOWN WAS ";V;" FT/SEC."
530 PRINT "WITH ";F;" UNITS OF FUEL REMAINING"
540 GO TO 640
550 FLASH 1: PRINT "!!!OUT OF FUEL!!!": FLASH 0
560 IF H>0 THEN GO TO 330
570 GO TO 610
580 PRINT "YOU HAVE MADE A CONTROLLED CRASH AND YOU ARE ALIVE!"
590 PRINT " HOWEVER THE LANDER IS DAMAGED AND YOU ARE STRANDED!": PRINT '''
600 GO TO 520
610 FLASH 1: PAUSE 3: FLASH 0: PRINT "CRUNCH! YOU HAVE JUST BECOME THEMOON'S NEWEST CRATER!"
620 PRINT "YOUR FLIGHT PAY WILL BE FORWARDED TO YOUR WIDOW.": PRINT
630 GO TO 520
640 PRINT
650 PRINT "LIKE TO TRY AGAIN,ACE? (Y/N) "
660 INPUT Z$
670 IF Z$="Y" THEN GO TO 190
680 IF Z$<>"Y" THEN STOP
690 REM DERIVE LEVEL OF THRUST FAILURE
700 LET L=L-(RND*10)+1
710 IF L+100<=100 THEN GO TO 760
720 PRINT
730 FLASH 1: PRINT TAB 8;"DETERIORATION",: FLASH 0: PRINT " IN MAIN THRUST UNIT": PRINT
740 PRINT "YOUR MAX. BURN IS NOW",L;"FT/SEC.": PRINT
750 RETURN
760 PRINT : PRINT " YOUR THRUST UNITS HAVE ": FLASH 1: PRINT TAB 8;"FAILED COMPLETELY ": FLASH 0: PRINT
770 LET L=0
780 RETURN
790 SAVE "LUNAR LAND" LINE 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
