Z88 Lander - Final Version

This is my final version of the Z88 lander, version 28g. I have completely restructured the code so that there are no GOTO or GOSUB statements, it now relies heavily on PROCedures. I added a couple of 'tape' displays to show the Altitude when in final descent mode (below 75 metres) and a Vertical Speed Indicator (between 0 and -15 metres/second) to the right of the main numbers. These are a very crude representation of the instruments available on the LEM.

I found a couple of last minute bugs which I have corrected, and as recommended I have added both some brief instructions and a handy key reference (that can be accessed in-flight using the 'K' key).

This will be the final version because I've hit the limit of BASIC memory on the Z88 (40K I believe) - presumably because I've added fairly extensive comments and instructions/help which cannot be tokenised. I was going to add a second part where you attempt to catch up and dock with the command module but it would be too much like hard work to squeeze the code in the remaining space.

The source is shown below and can be found here:

LANDER28G.BAS

and the help page can be found here:

LANDER28G.TXT

I've very much enjoyed developing the simulation. In my final retrochallenge entries I'll be drawing some comparisons between the simulation and the reality of the lunar descent.

Enjoy!

100 REM LUNAR LANDER, by Mark Wickens
 110 REM developed for Summer 2010 Retrochallenge
 120 REM V28D, 28-JUL-2010
 140 LANDED=0: REM 1 when down
 150 RESET=0
 160 ST%=0: REM Step count
 170 TS=100: REM length of loop x 10ms
 180 PROC_SPLASH
 190 PROC_INITIAL
 200 PROC_SIMLOOP
 210 END
 220 DEF PROC_SIMLOOP: REM --- Main loop
 230 CLS
 240 REPEAT
 250   PROC_DISPLAY
 260   PROC_GETKEY
 270   PROC_UPDSIM
 280   PROC_INPUT
 290   PROC_TESTLAND
 300   PROC_DELAY
 310   IF RESET=1 THEN PROC_RESET
 320   ST%=ST%+1
 330 UNTIL LANDED=1
 340 ENDPROC
 350 DEF PROC_INITIAL: REM --- set initial simulation conditions
 360 VSI=0: REM Vertical Speed Indicator Position
 370 PVSI=0: REM Previous VSI Indicator position
 380 ALT=0: REM Altitude indicator
 390 PALT=0: REM Previous altitude indicator
 400 HPI=0: REM Horizontal position indicator
 410 LA=60: REM Lander angle (0=vertical)
 420 BR=0: REM Burn rate/%
 430 F=25000: REM Total fuel/kg
 440 X=-30000: REM Range to landing site
 450 Y=10000: REM Initial height/metres
 460 DX=500: REM Initial horizontal velocity/ms
 470 DY=0: REM Initial vertical velocity/ms
 480 G=10/3: REM Gravity, metres/second
 490 VT=0: REM Vertical thrust component
 500 HT=0: REM Horizontal thrust component
 510 ENDPROC
 520 DEF PROC_DISPLAY: REM --- Update display
 530 PROC_NAVDISPLAY
 540 PROC_TENW2DP
 550 PRINT TAB(1,0) "F=" F
 560 PRINT TAB(15,0) "X=" X
 570 PRINT TAB(29,0) "Y=" Y
 580 PRINT TAB(0,1) "DX=" DX
 590 PRINT TAB(14,1) "DY=" DY
 600 PRINT TAB(28,1) "BR=" BR
 610 PRINT TAB(0,2) "LA=" LA
 620 PRINT TAB(14,2) "VT=" VT
 630 PRINT TAB(28,2) "HT=" HT
 640 IF F<3000 AND ST% MOD 2=0 THEN PRINT TAB(0,3) "FUEL" ELSE PRINT TAB(0,3) "   "
 650 IF DY>0 THEN PRINT TAB(5,3) "ASC" ELSE PRINT TAB(5,3) "   "
 660 IF Y<1000 THEN PRINT TAB(9,3) "RADAR"
 670 IF Y<3 THEN PRINT TAB(9,3) "CONTACT" ELSE IF Y>1000 PRINT TAB(9,3) "      "
 680 IF BR=0 AND F=0 THEN PRINT TAB(17,3) "ENGINE"
 690 IF X>=-500 AND X<=500 THEN PRINT TAB(24,3) "RANGE" ELSE PRINT TAB(24,3) "    "
 700 PROC_VSI: REM Update the vertical speed indicator
 710 PROC_ALT: REM Update the altitude indicator
 720 ENDPROC
 730 DEF PROC_VSI: REM --- Update the vertical speed indicator
 740 VSI=(0-DY)*6/15
 750 PROC_UPDTAPE(59,VSI,PVSI)
 760 PVSI=VSI
 770 IF PVSI<0 THEN PVSI=0
 780 IF PVSI>6 THEN PVSI=6
 790 ENDPROC
 800 DEF PROC_ALT: REM --- Update the altitude indicator
 810 IF Y>75 THEN ALT=-1 ELSE ALT=6-(Y/75*6)
 820 PROC_UPDTAPE(50,ALT,PALT)
 830 PALT=ALT
 840 IF PALT<0 THEN PALT=0
 850 IF PALT>6 THEN PALT=6
 860 ENDPROC
 870 DEF PROC_UPDTAPE(COL,CURR,PREV): REM -- Update tape display
 880 PRINT TAB(COL,PREV) " ": REM clear previous indicator position
 890 IF CURR<0 THEN PRINT TAB(COL,0) "^"
 900 IF CURR>6 THEN PRINT TAB(COL,6) "V"
 910 IF CURR>=0 AND CURR<=6 THEN PRINT TAB(COL,CURR) ">"
 920 ENDPROC
 930 DEF PROC_UPDSIM: REM --- Update simulation parameters
 940 HT=LA/90*BR/10: REM horizontal component of lander angle multiplied by burn rate
 950 VT=(1-(ABS(LA)/90))*BR/10
 960 DY=DY-G+VT: REM Update vertical speed with effects of gravity and vertical thrust
 970 Y=Y+DY
 980 DX=DX-HT
 990 X = X + DX
1000 IF F-BR<0 THEN BR=F
1010 IF F>0 THEN F=F-BR
1020 IF Y<0 THEN Y=0
1030 ENDPROC
1040 DEF PROC_INPUT: REM --- Process keyboard input
1050 IF C$="]" AND BR<100 THEN BR=BR+10
1060 IF C$="[" AND BR>0 THEN BR=BR-10
1070 IF C$="-" AND LA>-60 THEN LA=LA-5
1080 IF C$="=" AND LA<60 THEN LA=LA+5
1090 IF C$="R" THEN RESET=1
1100 IF C$="I" THEN PROC_INSTRUCTIONS
1110 IF C$="'" AND BR>=2 THEN BR=BR-2
1120 IF C$="£" AND BR<=98 THEN BR=BR+2
1130 IF C$="V" THEN LA=0
1140 IF C$="C" THEN LA=-60
1150 IF C$="B" THEN LA=60
1160 IF C$="1" THEN BR=20
1170 IF C$="2" THEN BR=40
1180 IF C$="3" THEN BR=60
1190 IF C$="4" THEN BR=80
1200 IF C$="5" THEN BR=100
1210 IF C$="0" THEN BR=0
1220 IF C$="P" THEN PROC_PAUSE
1230 IF C$="I" THEN PROC_INSTR
1240 IF C$="K" THEN PROC_KEYS
1250 ENDPROC
1260 DEF PROC_TESTLAND: REM --- Test for landed and engine off
1270 IF Y<=0 AND BR=0 THEN LANDED=1: PROC_LANDED
1280 ENDPROC
1290 DEF PROC_LANDED: REM --- Determine state of landing and score
1300 IF DX<0 THEN DX=-DX
1310 IF X<0 THEN X=-X
1320 PROC_DISPLAY: REM Update display for final position
1330 IF DX<=6 AND DY>=-6 THEN PRINT TAB(0,4) "You have landed successfully!"
1340 IF DX<6 AND DY<-3 AND DY>-6 THEN PRINT TAB(0,4) "You have landed with a bounce!"
1350 IF DY<-6 OR DX>6 THEN PRINT TAB(0,4) "You have CRASHED!"
1360 @%=&00000000
1370 IF X>500 THEN PRINT X " metres from the landing site"
1380 IF DY<-6.0 THEN PRINT "You left a crater " (ABS(DY)*2.5) " metres deep"
1390 SCORE%=100/(ABS(DX)*ABS(DY))
1400 IF ABS(X)<500 AND ABS(DX)<6.0 AND ABS(DY)<6.0 THEN PRINT "YOUR SCORE IS: " SCORE%
1410 ENDPROC
1420 DEF PROC_DELAY: REM --- loop delay
1430 REPEAT T=TIME
1440 UNTIL T>TS
1450 ENDPROC
1460 DEF PROC_PAUSE
1470 PRINT TAB(0,4) "PAUSED - Press 'P' to continue..."
1480 REPEAT
1490   C$=INKEY$(1000)
1500 UNTIL C$="P"
1510 PRINT TAB(0,4) "                                 "
1520 ENDPROC
1530 DEF PROC_NAVDISPLAY: REM --- Static elements
1540 PRINT TAB(46,0) "ALT"
1550 PROC_TAPE(51,75,-25)
1560 PRINT TAB(55,0) "VSI"
1570 PROC_TAPE(60,0,5)
1580 ENDPROC
1590 DEF PROC_TAPE(COL,MIN,TICK)
1600 PROC_MINW0DP
1610 PRINT TAB(COL,0) "-" MIN
1620 PRINT TAB(COL,1) "."
1630 PRINT TAB(COL,2) "-" (MIN+TICK)
1640 PRINT TAB(COL,3) "."
1650 PRINT TAB(COL,4) "-" (MIN+(TICK*2))
1660 PRINT TAB(COL,5) "."
1670 PRINT TAB(COL,6) "-" (MIN+(TICK*3))
1680 ENDPROC
1690 DEF PROC_GETKEY: REM --- keyboard input
1700 C$=INKEY$(TS*0.9)
1710 ENDPROC
1720 DEF PROC_SPLASH
1730 REPEAT
1740   CLS
1750   PRINT "Lunar Lander, by Mark Wickens"
1760   PRINT ""
1770   PRINT "Press 'I' for instructions, 'S' to start"
1780   PRINT "      'K' for keys"
1790   C$=INKEY$(5000)
1800   IF C$="I" THEN PROC_INSTR
1810   IF C$="K" THEN PROC_KEYS
1820 UNTIL C$="S"
1830 ENDPROC
1840 DEF PROC_INSTR
1850 CLS
1860 PRINT "You are the commander of the Lunar Excursion Module, your mission is to"
1870 PRINT "successfully land the LEM on the moon"
1880 PRINT ""
1890 PRINT "Your panel displays the following information:"
1900 PRINT "F: Fuel Remaining, X: Horiz. Distance down range, Y: Height"
1910 PRINT "DX: Horiz. Speed, DY: Vert. Speed, BR: Engine Burn Rate/%"
1920 PRINT "LA: LEM Attitude (0=vertical), VT/HT: Vert./Horiz. Thrust Component"
1930 PROC_ANYKEY
1940 PRINT "Slow your horiz. speed first, then land +/- 500 metres of the landing site"
1950 PRINT "with horiz. and vert. speed less than 3.0 metres/sec"
1960 PRINT ""
1970 PRINT "See the accompanying Pipedream/txt file for more information"
1980 PROC_ANYKEY
1990 ENDPROC
2000 DEF PROC_ANYKEY
2010 REPEAT
2020   C$=INKEY$(100)
2030 UNTIL C$<>""
2040 CLS
2050 ENDPROC
2060 DEF PROC_RESET: REM --- Reset the simulation
2070 RESET=0
2080 PROC_INITIAL
2090 ENDPROC
2100 DEF PROC_TENW2DP: REM --- Set number format, 10 wide, 2 decimal places
2110 @%=&0102020A
2120 ENDPROC
2130 DEF PROC_MINW0DP: REM --- Set number format, min width, no decimal places
2140 @%=&01020000
2150 ENDPROC
2160 DEF PROC_KEYS: REM -- Display valid keyboard commands
2170 CLS
2180 PRINT "Keys:"
2190 PRINT "Thrust: 1:20%, 2:40%, 3:60%, 4:80%, 5:100%, 0:Engine Cut"
2200 PRINT "        [:-10%, ]:+10%, ':-2%, ~:+2%"
2210 PRINT "Attitude: C:-60 degrees, V:vertical, B:+60 degrees"
2220 PRINT "          -:-5 degrees, +:+5 degrees"
2230 PRINT "Simulation: P:Pause, R:Restart, I:Instructions, K:Keys"
2240 PROC_ANYKEY
2250 ENDPROC