Author Topic: Moon Lander by Richard Frost  (Read 475 times)

Offline Qwerkey

  • Moderator
  • Forum Resident
  • Posts: 736
Moon Lander by Richard Frost
« on: May 19, 2020, 05:16:56 AM »
Moon Lander

Author: @Richard Frost
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=1022.0
Version: May 15, 2020
Tags: [Graphics], [Skill]

Description:
Lunar Lander based on a 1974 program running on a DEC PDP/11 with GT40 vector display terminal at the University of Alberta.  Initially written in QB4.5 (hence the convoluted code to save space), upgraded to use some QB64 features.  Updated May 15, 2020 -  More effects (at warp speeds) and cookies!

Controls:
The multifarious keyboard controls are given by pressing F1 (Help) when the program is run.

Source Code:
Code: QB64: [Select]
  1. ' Moon Lander by rfrost@mail.com
  2.  
  3. $EXEICON:'.\astro.ico'
  4.  
  5. DEFINT A-Z
  6. DIM SHARED a '                                                        angle of craft
  7. DIM SHARED a51i '                                                     Area 51 initializations
  8. DIM SHARED APdisengage '                                              AutoPilot disengage
  9. DIM SHARED ASO '                                                      ascent stage only
  10. DIM SHARED auto '                                                     autopilot
  11. DIM SHARED background '                                               for instrument panel
  12. DIM SHARED bh '                                                       black hole
  13. DIM SHARED bhx, bhy '                                                 black hole
  14. DIM SHARED bbit '                                                     blinking bit synced to time
  15. DIM SHARED bolthit, bolthitf, boltx '                                 Deathstar hit vehicle, feature
  16. DIM SHARED borgl, borgr, borgt '                                      left right top, distance
  17. DIM SHARED bstyle1, bstyle2 '                                         Borg matrix/lines/Moire
  18. DIM SHARED bw '                                                       black and white
  19. DIM SHARED c '                                                        usually color
  20. DIM SHARED canvas& '                                                  primary screen
  21. DIM SHARED cbh '                                                      constant black holes
  22. DIM SHARED center '                                                   varies according to gs (graphics start)
  23. DIM SHARED chs '                                                      parachute size
  24. DIM SHARED contact '                                                  landed
  25. DIM SHARED convo '                                                    conversation active LM/CM
  26. DIM SHARED cpal '                                                     color palette, normal/green/b&w (32 color kludge/fun)
  27. DIM SHARED craft '                                                    color
  28. DIM SHARED crash '                                                    layer of debris
  29. DIM SHARED cwd, cwsi, cwsd '                                          car wash distance, angles
  30. DIM SHARED cybilltime! '                                              time on screen
  31. DIM SHARED darkstarc '                                                deathstar color set
  32. DIM SHARED darkstars '                                                deathstar spin rate
  33. DIM SHARED darkstart '                                                   "      thickness
  34. DIM SHARED dead$ '                                                    end condition
  35. DIM SHARED debug$ '                                                   messages to God
  36. DIM SHARED demo '                                                     ground features compressed
  37. DIM SHARED doclock '                                                  it's Howdy Doody time
  38. DIM SHARED dosbox '                                                   flag
  39. DIM SHARED dsinit '                                                   deathstar
  40. DIM SHARED eou '                                                      end of universe
  41. DIM SHARED fb$ '                                                      landing feedback/analysis
  42. DIM SHARED flx '                                                      US/USSR flag position
  43. DIM SHARED fuel, fuel! '                                              color of, quantity left
  44. DIM SHARED gh, glmin, glmax '                                         ground height, level
  45. DIM SHARED grav! '                                                    gravity
  46. DIM SHARED gs '                                                       flight area x start
  47. DIM SHARED gstyle '                                                   ground style
  48. DIM SHARED inpause '                                                  flag
  49. DIM SHARED invincible '                                               impervious to threats
  50. DIM SHARED iscd '                                                     don't attempt to write!
  51. DIM SHARED jitter '                                                   shift-T to control
  52. DIM SHARED LEDc '                                                     color
  53. DIM SHARED LEDtri '                                                   tri-color flag
  54. DIM SHARED level '                                                    surface is
  55. DIM SHARED LGMc '                                                     Little Green Man color
  56. DIM SHARED liftoff '                                                  AS only
  57. DIM SHARED lmsl '                                                     LM shield/laser color
  58. DIM SHARED lob '                                                      landed on Borg
  59. DIM SHARED lockfuel '                                                 cheat!
  60. DIM SHARED lp, rp, xp, th1, th2 '                                     pads, radar, thrusters
  61. DIM SHARED magic '                                                    cheat! (instant landing)
  62. DIM SHARED mdelay '                                                   PgUp/PgDn controlled
  63. DIM SHARED msflag '                                                   making surfaces
  64. DIM SHARED mstar '                                                    make stars
  65. DIM SHARED nation '                                                   1 US, 2 USSR (flags & fireworks)
  66. DIM SHARED ok '                                                       at landing, to plant flag
  67. DIM SHARED okrick '                                                   diagnostics
  68. DIM SHARED osc '                                                      on screen count
  69. DIM SHARED oscar '                                                    semaphore land/sea flags
  70. DIM SHARED panelinit '                                                replot flag
  71. DIM SHARED paraf '                                                    parachute flag
  72. DIM SHARED pload '                                                    panel load flag
  73. DIM SHARED porb '                                                     pointers/bargraphs
  74. DIM SHARED ptk '                                                      points to kill (gasoline) ExplodeLM
  75. DIM SHARED px!, py! '                                                 vehicle position on screen
  76. DIM SHARED ra '                                                       random angle
  77. DIM SHARED radarf '                                                   radar on/off
  78. DIM SHARED rads '                                                     Luna radiation
  79. DIM SHARED radiationdeath '                                           flag
  80. DIM SHARED rdtime! '                                                  fun with high res screen (my picture)
  81. DIM SHARED regen '                                                    all star files
  82. DIM SHARED rfx, rfy '                                                 craft jigger
  83. DIM SHARED rick '                                                     debug flag
  84. DIM SHARED rmin, dmin '                                               stars
  85. DIM SHARED settings$ '                                                lander.set
  86. DIM SHARED sf '                                                       surface feature
  87. DIM SHARED shield '                                                   flag
  88. DIM SHARED shoot '                                                    flag
  89. DIM SHARED showmap '                                                  locations of things shown at top
  90. DIM SHARED sia '                                                      shells in air
  91. DIM SHARED skyoff '                                                   for faster performance
  92. DIM SHARED starship '                                                 Enterprise (double shift twice)
  93. DIM SHARED ufof '                                                     for ufo
  94. DIM SHARED sspinit1, sspinit2 '                                       Surveyor
  95. DIM SHARED starfiles '                                                use stars1,2 or 3 (few/med/lots)
  96. DIM SHARED starinit '                                                 flag
  97. DIM SHARED shipi&, shipx '                                            starship
  98. DIM SHARED starstatus '                                               0 off, 1 on, 234 more info
  99. DIM SHARED suri '                                                     surface index
  100. DIM SHARED sx0, sy0 '                                                 LM radar/laser location
  101. DIM SHARED sx1, sy1 '                                                 LM left landing pad
  102. DIM SHARED sx2, sy2 '                                                 LM right landing pad
  103. DIM SHARED temp '                                                     temperature
  104. DIM SHARED thrust! '                                                  0 - 100
  105. DIM SHARED tilef '                                                    tile variation
  106. DIM SHARED vx!, vy! '                                                 LM velocity
  107. DIM SHARED warp! '                                                    vx! >= 100
  108. DIM SHARED wi, wi2 '                                                  width (distance between pads)
  109. DIM SHARED wx!, wy! '                                                 vehicle position on screen
  110. DIM SHARED x '                                                        = suri + px!
  111. DIM SHARED xoff '                                                     offset for v=5-20, Surv & Etna
  112. DIM SHARED zoom '                                                     starfield
  113.  
  114. DIM SHARED blue, green, gunmetal, red, gasoline, gray2, white, gray
  115. DIM SHARED dred, gold, black2, orange, blue2, yellow, white2
  116.  
  117. DIM SHARED q1, q2, q3, q4, h, t, th, tsix, aspect!, pf! '             constants
  118.  
  119. q1 = 6400: q2 = 860: q3 = 639: q4 = 349: h = 100: th = 200: t = 10: tsix = 360
  120. pf! = .5: aspect! = 1.4: grav! = 1.6
  121.  
  122. qt = 2000 '                                                           3 arrays below weren't loading properly with q2
  123. DIM SHARED LMx(qt), LMy(qt), LMc(qt) '                                LM+exhaust x,y,color
  124.  
  125. DIM SHARED LMrx(1400), LMry(1400) '                                   LM+exhaust x,y after rotation
  126. DIM SHARED LMoc(705), LMci(3) '                                       LM colors,original colors, index
  127. DIM SHARED c!(360), s!(360) '                                         sines and cosines
  128. DIM SHARED ex(6), ey(6), exv(6), eyv(6), ei(6), ek(6), exl(6) '       sky objects
  129. DIM SHARED f$(40) '                                                   support files
  130. DIM SHARED mes$(1), omes$(1), sm!(1) '                                messages at screen top
  131. DIM SHARED sf(10, 2), sf$(10) '                                       surface features start/end/middle
  132. DIM SHARED shx(20), shy(20), sha(20) '                                shells (IBM weapons) x,y,angle
  133. DIM SHARED shvx(20), shvy(20), shd(20) '                              velocity, distance
  134. DIM SHARED rtl!(2), rtlc(2) '                                         radiation/temperature/lightning
  135. DIM SHARED gh(6400) '                                                 ground height
  136.  
  137. DIM clocka(2) '                                                       clock angles
  138. DIM cmp&(30) '                                                        CM patterns
  139. DIM convo$(50) '                                                      LM/CM
  140. DIM SHARED gbuff(800) '                                               DS liftoff
  141. DIM skyset1(t), skyset2(t) '                                          skycrud
  142. DIM SHARED p(127, 13), p2(127, 7) '                                   vga and cga fonts
  143. DIM SHARED tflags(30)
  144.  
  145. begin:
  146. GOSUB init1
  147.     GOSUB init2
  148.     WHILE LEN(INKEY$): WEND '                                         clear keyboard buffer
  149.     DO: _LIMIT mdelay
  150.         GOSUB Autopilot
  151.         GOSUB Plotscreen
  152.         GOSUB KeyAndMouse
  153.         IF restart THEN GOTO begin '                                  restore defaults
  154.         IF warp! < 1 THEN GOSUB CheckHit
  155.     LOOP UNTIL contact OR LEN(dead$)
  156.     GOSUB CheckDead
  157.     IF contact THEN
  158.         Evaluate savea, a + ma '                                      landing feedback contact/currentø
  159.         wu2! = TIMER + 1
  160.         GOSUB pause '                                                 landed, Enter for liftoff
  161.         IF restart THEN GOTO begin '                                  restore defaults
  162.         IF k <> 60 THEN GOSUB CheckDead '                             F2 demo restart
  163.     END IF
  164.  
  165. CheckDead:
  166. z$ = LEFT$(LEFT$(dead$, 1) + " ", 1)
  167. IF INSTR(" CBE", z$) = 0 THEN '                                       not Crashed, Borg, Eaten by BH
  168.     ExplodeLM
  169.     contact = 0
  170. dead$ = ""
  171.  
  172. Autopilot:
  173. aboveborg = 0
  174. IF (ek(2) = -1) OR (ek(2) > h) THEN borgt = 0
  175. IF (skyoff = 0) AND (sy1 < borgt) AND (px! > borgl) AND (px! < borgr) THEN aboveborg = 1
  176. super = 0
  177. IF vert OR hover THEN
  178.     GOSUB GetAlt
  179.     i! = alt! / 8 + pf! '                                             thrust target
  180.     IF jitter AND (alt! < t) THEN i! = i! * 2 '                       optional, faster
  181.     IF aboveborg THEN i! = 1
  182.     GOSUB idealthrust
  183.     thrust! = sbest!
  184.     super = -(sbest! > h) '                                           add side thusters
  185.     IF thrust! > h THEN thrust! = h
  186. IF thrust! < 0 THEN thrust! = 0
  187.  
  188. CutOrOutOfFuel:
  189. IF fuel! = 0 THEN shield = 0 '                                        shields need fuel
  190. IF cut = 0 THEN
  191.     cut = 1
  192.     cvy! = vy!
  193.     ctime! = TIMER
  194.     tfollow = 0 '                                                     terrain following
  195.     thrust! = 0
  196.  
  197. idealthrust: '                                                        for hover or descend
  198. IF (alt! < pf!) AND (jitter = 0) THEN i! = .05 '                      soft landing
  199. IF hover THEN i! = hoverc '                                           target
  200. hoverc = hoverc - SGN(hoverc) '                                       up/down
  201. fmin! = q1 '                                                          conventient large number (6400)
  202. ma! = (vmass + fuel!) / th '                                          mass (actually 54% fuel)
  203. ts! = s!((a + 270) MOD tsix) / ma! / power
  204. IF jitter THEN us! = RND * t + 1 ELSE us! = .1
  205. IF powerloss THEN us! = h
  206. FOR z! = 0 TO (h + t) STEP us! '                                      find best thrust 0-110
  207.     fo! = z! * ts!
  208.     aa! = ABS(vy! + grav! + fo! - i!)
  209.     IF aa! < fmin! THEN fmin! = aa!: sbest! = z!
  210.     IF aa! > fmin! THEN EXIT FOR
  211. NEXT z!
  212.  
  213. GoSkyObject:
  214. IF (ek(p) <> -1) AND (contact = 0) THEN
  215.     auto = 0
  216.     a = -ma
  217.     wa = -ma
  218.     lock1 = 0
  219.     suri = ex(p) - center
  220.     GOSUB slimit
  221.     IF p > 2 THEN ey(p) = th '                                        BH, worm, comet, alien
  222.     px! = center
  223.     IF p = 2 THEN py! = 130 '                                         above Borg
  224.     vx! = exv(p)
  225.     eyv(p) = 0
  226.  
  227. KeyAndMouse:
  228.     lb = ABS(_MOUSEBUTTON(1))
  229.     rb = ABS(_MOUSEBUTTON(2))
  230.     IF mouseswap THEN SWAP lb, rb '                                   whatever floats your boat
  231.     IF TIMER < ignoreuntil! THEN lb = 0: rb = 0 '                     2 lines for debouncing
  232.     IF lb OR rb THEN ignoreuntil! = TIMER + .25
  233.     ww = wa '                                                         stash current wanted angle
  234.     wa = wa + lb - rb '                                               want angle
  235.     IF wa <> ww THEN '                                                if changed
  236.         IF inpause THEN i$ = CHR$(13): GOTO gotit '                   either button to cause liftoff
  237.         apd = 1 '                                                     autopilot disconnect warning
  238.         auto = 0 '                                                    autopilot
  239.         GOTO endk '                                                   don't bother checking keys
  240.     END IF
  241.     mw = mw + _MOUSEWHEEL
  242. IF mw <> 0 THEN '                                                     wheel moved
  243.     thrust! = INT(thrust!) - mw
  244.     IF thrust! < 0 THEN thrust! = 0
  245.     IF thrust! > h THEN thrust! = h
  246.     apd = 1 '                                                         autopilot disconnect warning
  247.     auto = 0 '                                                        autopilot
  248.     hover = 0 '                                                       hover off
  249.     vert = 0 '                                                        vertical control off
  250.     mw = 0 '                                                          zap
  251.     GOTO endk '                                                       don't bother checking keys
  252.  
  253. DEF SEG = 0
  254. status = PEEK(&H417) '                                                7ins 6caps 5num 4scrl 3alt 2ctrl 1ls 0rs
  255.  
  256. IF ((status AND 1) > 0) AND ((status AND 2) > 0) THEN '               both shift (cookie!)
  257.     IF rdtime! > 0 THEN starship = 1 '                                must have pressed shift-shift twice, another cookie
  258.     rdtime! = TIMER + 5 '                                             Rick display time
  259.  
  260. IF status AND 8 THEN start1! = TIMER: mpass& = 0 '                    alt, reset speed timer
  261.  
  262. IF status AND 4 THEN '                                                ctrl
  263.     i$ = RIGHT$(" " + INKEY$, 1)
  264.     kk = ASC(i$)
  265.     IF (kk = 3) OR (kk = 19) THEN '                                   c or s
  266.         nfile:
  267.         image = image + 1
  268.         f$ = "CAP" + RIGHT$("0000" + LTRIM$(STR$(image)), 3) + ".BMP"
  269.         IF _FILEEXISTS(f$) THEN GOTO nfile
  270.         SaveImage f$
  271.         IF _FILEEXISTS(f$) THEN mes$(1) = "Screen captured to " + f$
  272.         GOTO endk
  273.     END IF
  274.  
  275. i$ = INKEY$ '                                                         consult human
  276. li = LEN(i$)
  277. IF li = 0 THEN RETURN
  278.  
  279. IF i$ = "|" THEN MakeStarFiles '                                      takes hours!
  280.  
  281. k = ASC(RIGHT$(i$, 1))
  282. IF k = 27 THEN Quit
  283. IF inpause AND (k = 32) THEN
  284.     k = 13 '                                                          transform spacebar to Enter
  285.     i$ = RIGHT$(CHR$(0) + CHR$(k), li) '                              gentlemen, we can rebuild him
  286.  
  287. gotit:
  288. IF (i$ = "\") AND (shx(0) = 0) AND (contact = 0) THEN '               LM drops bomb
  289.     IF (cwd < 50) AND (sy1 > 300) THEN dead$ = "Smooth move, Exlax!" 'kill self in car wash
  290.     sia = sia + 1 '                                                   shells in air
  291.     shvx(0) = vx! + 3 + RND * t
  292.     shvy(0) = 0
  293.     shx(0) = suri + sx0
  294.     shy(0) = sy0
  295.     shd(0) = 1
  296.  
  297. IF i$ = "[" THEN bw = bw XOR 1: Setcolor '                            crude method for b&w
  298. IF i$ = "]" THEN
  299.     ufof = ufof XOR 1
  300.     mes$(0) = "UFO " + OnOff$(ufof)
  301.     IF ufof THEN
  302.         GOSUB SkyStuff
  303.         p = 6: GOSUB GoSkyObject
  304.     END IF
  305.  
  306. IF i$ = "=" THEN GOSUB lmshow '                                       show LM data - pointless but amusing
  307. IF i$ = "'" THEN pdiv = (pdiv + 1) MOD 4 '                            Henon speed, also slows down thrust display
  308. IF radiationdeath THEN i$ = "": RETURN '                              you're dead and cannot pass this point
  309.  
  310. IF i$ = "`" THEN '                                                    Deathstar size - thought a smaller one wouuld be faster - it is - not by much
  311.     dsinit = 0
  312.     dstype = 2 + (MID$(f$(37), 6, 1) = "m")
  313.     MID$(f$(37), 6, 1) = MID$("sm", dstype, 1)
  314. IF i$ = "~" THEN darkstarc = darkstarc XOR 1 '                        color
  315. IF i$ = "@" THEN darkstart = darkstart XOR 1 '                        thickness
  316.  
  317. IF inpause THEN '                                                     hit "p" or landed
  318.     IF i$ = "b" THEN '                                                Big Dipper
  319.         rmin = 9 '                                                    right ascension
  320.         dmin = 30 '                                                   declination
  321.         starinit = 0
  322.         RETURN
  323.     END IF
  324.     IF li = 2 THEN '                                                  arrow keys move stars
  325.         rdol = rmin + dmin '                                          detect change
  326.         rmin = rmin + (k = 75) - (k = 77) '                           left right
  327.         rmin = (rmin + 24) MOD 24 '                                   RA limit 0 - 24
  328.         dmin = dmin - (k = 80) * t + (k = 72) * t '                   declination up down
  329.         IF dmin = h THEN dmin = -80 '                                 limit -90 - 90
  330.         IF dmin = -h THEN dmin = 80
  331.         IF (rmin + dmin) <> rdol THEN starinit = 0 '                  changed, replot stars
  332.     END IF
  333. IF li = 2 THEN GOTO is2 '                                             extended key
  334.  
  335. IF i$ = "_" THEN '                                                    star twinkle
  336.     twinkle = twinkle XOR 1
  337.     mes$(0) = "STAR TWINKLE " + OnOff$(twinkle)
  338. IF i$ = ";" THEN fpl = 1 '                                            force power loss
  339. IF k = 9 THEN ex(1) = (suri + px!) - SGN(exv(1)) * h '                TAB summon DS
  340. p = INSTR(")!@#$%^&*(", i$)
  341. IF p AND (contact = 0) THEN GetSurface p - 1 '                        shifted-number for 1 of 10 surfaces
  342. p = INSTR("01234", i$) '                                              stars off/on/info
  343. IF p THEN starstatus = p - 1
  344. IF k = 8 THEN '                                                       backspace, random star position
  345.     rmin = INT(RND * 24) '                                            random RA
  346.     dmin = (INT(RND * 18) - 9) * t '                                  random dec
  347.     starinit = 0
  348. IF i$ = "." THEN
  349.     tfollow = tfollow XOR 1
  350.     auto = 0
  351.     vert = 1
  352.     mes$(0) = "TERRAIN FOLLOWING " + OnOff$(tfollow)
  353. p = (i$ = "<") - (i$ = ">") '                                         jump left/right
  354. IF (contact = 0) AND (p <> 0) THEN
  355.     suri = suri + 40 * p '                                            surface index
  356.     GOSUB slimit '                                                    limit suri
  357.     IF lock1 THEN hover = 1: lock1 = 0
  358. IF (i$ = "+") AND (zoom < 2) THEN zoom = zoom + 1: starinit = 0
  359. IF (i$ = "-") AND (zoom > 0) THEN zoom = zoom - 1: starinit = 0
  360. IF i$ = "?" THEN rick = rick XOR 1 '                                  show speed of processing graph
  361. IF okrick AND (i$ = "U") THEN tilef = (tilef + 1) MOD 3 '             alternate tilings
  362. IF i$ = "/" THEN
  363.     cpal = (cpal + 1) MOD 4 '                                         cycle green/black & white/normal monitor
  364.     mes$(0) = "": mes$(1) = ""
  365.     IF cpal = 1 THEN mes$(0) = "GT40 mode"
  366.     IF cpal = 2 THEN mes$(1) = "Hyperion mode!"
  367.     IF cpal = 3 THEN mes$(1) = "Do not adjust your set.  We control the horizontal and the vertical!"
  368. IF k = 32 THEN '                                                      cycle thru features
  369.     IF lock1 > 0 THEN '                                               on auto, landing zone selected, abort landing
  370.         abort = 1
  371.         mes$(0) = "ABORT!"
  372.         IF vx! = 0 THEN vx! = .01
  373.         RETURN
  374.     END IF
  375.     IF convo THEN '                                                   or speed up rendesvous
  376.         sct! = .2
  377.         sc! = TIMER
  378.         RETURN
  379.     END IF
  380.  
  381.     IF skyoff THEN tmod = t ELSE tmod = 16
  382.     jf = (jf + 1) MOD tmod
  383.     '          01234567890123456
  384.     i$ = MID$("mtsiHg5wleObBWoR", jf + 1, 1) '                        cycle thru ground and sky features
  385.     k = ASC(i$)
  386.     IF demo AND (jf = 7) THEN i$ = "e" '                              skip LGM in demo, because it's on the grave
  387.  
  388. p = INSTR("RObBWo", i$) '                                             jump to CM, deathstar, etc.
  389. IF p AND (skyoff = 0) THEN p = p - 1: GOSUB GoSkyObject
  390.  
  391. IF i$ = "A" THEN
  392.     lam = lam XOR 1 '                                                 land at McDonalds
  393.     IF lam AND (auto = 0) THEN i$ = "a" '                             turn on autopilot
  394. IF i$ = "a" THEN '                                                    autopilot
  395.     abort = 0 '                                                       in case it was on
  396.     tfollow = 0
  397.     auto = auto XOR 1 '                                               toggle
  398.     IF auto AND (radarf = 0) THEN radarf = 2
  399.     IF auto = 0 THEN hover = 1 '                                      be nice, help user
  400.     pt! = TIMER '                                                     restart countdown
  401. IF i$ = "c" THEN GOSUB CutOrOutOfFuel
  402. IF i$ = "C" THEN doclock = doclock XOR 1
  403. IF i$ = "d" THEN dump = dump XOR 1 '                                  fuel
  404. IF i$ = "D" THEN restart = 1 '                                        restart with defaults
  405. IF (i$ = "E") AND (starstatus > 0) THEN '                             end of universe
  406.     IF eou = 0 THEN eou = -1 ELSE eou = eou + 1 '                     restart or speedup
  407. IF i$ = "F" THEN
  408.     fuel! = h
  409.     lockfuel = 1
  410. IF i$ = "f" THEN lockfuel = lockfuel XOR 1 '                          THIS cheat the GT40 had, using toggle switches!
  411. IF i$ = "G" THEN gstyle = (gstyle + 1) MOD 6 '                        ground style
  412. IF i$ = "h" THEN hover = hover XOR 1: apd = 1 '                       apd=autopilot disconnect warning
  413. IF i$ = "I" THEN
  414.     invincible = ABS(invincible) XOR 1
  415.     mes$(0) = "INVINCIBLE MODE " + OnOff$(invincible)
  416.     GOSUB ReadLM '                                                    to change thrusters
  417. IF i$ = "j" THEN
  418.     darkstars = (darkstars + 1) MOD 5
  419.     mes$(0) = "Deathstar rotation" + STR$(darkstars)
  420. IF i$ = "k" THEN '                                                    kill threats or, if none, shoot at ground feature
  421.     firel = 1 '                                                       fire laser
  422.     FOR z = 1 TO 20 '                                                 IBM shells
  423.         shd(z) = 1
  424.     NEXT z
  425. IF i$ = "L" THEN GetSurface -1 '                                      level ground
  426. IF (i$ = "M") AND ((contact + inpause) = 0) THEN '                    laser level & land
  427.     magic = magic + 1
  428. IF (i$ = "n") AND inpause THEN nation = ((nation - 1) XOR 1) + 1 '    flag 1 US, 2 USSR
  429. IF i$ = "p" THEN GOSUB pause '                                        pause LM movement
  430. IF (i$ = "P") AND (contact = 0) AND (warp! < 1) AND (paraf = 0) THEN
  431.     paraf = 1 '                                                       parachute!
  432.     chs = 0
  433.     a = 0
  434.     GOSUB CutOrOutOfFuel
  435. IF i$ = "q" THEN Quit
  436. IF i$ = "Q" THEN
  437.     oscar = oscar XOR 1 '                                            land or sea flags for LGM
  438.     IF oscar THEN z$ = "SEA" ELSE z$ = "LAND"
  439.     mes$(0) = "LGM flags: " + z$
  440. IF i$ = "r" THEN
  441.     IF cut THEN '                                                     restart engine
  442.         cut = 0
  443.         hover = 1
  444.         power = opower
  445.         powerloss = 0
  446.     ELSE
  447.         IF auto = 0 THEN
  448.             radarf = (radarf + 1) MOD 3
  449.             mes$(0) = "Radar " + MID$("OFFON FAT", radarf * 3 + 1, 3)
  450.         END IF
  451.     END IF
  452. IF i$ = "S" THEN MakeSur: restart = 1 '                               generate new surfaces
  453. IF i$ = "T" THEN jitter = jitter XOR 1 '                              thrust computation
  454. IF i$ = "u" THEN '                                                    instrument panel on/off
  455.     zz = gs
  456.     gs = (SGN(gs) XOR 1) * 85 '                                       graphics start
  457.  
  458.     panelinit = 0
  459.     pif = -1
  460.  
  461.     z = (gs + 30) - px!
  462.     IF (gs > 0) AND (z > 0) THEN
  463.         px! = px! + z
  464.         suri = suri - z
  465.         GOSUB slimit
  466.     END IF
  467. IF i$ = "v" THEN '                                                    vertical automatic
  468.     IF tfollow THEN
  469.         tfollow = 0
  470.         mes$(0) = "TERRAIN FOLLOWING OFF"
  471.     END IF
  472.     vert = vert XOR 1
  473.     apd = 1 '                                                         autopilot disconnect warning
  474. IF i$ = "x" THEN starinit = 0: starfiles = (starfiles + 1) MOD 3 '    star density
  475. IF i$ = "X" THEN starinit = 0: regen = 1: Stars '                     regenerate single star file
  476. IF i$ = "y" THEN
  477.     mouseswap = mouseswap XOR 1
  478.     IF mouseswap THEN z$ = "reversed" ELSE z$ = "normal"
  479.     mes$(0) = "Mouse buttons " + z$
  480. IF i$ = "Y" THEN min = 3: sec = 45 '                                  black hole at 3:50
  481. IF (i$ = "z") AND (crash = 0) THEN
  482.     mes$(0) = "" '
  483.     mes$(1) = "" '                                                    erase radiation messages
  484.     dead$ = "SELF-DESTRUCT"
  485.  
  486. IF i$ = "}" THEN
  487.     GOSUB CutOrOutOfFuel
  488.     sgs = gs: gs = 0
  489.     srf = radarf: radarf = 0
  490.     GOSUB Plotscreen
  491.     dissolve
  492.     dead$ = " "
  493.     gs = sgs: radarf = srf
  494.  
  495. '          1234567890
  496. p = INSTR("5wlemtsiHg", i$) '                                         jump to feature
  497. IF p AND (contact = 0) THEN
  498.     sf = p
  499.     IF demo AND sf = 9 THEN sf = t
  500.     IF (sf(sf, 1) >= suri) AND (sf(sf, 0) < (suri + q3)) THEN '       already in vicinity of IBM
  501.         IF sf = 8 THEN shoot = 1 '                                    tell IBM to fire
  502.         IF demo THEN '                                                IBM at special location in demo mode, deal with it
  503.             px! = sf(sf, 2) - 3130
  504.             suri = 3130
  505.         END IF
  506.     ELSE
  507.         px! = center '                                                move ship to screen center
  508.         suri = sf(sf, 0) - center - 30 - (sf = 9) * h '               move ground to IBM
  509.     END IF
  510.     a = -ma '                                                         angle = -malfunction angle
  511.     abort = 0
  512.     wa = -ma '                                                        want angle
  513.     lock1 = 0 '                                                       radar lock
  514.     tmt! = 0 '                                                        to move total
  515.     vx! = 0 '                                                         not moving
  516.     warp! = 0 '                                                       cancel warp
  517. GOTO endk '                                                           done with ordinary keys
  518.  
  519. is2: '                                                                extended key
  520. z = mdelay '                                                          master delay
  521. mdelay = mdelay - (k = 73) + (k = 81) '                               PgUp/PgDn
  522. IF mdelay < 1 THEN mdelay = 1
  523. IF mdelay <> z THEN '                                                 changed
  524.     mes$(0) = "_LIMIT " + OnOff$(SGN(mdelay))
  525.     IF mdelay THEN mes$(0) = mes$(0) + LTRIM$(STR$(mdelay))
  526. IF status AND 3 THEN '                                                left or right shift
  527.     IF k = 72 THEN k = 201 '                                          LM up
  528.     IF k = 75 THEN k = 203 '                                          LM left
  529.     IF k = 77 THEN k = 204 '                                          LM right
  530. IF (inpause = 0) AND ((k = 72) OR (k = 80)) THEN '                    up and down arrow
  531.     apd = 1 '                                                         autopilot disconnect
  532.     hover = 0
  533.     vert = 0
  534.     thrust! = thrust! + (k = 80) - (k = 72) '                         true = -1
  535. thrust! = INT(thrust! * t) / t '                                      t = 10
  536. IF (hover = 0) AND (vert = 0) THEN thrust! = INT(thrust!)
  537. IF thrust! > h THEN thrust! = h
  538. IF (dump = 0) AND (fuel! > 0) AND (contact = 0) THEN '                side thrust/angle
  539.     IF inpause = 0 THEN wa = a - (k = 75) + (k = 77) '                                    left/right arrows
  540.     IF ABS(wa) > 99 THEN wa = 99 * SGN(wa) '                          want angle, limit 99
  541.     IF a <> wa THEN apd = 1 '                                         autopilot disconnect
  542. IF k = 59 THEN '                                                      F1 help
  543.     mHelp
  544.     start1! = TIMER: mpass& = 0 '                                     reset speed timer
  545. IF k = 60 THEN '                                                      F2 demo
  546.     demo = demo XOR 1
  547.     GOSUB init2
  548.     cbh = demo '                                                      constant black holes
  549. IF k = 61 THEN '                                                      F3, sky feature toggle
  550.     skyoff = skyoff XOR 1
  551.     IF skyoff = 0 THEN convo = 0
  552.     mes$(0) = "SKY OBJECTS " + OnOff$(1 - skyoff)
  553. IF k = 62 THEN '                                                      F4 endless bh
  554.     cbh = cbh XOR 1
  555.     exv(3) = 0
  556.     mes$(0) = "CONSTANT BLACK HOLES " + OnOff$(cbh)
  557. IF k = 63 THEN '                                                      F5 instrument background
  558.     f5toggle = f5toggle XOR 1
  559.     IF f5toggle = 0 THEN background = background XOR 1
  560.     IF f5toggle = 1 THEN porb = porb XOR 1
  561.     pload = 0
  562. IF (k = 64) AND ((ASO + inpause) = 0) THEN '                          F6 seperate AS/DS
  563.     GOSUB liftoff
  564.     RETURN
  565. IF k = 65 THEN showmap = showmap XOR 1 '                              F7 map
  566. IF k = 66 THEN '                                                      F8 shields
  567.     shield = shield XOR 1
  568.     geof = shield * t
  569. IF k = 67 THEN '                                                      F9 LED color
  570.     z$ = RIGHT$("0" + LTRIM$(STR$(LEDc)), 2)
  571.     z = INSTR(LED$, z$): IF z = 11 THEN z = -1
  572.     LEDc = VAL(MID$(LED$, z + 2, 2))
  573.     LEDtri = 0
  574. IF k = 68 THEN '                                                      F10 LED tri-color
  575.     LEDtri = LEDtri XOR 1
  576.     IF LEDtri THEN LEDc = green
  577. IF k = 71 THEN rmin = 0: dmin = 0: starinit = 0 '                     Home, star RA/dec to 0
  578.  
  579. endk:
  580. IF k = 201 THEN hoverc = hoverc - t '                                 move up
  581. IF k = 203 AND (left = 0) THEN left = 16 '                            move left
  582. IF k = 204 AND (right = 0) THEN right = 16 '                          move right
  583. IF apd OR (k = 201) OR (k = 203) OR (k = 204) THEN '                  blink AUTO
  584.     IF auto THEN APdisengage = 20 '                                   blink 20 times
  585.     auto = 0 '                                                        turn it off
  586.     apd = 0 '                                                         reset flag
  587.  
  588. pause:
  589. IF inpause THEN RETURN '                                              already doing this....
  590. dead$ = ""
  591. inpause = 1
  592. pt! = TIMER '                                                         for demo mode
  593. wu! = pt! + 1 '                                                       delay before planting flag
  594. DO: _LIMIT mdelay
  595.     GOSUB KeyAndMouse
  596.     IF k = 60 THEN RETURN '                                           F2 demo
  597.     IF (i$ > "") AND (INSTR("zD", i$)) THEN RETURN '                  self-destruct or restart
  598.     GOSUB Plotscreen
  599.     IF LEN(dead$) THEN RETURN
  600.     IF auto AND contact THEN '                                        countdown to blast off
  601.         IF TIMER < pt! THEN pt! = TIMER '                             midnite crossing fix
  602.         z! = TIMER - pt!
  603.         z = t - z!
  604.         IF z < 0 THEN z = 0
  605.         TextOnLM$ = LTRIM$(STR$(z))
  606.         IF z! > t THEN i$ = CHR$(13) '                                like pressing the key
  607.     END IF
  608.     GOSUB CalcFuel
  609. LOOP UNTIL (i$ = CHR$(13)) OR (i$ = "p")
  610. ctime! = TIMER
  611. fb$ = "" '                                                            feedback
  612. inpause = 0
  613. c = (contact = 1) AND (crash = 0) AND (liftoff = 0) AND (ABS(a) < 31)
  614. IF c THEN GOSUB liftoff
  615.  
  616. CalculateMotion:
  617. i = 0
  618. IF (power = opower) AND (RND < .0003) THEN
  619.     i = ((auto + contact + liftoff + vert) = 0) AND ((min * 60 + sec) > t)
  620. IF fpl OR i THEN '                                                    force power loss
  621.     fpl = 0
  622.     powerloss = t + RND * t + ASO * 30 '                              10 TO 20%, 50% ASO
  623.     power = opower + powerloss / h * opower
  624.     mes$(0) = LTRIM$(STR$(powerloss)) + "% POWER LOSS - DUMP FUEL!"
  625.  
  626. IF lob THEN px! = px! + exv(2) '                                      landed on Borg
  627. IF contact OR inpause THEN GOTO other
  628.  
  629. ta = ((a + ma) + 270) MOD tsix '                                       temp angle = a+malfunction angle
  630. ma! = (vmass + fuel!) / th '                                          actually 54% fuel
  631. fo! = ((thrust! + super * 5) / ma!) / power '                         f = ma
  632. IF fuel! = 0 THEN fo! = 0 '                                           nix any force if running on empty
  633. fx! = fo! * c!(ta) / 2
  634. IF dump AND (ABS(a) < 5) THEN fx! = 0
  635. fy! = fo! * s!(ta) + grav! '                                          thrust + gravity
  636. IF warp! > 0 THEN fx! = fx! * (warp! * 2 + 1) '                       get thru warp msgs faster
  637. vx! = vx! - fx!
  638. IF a <> 0 THEN vx! = vx! + (RND - pf!) / h '                          help get to integer vx
  639. IF ABS(vx!) < .01 THEN vx! = 0
  640. avx = ABS(vx!)
  641. IF (avx > 5) AND (avx < 20) THEN xoff = vx! ELSE xoff = 0
  642. IF cut AND (magic = 0) THEN
  643.     cel! = TIMER - ctime! '                                           time since cut
  644.     vy! = cvy! + grav! * (cel! * cel!) '                              v = at^2  velocity = acceleration times time squared
  645.     fy! = 0 '                                                         null y force since it's a different situation
  646. vy! = vy! + fy!
  647. IF warp! >= 1 THEN vy! = 0
  648.  
  649. px! = px! + vx! - lob * exv(2)
  650. py! = py! + vy!
  651.  
  652. IF (liftoff = 0) AND (py! < 55) THEN '                                stop going off screen top
  653.     IF convo = 0 THEN mes$(0) = "Too high - reduce thrust!"
  654.     py! = 55
  655.     vy! = 0
  656.  
  657. other:
  658. GOSUB CalcFuel
  659. IF liftoff AND (lob = 0) THEN RETURN
  660. nomove = demo AND (((suri \ q3) + 1) = 5)
  661.  
  662. zz = px! - center
  663. z! = ABS(vx!)
  664.  
  665. IF (nomove = 0) AND ((rlink > 0) OR (z! < 3) OR (z! > 20)) THEN
  666.     dx! = px! - center
  667.     px! = center
  668.     tmt! = tmt! + dx!
  669.     zq = 0 '                                                          was 30 woof woof
  670.     c1 = (px! <= (gs + zq))
  671.     c2 = (px! >= (q3 - zq))
  672.     IF c1 OR c2 THEN
  673.         IF c1 THEN z = q3 - zq ELSE z = gs + zq
  674.         z = z - px!
  675.         tmt! = tmt! - z
  676.         px! = px! + z
  677.     ELSEIF (zz <> 0) AND (ABS(vx!) <= 5) AND (nomove = 0) THEN
  678.         z = zz \ 2 + 1
  679.         tmt! = tmt! + z
  680.         px! = px! - z
  681.     END IF
  682. IF ABS(tmt!) >= q3 THEN tmt! = SGN(tmt!) * q3 - 1
  683.  
  684. IF left THEN '                                                        jog left (shift left arrow)
  685.     IF left = 16 THEN sv! = vx!
  686.     IF left > 8 THEN a = 4 ELSE a = -4
  687.     left = left - 1
  688.     IF left = 0 THEN a = 0: vx! = sv!
  689. IF right THEN '                                                       jog right (shift right arrow)
  690.     IF right = 16 THEN sv! = vx!
  691.     IF right > 8 THEN a = -4 ELSE a = 4
  692.     right = right - 1
  693.     IF right = 0 THEN a = 0: vx! = sv!
  694.  
  695. CalcFuel:
  696. IF cut THEN thrust! = 0
  697. IF lockfuel = 0 THEN
  698.     ta = ABS(a): IF ta > 5 THEN ta = 5 '                              main angle, up to 5
  699.     z! = (ta + super + ABS(fst)) * t '                                plus 10% for thrusters
  700.     used! = (thrust! + z!) / 8000
  701.     IF ASO THEN used! = used! * 2 '                                   burn faster for AS
  702.     IF inpause THEN used! = 0
  703.     IF shield THEN used! = used! + .001
  704.     fuel! = fuel! - used! * 4
  705.     IF fuel! <= 0 THEN fuel! = 0: GOSUB CutOrOutOfFuel
  706.  
  707. Plotscreen:
  708. IF bit! = 0 THEN bit! = TIMER + pf!
  709. IF TIMER > bit! THEN
  710.     bbit = bbit XOR 1 '                                               toggles twice per second, used all over - instruments, IBM hazard lights, clock colon, LGM ear wiggle
  711.     bit! = 0
  712.  
  713. bolthit = 0
  714. bolthitf = 0
  715. IF (crash = 0) AND (ABS(vx!) >= h) THEN warp! = ABS(vx!) / h ELSE warp! = 0
  716. IF warp! >= 1 THEN paraf = 0 '                                        reckon parachute can be dropped at warp speeds
  717.  
  718. ' change styles every 10/30 seconds
  719. IF style! = 0 THEN style! = TIMER + t
  720. IF style! > 86400 THEN style! = 1 '                                   midnite xing
  721. IF TIMER > style! THEN
  722.     bstyle1 = (bstyle1 + 1) MOD 3 '                                   Borg guts every 10s
  723.     IF bstyle1 = 0 THEN bstyle2 = bstyle2 XOR 1 '                     Borg exhaust
  724.     style! = 0
  725.  
  726. IF (starstatus > 0) AND (eou = 0) AND (vert = 0) AND (RND > .9999) THEN '  stars on+not already falling+WHY?+rarely
  727.     mes$(0) = "THE SKY IS FALLING!  THE SKY IS FALLING!"
  728.     eou = 1
  729. GOSUB CalculateMotion
  730.  
  731. IF gs THEN '                                                          graphics start not 0, instruments are visible
  732.     VIEW
  733.     pif = (pif + 1) MOD (pdiv + 1)
  734.     IF pif THEN timemachine ELSE GOSUB Instruments '                  INSTRUMENTS
  735. IF starstatus THEN
  736.     VIEW SCREEN(gs, SGN(LEN(mes$(0))) * 20)-(q3, q4)
  737.     Stars '                                                           STARS
  738.     VIEW SCREEN(gs, 0)-(q3, q4)
  739.     VIEW SCREEN(gs, 0)-(q3, q4)
  740.     CLS
  741.  
  742. IF LEN(mes$(0)) THEN
  743.     VIEW SCREEN(gs, 0)-(q3, 20)
  744.     CLS
  745.     VIEW SCREEN(gs, 0)-(q3, q4)
  746.  
  747. Info '                                                                INFO show timed messages at top, if any
  748. IF warp! < 1 THEN '                                                   no sky features except star streaks at warp speeds
  749.     IF skyoff = 0 THEN GOSUB SkyStuff '                               CM/DS/Bo/BH/Wo/Co
  750.     GOSUB PlotGround '                                                GROUND/FEATURES
  751.     Shells '                                                          SHELLS
  752.     IF (invincible = 0) AND (shield = 0) AND (skyoff = 0) THEN GOSUB FiveWaysToDie
  753. IF platform THEN PUT (pminx, pminy), gbuff(), OR '                    falling descent stage
  754. IF LEN(dead$) = 0 THEN GOSUB PlotVehicle '                            VEHICLE
  755. IF (warp! < 1) AND showmap AND (crash = 0) THEN
  756.     VIEW
  757.     Map '                                                             LM, ground & sky features
  758.     VIEW SCREEN(gs, 0)-(q3, q4)
  759. IF bolthit THEN '                                                     lightning zap from Deathstar
  760.     boltc = boltc + 1 + (boltc = 9999)
  761.     rtl!(2) = TIMER + 5
  762.     rtlc(2) = boltc
  763.     IF ((invincible + shield) = 0) AND (boltc >= t) THEN dead$ = "Zapped!" '   by EPCOR!"
  764.  
  765. IF okrick AND (LEN(debug$) > 0) THEN LOCATE 1, 12: PRINT debug$;
  766. timemachine
  767.  
  768.  
  769. SkyStuff:
  770. IF (min = 3) AND (sec = 50) THEN '                                    Tree-fiddy! (Southpark), do black hole
  771.     ex(3) = suri + t
  772.     ey(3) = h
  773.     exv(3) = t
  774.     eyv(3) = 1
  775.  
  776. IF cmleaving THEN
  777.     exv(0) = exv(0) + 2
  778.     IF exv(0) = 0 THEN exv(0) = 1
  779.  
  780. RESTORE skycrud
  781. IF eou THEN mi = 2 ELSE mi = 5 '                                      end of universe, no celestial events
  782. FOR i = 0 TO mi '                                                     0CM 1DS 2Borg 3BH 4Worm 5Comet 6Al
  783.     READ g$, skyset1(i), skyset2(i)
  784.  
  785. FOR i = 0 TO mi + ufof '                                              0CM 1DS 2Borg 3BH 4Worm 5Comet 6Alien
  786.     xplus = skyset1(i): xminus = skyset2(i)
  787.     IF (i = 3) AND cbh THEN ek(i) = 0 '                               constant black hole
  788.     IF ek(i) = -1 THEN GOTO ni2
  789.  
  790.     IF (ey(i) > (q4 + 50)) OR (ey(i) < -50) OR (exv(i) = 0) THEN
  791.         ei(i) = 0 '                                                   ini
  792.         ek(i) = 9999
  793.         nx:
  794.         ex(i) = RND * q1
  795.         IF ABS(ex(i) - (px! + suri)) < q3 THEN GOTO nx '              start away from craft
  796.         IF ABS(ex(i) - px!) < q3 THEN GOTO nx '                       start away from craft
  797.         IF i = 2 THEN ex(i) = (ex(1) + 3200) MOD q1
  798.         ey(i) = 120 + RND * h '                                       random y 120-220
  799.         IF i = 0 THEN ey(i) = 22 '                                    CM
  800.         IF i = 1 THEN ey(i) = 170 '                                   DS
  801.         IF i = 2 THEN ey(i) = th '                                    Borg
  802.         '              0 1 2 3 4 5
  803.         '              CMDeBoBHWoCoAl
  804.         c1 = VAL(MID$("04010210120502", i * 2 + 1, 2)) '              min x velocity
  805.         c2 = VAL(MID$("09030210171005", i * 2 + 1, 2)) '              max x velocity
  806.         exv(i) = RND * (c2 - c1) + c1 '                               random in range
  807.         IF RND > pf! THEN exv(i) = -exv(i)
  808.  
  809.         z = VAL(MID$("00000003020100", i * 2 + 1, 2)) '               top range y velocity
  810.         eyv(i) = 0
  811.         IF z THEN eyv(i) = RND * (z - 1) + 1 '                        random in range
  812.  
  813.         IF RND > pf! THEN exv(i) = -exv(i)
  814.         IF RND > pf! THEN eyv(i) = -eyv(i)
  815.         IF (i = 3) AND cbh THEN
  816.             IF RND > pf! THEN
  817.                 ex(i) = suri - t
  818.                 exv(i) = t
  819.             ELSE
  820.                 ex(i) = suri + q3 + t
  821.                 exv(i) = -t
  822.             END IF
  823.         END IF
  824.     END IF
  825.  
  826.     ex(i) = ex(i) + exv(i)
  827.     ey(i) = ey(i) + eyv(i)
  828.  
  829.     IF ex(i) < 0 THEN
  830.         IF (i = 0) AND cmleaving THEN
  831.             ek(i) = -1: cmleaving = 0
  832.         ELSE
  833.             ex(i) = ex(i) + q1
  834.         END IF
  835.     END IF
  836.     IF ex(i) > q1 THEN
  837.         IF (i = 0) AND cmleaving THEN
  838.             ek(i) = -1: cmleaving = 0
  839.         ELSE
  840.             ex(i) = ex(i) - q1
  841.         END IF
  842.     END IF
  843.  
  844.     exl(i) = localize(ex(i), xplus, xminus)
  845.     IF (i = 3) AND cbh AND (exl(i) = 9999) THEN exv(i) = 0
  846.  
  847.     IF ek(i) <> -1 THEN ek(i) = 9999
  848.     IF exl(i) <> 9999 THEN
  849.         dx! = ABS(px! - exl(i))
  850.         dy! = ABS(py! - ey(i))
  851.         ek(i) = SQR(dx! * dx! + dy! * dy!)
  852.  
  853.         IF i = 0 THEN GOSUB CommandModule
  854.         IF i = 1 THEN DeathStar exl(i), f$(37)
  855.         IF i = 2 THEN Borg exl(i), ey(i)
  856.         IF i = 3 THEN
  857.             IF (LEN(mes$(0)) = 0) AND (showmap = 0) AND (cbh = 0) THEN
  858.                 mes$(0) = "DANGER, WILL ROBINSON, DANGER!"
  859.             END IF
  860.             IF sas = 0 THEN BlackHole 0
  861.             sas = 0
  862.         END IF
  863.         IF i = 4 THEN WormHole
  864.         IF i = 5 THEN
  865.             tx = localize(ex(5), 0, 0)
  866.             ty = ey(5)
  867.             Comet tx, ty
  868.         END IF
  869.         IF i = 6 THEN '                                               traditional alien - too silly
  870.             j = RND * h - h \ 2
  871.             z = ey(6) + j
  872.             IF (RND > .9) AND (z > h) AND (z < 250) THEN
  873.                 ey(6) = z
  874.                 alien = alien XOR 1
  875.                 ex(6) = ex(6) + 20 * SGN(alien - pf!)
  876.             END IF
  877.             UFO exl(6), ey(6), exv(6)
  878.         END IF
  879.     END IF
  880.     ni2:
  881.  
  882. FiveWaysToDie:
  883. IF (ek(2) >= 0) AND (ek(2) < 20) THEN '                               Borg
  884.     wu! = TIMER + 5
  885.     DO: _LIMIT mdelay
  886.         CLS
  887.         mes$(0) = "YOU ARE BORG"
  888.         Info
  889.         Borg exl(2), ey(2)
  890.         FOR i = 1 TO rp
  891.             p = POINT(LMrx(i), LMry(i))
  892.             IF p = black2 THEN c = green ELSE c = black2
  893.             PSET (LMrx(i), LMry(i)), c
  894.         NEXT i
  895.         timemachine
  896.     LOOP UNTIL TIMER > wu!
  897.     dead$ = "BORG"
  898.  
  899. IF (ek(3) >= 0) AND (ek(3) < 30) THEN '                               black hole
  900.     dead$ = "EATEN"
  901.     BlackHoleDoom
  902.  
  903. IF (ek(4) >= 0) AND (ek(4) < 30) THEN '                               wormhole
  904.     wu! = TIMER + 5
  905.     spx! = exl(4)
  906.     spy! = ey(4)
  907.     exv(4) = 0
  908.     eyv(4) = 0
  909.     wradar = radarf
  910.     radarf = 1
  911.     cut = 1
  912.     DO: _LIMIT mdelay
  913.         CLS
  914.         fb$ = ""
  915.         mes$(0) = "HOLY CRAP, BATMAN!"
  916.         mes$(1) = ""
  917.         Info
  918.         a = RND * 359
  919.         px! = spx! + (RND - pf!) * 20
  920.         py! = spy! + (RND - pf!) * 5
  921.         WormHole
  922.         LMdistort '                                                   optional
  923.         GOSUB PlotVehicle
  924.         timemachine
  925.     LOOP UNTIL TIMER > wu!
  926.     radarf = wradar
  927.     dead$ = "BATMAN"
  928.  
  929. IF (ek(5) >= 0) AND (ek(5) < 15) THEN dead$ = "HIT BY COMET"
  930. IF ufof AND (ek(6) >= 0) AND (ek(6) < 45) THEN dead$ = "HIT BY ALIEN"
  931.  
  932. GetAlt:
  933. alt! = (gety(-(rxm + wi2)) - ((sy1 + sy2) \ 2)) / 5
  934.  
  935. Instruments:
  936. osc = 8
  937. IF gs THEN LoadPanel '                                                graphics start not zero, instrument panel is on
  938. IF (warp! > 0) AND (contact = 0) THEN
  939.     IF warp! >= t THEN
  940.         dead$ = "WARP 10"
  941.         RETURN
  942.     END IF
  943.     RESTORE warp
  944.     FOR i = 1 TO INT(warp!)
  945.         READ z$
  946.     NEXT i
  947.     w$ = LTRIM$(STR$(INT(warp! * h) / h))
  948.     IF LEN(w$) = 1 THEN w$ = w$ + ".00"
  949.     IF LEN(w$) = 3 THEN w$ = w$ + "0"
  950.     mes$(0) = "WARP " + w$ + " - " + z$
  951.     IF gs AND ((TIMER MOD t) > 5) THEN
  952.         Henonp f
  953.         Wave '                                                        osc = 5 if commented out
  954.         AuHoVe auto, hover, vert, lam
  955.         GOTO clock
  956.     END IF
  957.  
  958. IF gs = 0 THEN RETURN '                                               graphics start of 0 means the instrument panel is off
  959.  
  960. IF panelinit = 0 THEN
  961.     IF crash THEN f = 15 ELSE f = ((f + 1) MOD 5) + t '               title graphic/face
  962.  
  963. Henonp f '                                                            title graphic
  964.  
  965. LINE (0, 0)-(gs - 1, 3), blue2, BF '                                  clear map area
  966.  
  967. IF pdiv THEN '                                                        instrument update frequency 1-4, mainly a way to slow down erratic thrust display
  968.     j = 0
  969.     FOR i = 1 TO 18 '                                                 my name in Morse
  970.         p = VAL(MID$("002032023222300032", i, 1)) '                   Frost
  971.         IF p < 3 THEN LINE (14 + j, 2)-(14 + j + p, 2), white
  972.         j = j + p + 2
  973.     NEXT i
  974.  
  975. IF (contact + auto + hover + vert + liftoff) = 0 THEN
  976.     IF (vy! > .6) AND (-fy! < 0) THEN PrintVGA CHR$(24), 5, 241, red, black2
  977.     IF (vy! < .4) AND (-fy! > -.01) THEN PrintVGA CHR$(25), 5, 250, yellow, black2
  978.  
  979. AuHoVe auto, hover, vert, lam
  980.  
  981. IF tfollow THEN '                                                     terrain following!
  982.     FOR ty = glmax - 20 TO glmax
  983.         FOR tx = 0 TO gs - 1
  984.             IF POINT(tx, ty) = blue THEN PSET (tx, ty), red '         red bg
  985.         NEXT tx
  986.     NEXT ty
  987.     FOR i = 0 TO 4 '                                                  TF
  988.         p& = VAL("&H" + MID$("E744464444", i * 2 + 1, 2))
  989.         LINE (2, 339 + i)-(10, 339 + i), green, , p& * 128
  990.     NEXT i
  991.  
  992. osc = 0
  993. c = LEDc
  994. IF (sbest! >= h) OR powerloss THEN c = red
  995. z! = thrust!: IF z! > h THEN z! = h '                                 200 at liftoff, show 100
  996. PrepAndShowLED z!, 3, 1 '                                             thrust osc1
  997. PrintCGA "T", 5, -1, c, -blue, 0 '                                    T is for flame
  998. i = LEDc: j = black
  999. IF jitter THEN SWAP i, j '                                            thrust calc type
  1000. LINE (4, 231)-(5, 232), i, B '                                        left light  (on = slow)
  1001. LINE (13, 231)-(14, 232), j, B '                                      right light (on = fast)
  1002. Bar z! / h, 0
  1003.  
  1004. c = dcolor(vy!, 2, 3, 1) '                                            vy osc2
  1005. z! = vy!
  1006. IF ABS(z!) > 99.97 THEN z! = 99.99
  1007. PrepAndShowLED z!, 3, 2
  1008. PrintCGA "V", 5, -1, c, -blue2, 0
  1009. z! = (z! + 3) / 6
  1010. Bar z!, 1
  1011.  
  1012. c = dcolor(vx!, 2, 3, 1) '                                            vx osc3
  1013. IF warp! THEN
  1014.     z! = warp!
  1015.     z! = vx! + rfs!
  1016. PrepAndShowLED z!, 3, 2
  1017. PrintCGA "H", 5, -1, c, -blue, 0
  1018. z! = (z! + 3) / 6
  1019. Bar z!, 1
  1020.  
  1021. GOSUB GetAlt '                                                        alt osc4
  1022. IF contact AND (alt! > 0) THEN alt! = 0
  1023. c = dcolor(alt!, t, 3, -1)
  1024. PrepAndShowLED alt!, 4, 1
  1025. PrintCGA "A", 5, -1, c, -blue2, 0
  1026. IF warp! OR (radarf = 0) THEN z! = 0 ELSE z! = alt! / 60
  1027. Bar z!, 0
  1028.  
  1029. c = dcolor(fuel!, t, 5, -1) '                                         fuel osc5
  1030. PrepAndShowLED fuel!, 4, 1
  1031. PrintCGA "F", 5, -1, c, -blue, 0
  1032. z! = fuel! / h
  1033. Bar z!, 0
  1034.  
  1035. clock:
  1036. IF TIMER < start2! THEN start2! = TIMER '                             midnite crossing
  1037. IF crash = 0 THEN el! = el! + (TIMER - start2!) '                     elapsed time
  1038. start2! = TIMER
  1039. IF el! >= 1 THEN
  1040.     WHILE el! >= 1 '                                                  catch-up
  1041.         el! = el! - 1
  1042.         sec = (sec + 1) MOD 60
  1043.         IF sec = 0 THEN min = (min + 1) MOD 99
  1044.     WEND
  1045.     IF sec MOD 5 = 0 THEN '                                           change title graphic
  1046.         IF crash THEN f = 15 ELSE f = ((f + 1) MOD 5) + t
  1047.     END IF
  1048. z$ = RIGHT$("0" + LTRIM$(STR$(min)), 2) + RIGHT$("0" + LTRIM$(STR$(sec)), 2)
  1049. osc = 6
  1050. LEDdisplay z$ '                                                       clock osc6
  1051.  
  1052. i = suri + px!
  1053. j = ABS(i - sf(5, 2))
  1054. k = sf(5, 2) + (q1 - i)
  1055. IF j <= 3200 THEN dtm! = j ELSE dtm! = k
  1056. PrepAndShowLED dtm!, 4, 0 '                                           dtm osc7
  1057. PrepAndShowLED CSNG(speed), 4, 0 '                                    speed osc8
  1058. ShowAngle a '                                                         angle osc9
  1059. panelinit = 1
  1060.  
  1061. LMcolors: '                                                           optional
  1062. IF contact OR (vx! = 0) THEN lbit = 0
  1063. IF (contact + vx!) = 0 THEN
  1064.     v1 = RND * 3
  1065.     v2 = RND * 3
  1066.     SWAP LMci(v1), LMci(v2)
  1067. FOR i = 1 TO rp '                                                     right pad
  1068.     oc = LMoc(i)
  1069.     LMc(i) = oc
  1070.     IF (oc = craft) OR (oc = red) THEN '                              shadow
  1071.         zx = LMrx(i) - px! + 2 - xoff * (inpause = 0)
  1072.         zy = LMry(i) - py!
  1073.         IF (oc = craft) AND ((warp! > 0) OR (zy > zx)) THEN
  1074.             tc = gray2
  1075.         ELSE
  1076.             tc = oc
  1077.         END IF
  1078.         LMc(i) = tc
  1079.     END IF
  1080.     IF (i < 279) AND (LMoc(i) = black2) THEN '                        Ascent stage cycle
  1081.         lbit = (lbit + 5) MOD 4
  1082.         LMc(i) = LMci(lbit)
  1083.     END IF
  1084. lbit = lbit - (vx! > 0) * 2 + ASO * t
  1085.  
  1086. PlotVehicle:
  1087. IF warp! < 1 THEN
  1088.     wda = 0
  1089.     px! = wx!: py! = wy!
  1090.     wda = warp! * 5 * s!((px! + 40) MOD tsix)
  1091.  
  1092. IF crash THEN
  1093.     FOR i = 1 TO rp
  1094.         PSET (LMrx(i), LMry(i)), LMc(i)
  1095.     NEXT i
  1096.     GOTO endproc
  1097.  
  1098. IF bolthit = 0 THEN GOSUB LMcolors
  1099.  
  1100. i = sf(4, 2) - 50 '                                                   left of volcano
  1101. j = sf(4, 2) + 50 '                                                   right of volcano
  1102. k = suri + px! '                                                      LM position
  1103. IF (k > i) AND (k < j) THEN '                                         in the locality?
  1104.     c = 0 '                                                           count
  1105.     FOR ty = py! + 8 TO py! + 18 '                                    leg/nozzle area
  1106.         FOR tx = px! - 17 TO px! + 17
  1107.             p = POINT(tx, ty) '                                       what color is the pixel?
  1108.             c = c - (p = orange) '                                    hot lava
  1109.         NEXT tx
  1110.     NEXT ty
  1111.     ' LINE (px! - 17, py! + 8)-(px! + 17, py! + 18), yellow, B '      diagnostics
  1112.     IF c THEN '                                                       contacted some lava
  1113.         FOR i = rp TO 1 STEP -1 '                                     from the bottom
  1114.             IF LMoc(i) = craft THEN '                                 is normal color?
  1115.                 LMoc(i) = red '                                       make red
  1116.                 nred = nred + 1 '                                     keep track of count
  1117.                 c = c - 1
  1118.                 IF c = 0 THEN EXIT FOR '                              enough
  1119.             END IF
  1120.         NEXT i
  1121.     END IF
  1122.  
  1123. IF nred = 0 THEN '                                                    number red
  1124.     temp = 0
  1125.     rtlc(1) = 0
  1126.     IF ASO THEN z = 115 ELSE z = 223 '                                max that COULD be normal
  1127.     otemp = temp
  1128.     temp = (nred * h / z) MOD 101 '                                   temperature
  1129.     rtlc(1) = temp
  1130.     IF temp > otemp THEN rtl!(1) = TIMER + 5
  1131.     c = 24 '                                                          gasoline
  1132.     IF temp > 30 THEN c = 32 '                                        dark red
  1133.     IF temp > 60 THEN c = 4 '                                         red
  1134.     IF temp = h THEN c = 15 '                                         white
  1135.     IF bw = 0 THEN PALETTE gasoline, c
  1136.     IF (temp = h) AND (invincible = 0) THEN dead$ = "FRIED BY VOLCANO"
  1137.     FOR i = 0 TO 20 '                                                 cool down some
  1138.         j = RND * rp
  1139.         IF LMoc(j) = red THEN LMoc(j) = craft: nred = nred - 1
  1140.     NEXT i
  1141.  
  1142. n = rp '                                                              last pixel = right pad
  1143. IF fuel! > 0 THEN GOSUB Exhaust '                                     maybe vehicle only
  1144.  
  1145. IF n > maxn THEN maxn = n
  1146.  
  1147. ta = a + ma '                                                         temp a = a + malfunction
  1148. zz = ta * -(ABS(ta) > 4) '                                            rotate beyond 5 degrees
  1149. ta = (zz + wda + tsix) MOD tsix '                                             keep in array bounds
  1150. c! = c!(ta) '                                                         cosine
  1151. s! = s!(ta) '                                                         sine
  1152. ta = zz '                                                             angle to use
  1153.  
  1154. rfx = 0 '                                                             optional craft jitter
  1155. rfy = 0
  1156. rfs! = 0 '                                                            random change in vx
  1157. IF (jitter = 1) AND (cut = 0) THEN '                                  not slow or engine cut
  1158.     IF (RND > .9) AND (a = 0) THEN '                                  a = angle
  1159.         IF RND > pf! THEN rfx = 1 ELSE rfx = -1 '                     half right, half left
  1160.         rfs! = rfx * .01 * (INT(RND * 9) + 1) '                       how much? .01 - .09
  1161.     END IF
  1162.     IF RND > .9 THEN '                                                y jitter, 1 chance in 10
  1163.         IF RND > pf! THEN rfy = 1 ELSE rfy = -1 '                     half down, half up
  1164.     END IF
  1165.  
  1166. IF doclock THEN
  1167.     i = VAL(MID$(TIME$, 1, 2))
  1168.     j = VAL(MID$(TIME$, 4, 2))
  1169.     k = VAL(MID$(TIME$, 7, 2))
  1170.     clocka(0) = (i + j / 60) * 30 '                                   hour hand
  1171.     clocka(1) = j * 6 '                                               minute hand
  1172.     clocka(2) = k * 6 '                                               seconds
  1173.     FOR z = 0 TO 2 '                                                  prep for radians
  1174.         clocka(z) = (clocka(z) + 270) MOD tsix
  1175.     NEXT z
  1176.     ao = 0 '                                                          angle offset
  1177.     ao = (ao + 1) MOD 361
  1178.  
  1179. tvx = SGN(vx!): IF tvx = 0 THEN tvx = 1
  1180. tao = ao * tvx
  1181. sco = sco XOR 1
  1182. IF doclock THEN sco = 0
  1183. IF sco THEN tc = red ELSE tc = lmsl
  1184. z3 = tsix + (shield = 0) * 361
  1185. FOR z2 = 0 TO z3
  1186.     a2 = (z2 + tao * 5 + tsix0) MOD tsix
  1187.     tx = px! + 50 * c!(a2) * aspect!
  1188.     ty = py! + 50 * s!(a2)
  1189.     IF ty < gety(tx) THEN
  1190.         IF (z2 MOD 30) = 0 THEN
  1191.             CIRCLE (tx, ty), 1, tc, , , .75
  1192.             IF geof THEN
  1193.                 FOR i = z2 - 120 TO z2 STEP 30
  1194.                     j = (i + tsix) MOD tsix
  1195.                     tx2 = px! + 60 * c!(j) * aspect!
  1196.                     ty2 = py! + 60 * s!(j)
  1197.                     LINE (tx, ty)-(tx2, ty2), tc
  1198.                 NEXT i
  1199.             END IF
  1200.         END IF
  1201.         IF doclock THEN
  1202.             FOR i = 0 TO 2
  1203.                 IF a2 = clocka(i) THEN
  1204.                     c = VAL(MID$("021404", i * 2 + 1, 2))
  1205.                     CIRCLE (tx, ty), 4 - i, c, , , .75
  1206.                     PAINT (tx, ty), c, c
  1207.                 END IF
  1208.             NEXT i
  1209.         END IF
  1210.     END IF
  1211. NEXT z2
  1212.  
  1213. FOR i = 1 TO rp '                                                     rp = craft right pad
  1214.     LMrx(i) = px! + LMx(i) * c! + LMy(i) * s! + rfx '                 x rotated
  1215.     LMry(i) = py! - LMx(i) * s! + LMy(i) * c! + rfy '                 y rotated
  1216.     IF LMry(i) > glmax THEN LMry(i) = glmax '                         not below ground
  1217.     IF i = xp THEN sx0 = LMrx(i): sy0 = LMry(i) '                     save radar loc
  1218.     IF i = lp THEN sx1 = LMrx(i): sy1 = LMry(i) '                     save left pad loc
  1219.     IF i = rp THEN sx2 = LMrx(i): sy2 = LMry(i) '                     save right pad loc
  1220.     IF bolthit THEN LMc(i) = white
  1221.     PSET (LMrx(i), LMry(i)), LMc(i)
  1222.  
  1223. IF fuel! < 95 THEN GOSUB flevel
  1224.  
  1225. eflag = 0 '                                                           determine flame climb
  1226. fx1 = 0 ' initialize for deflect
  1227. fx2 = 0
  1228. phg = (sx1 + sx2) \ 2 + ta * 2 '                                      point hit ground
  1229.  
  1230. tty! = py! + 26
  1231.  
  1232. FOR i = rp + 1 TO n '                                                 flame/fuel dump
  1233.     x = px! + LMx(i) * c! + LMy(i) * s! + rfx '                       x rotated
  1234.     y = py! - LMx(i) * s! + LMy(i) * c! + rfy '                       y rotated
  1235.     c = LMc(i) '                                                      fuel dump/flame
  1236.     IF warp! < 1 THEN GOSUB deflect '                                 deflect off ground
  1237.     c = ABS(c) '                                                      color
  1238.     PSET (x, y), c '                                                  flame particle
  1239.     IF i <= n3 THEN '                                                 main exhaust
  1240.         IF (i MOD t) = 1 THEN '                                       every 10th pixel
  1241.             LINE (x - 1, y)-(x + 1, y), c '                           make "+"
  1242.             LINE (x, y - 1)-(x, y + 1), c
  1243.         END IF
  1244.     END IF
  1245.  
  1246. IF rfx AND dump AND (a = 0) THEN vx! = vx! + rfs! '                   make jitter real
  1247. IF rfx AND (dump = 0) AND (a <> 0) THEN vx! = vx! + rfs!
  1248.  
  1249. endproc:
  1250.  
  1251. IF doclock THEN TextOnLM$ = LEFT$(TIME$, 5)
  1252. IF LEN(TextOnLM$) THEN GOSUB TextOnLM
  1253.  
  1254. GOSUB radar
  1255.  
  1256. fc = 0 '                                                              LGM flame count
  1257. IF (sf(3, 1) >= suri) AND (sf(3, 0) < (suri + q3)) THEN
  1258.     x1 = sf(3, 0) - suri
  1259.     y1 = gety(x1) - 14
  1260.     FOR x = x1 + 5 TO x1 + 15
  1261.         FOR y = y1 - 9 TO y1 + 12
  1262.             IF POINT(x, y) = yellow THEN fc = fc + 1
  1263.         NEXT y
  1264.     NEXT x
  1265.  
  1266. GOSUB KillThreats
  1267.      
  1268. geof = geof - 1 - (geof = 0)
  1269.  
  1270. IF ok AND (TIMER > wu2!) AND (INSTR(mes$(0), "IN CAR") = 0) THEN FlagandFireworks
  1271.  
  1272. mpass& = mpass& + 1
  1273. IF TIMER <= start1! THEN start1! = TIMER: mpass& = 1
  1274. speed = ((TIMER - start1!) / mpass&) * h * t
  1275.  
  1276. IF rick THEN GraphSpeed
  1277.  
  1278. IF magic = 1 THEN '                                                   magic landing, 1st step laser the surface to level
  1279.     sf = 0
  1280.     z = suri + px!
  1281.     IF z > q1 THEN z = z - q1
  1282.     sf(0, 0) = z - 35 '                                               cut out a swath 70 units wide
  1283.     sf(0, 1) = z + 35
  1284.     GOSUB lsurface '                                                  apply laser
  1285.     a = 0 '                                                           angle
  1286.     auto = 0 '                                                        autopilot
  1287.     vx! = 0 '                                                         cancel any x velocity
  1288.     vy! = 0 '                                                         cancel any y velocity
  1289.     py! = 331 + ASO * 9 '                                             ground has been cut to the lowest
  1290.     cut = 1 '                                                         signal engine off
  1291.     magic = 2
  1292.  
  1293. '                                                                     kill surface feature
  1294. IF firel AND ksf AND (contact = 0) AND (sf(sf, 2) > 0) THEN
  1295.     GOSUB lsurface
  1296. firel = ks '                                                          ks = keep shooting
  1297.  
  1298. '                                                                     terrain following
  1299. IF tfollow AND (contact = 0) AND (dump = 0) AND (liftoff = 0) THEN
  1300.     hover = 1
  1301.     hp = q1
  1302.     svx = SGN(vx!)
  1303.     IF svx < 0 THEN tx = sx1 ELSE tx = sx2
  1304.     la = ABS(vx!) * t
  1305.     IF la < t THEN la = t
  1306.     IF la > h THEN la = h
  1307.     FOR i = -(wi + 5) TO la
  1308.         j = tx + i * svx
  1309.         k = j
  1310.         IF k < 0 THEN k = k + q1
  1311.         IF k > q1 THEN k = k - q1
  1312.         z = gety(k)
  1313.         IF z < hp THEN hp = z: sx = j
  1314.     NEXT i
  1315.     cx = ABS(sx - tx)
  1316.     IF cx THEN
  1317.         cy = hp - t - ABS(a / 2) - sy1
  1318.         st! = cy / cx * (ABS(vx!) + 1)
  1319.         IF st! > 2 THEN st! = 2
  1320.         IF st! < -t THEN st = -t
  1321.         fst = -SGN(st!) * 2
  1322.         py! = py! + st!
  1323.         IF py! < 250 THEN py! = 250
  1324.     END IF
  1325. IF paraf THEN
  1326.     IF py! > 150 THEN mes$(0) = "Parachutes don't work in a vacuum!"
  1327.     Parachute
  1328.  
  1329.  
  1330. TextOnLM:
  1331. IF (ASO = 0) AND (ABS(ta) < t) THEN
  1332.     lt = LEN(TextOnLM$)
  1333.     tx = px! - lt * 2 + rfx
  1334.     ty = py! + rfy
  1335.     IF ty > 340 THEN ty = 340
  1336.     TinyFont TextOnLM$, tx, ty, white
  1337. TextOnLM$ = ""
  1338.  
  1339. KillThreats:
  1340. killed = 0
  1341. FOR i = 0 TO 20 '                                                     shells
  1342.     c1 = shield AND (shx(i) > 0) AND (shd(i) < 70) '                  shield on and shell close to LM
  1343.     c2 = firel AND (shx(i) > 0) '                                     fire laser and shell in air
  1344.     IF c1 OR c2 THEN
  1345.         killed = 1 '                                                  found something to kill
  1346.         tx = shx(i) - suri
  1347.         ty = shy(i)
  1348.         GOSUB LMfl '                                                  fl = fire laser
  1349.         IF LEN(dead$) THEN RETURN
  1350.         ExplodeShell i
  1351.     END IF
  1352.  
  1353. ks = 0
  1354. FOR i = 1 TO 6
  1355.     IF skyoff OR (ek(i) = -1) THEN GOTO ni3
  1356.     '                   CM DS BO BH WO Co
  1357.     IF firel AND (exl(i) > gs) AND (exl(i) < q3) THEN
  1358.         killed = 1
  1359.         ks = 1
  1360.         tx = exl(i)
  1361.         ty = ey(i)
  1362.         IF laserb = 0 THEN laserb = 5
  1363.         IF laserb > 0 THEN
  1364.             GOSUB LMfl
  1365.             IF LEN(dead$) THEN RETURN
  1366.             k = (5 - laserb) * 4
  1367.             IF i > 1 THEN
  1368.                 CIRCLE (tx, ty), k, yellow
  1369.                 PAINT (tx, ty), yellow, yellow
  1370.             END IF
  1371.             laserb = laserb - 1
  1372.         END IF
  1373.         IF laserb = 0 THEN
  1374.             ks = 0
  1375.             IF i = 1 THEN
  1376.                 mes$(1) = "The Dark Side has cookies!"
  1377.             ELSE
  1378.                 FOR a2 = 0 TO tsix STEP 2
  1379.                     x2 = tx + RND * h * c!(a2) * aspect!
  1380.                     y2 = ty + RND * h * s!(a2)
  1381.                     LINE (tx, ty)-(x2, y2), gold
  1382.                 NEXT a2
  1383.                 ek(i) = -1
  1384.                 exv(i) = 0
  1385.                 exl(i) = -1
  1386.                 IF (i = 2) AND lob THEN dead$ = "SELF-DESTRUCT"
  1387.             END IF
  1388.         END IF
  1389.     END IF
  1390.     ni3:
  1391. IF killed THEN ksf = 0 ELSE ksf = 1
  1392.  
  1393. lsurface: '                                                           laser surface feature
  1394. z = (RND > .9) OR (magic = 1) '                                       1 out of 10 destroys, magic always
  1395. FOR i = sf(sf, 0) TO sf(sf, 1)
  1396.     tx = i - suri
  1397.     IF tx < 0 THEN tx = tx + q1
  1398.     ty = gety(tx)
  1399.     IF sf <> 3 THEN ty = ty + RND * (q4 - ty)
  1400.     IF i MOD 2 THEN GOSUB LMfl '                                      fire laser
  1401.     IF z THEN gh(i) = glmax '                                         level
  1402.     SMOOTH sf(sf, 0) - 1 '                                            smooth transition from where the ground has been leveled, left side
  1403.     SMOOTH sf(sf, 1) '                                                                                                        , right side
  1404.     sf(sf, 2) = -1
  1405.  
  1406. LMfl: '                                                               fire laser
  1407. IF (cwd < 50) AND (sy1 > szs) THEN '                                  in car wash?
  1408.     dead$ = "REFLECTED LASER"
  1409.     cwd = 999
  1410.     firel = 0
  1411.     laserb = 0
  1412.     ks = 0
  1413.     RETURN
  1414. FOR zx = -1 TO 1
  1415.     FOR zy = -1 TO 1
  1416.         LINE (sx0 + zx, sy0 + zy)-(tx, ty), lmsl
  1417.     NEXT zy
  1418. NEXT zx
  1419. geof = t
  1420.  
  1421. flevel: '                                                             make fuel level when angle > 4
  1422. IF ASO THEN RETURN '                                                  no fuel shown with AS
  1423. ptk = (h - fuel!) * 2.7 '                                             pixels to kill
  1424. z = ptk '                                                             ptk used by ExplodeLM
  1425. x1 = px! - 16
  1426. x2 = px! + 14
  1427. y1 = py! - 15
  1428. y2 = py! + 15
  1429. FOR y = y1 TO y2
  1430.     FOR x = x1 TO x2
  1431.         IF POINT(x, y) = fuel THEN
  1432.             PSET (x, y), black2
  1433.             z = z - 1
  1434.         END IF
  1435.     NEXT x
  1436.     IF z <= 0 THEN EXIT FOR
  1437.  
  1438. deflect: '                                                            flame bounce
  1439. oz = gety(-x)
  1440. IF deflectat > 0 THEN oz = deflectat
  1441. z = oz
  1442.  
  1443. '       dump           side t      st in pause
  1444. IF (c = fuel) OR (c = -yellow) OR (c = -blue) THEN
  1445.     IF (fx1 > 0) AND (x < fx1) THEN z = 0
  1446.     IF (fx2 > 0) AND (x > fx2) THEN z = 0
  1447.     rf1 = RND * t + 1
  1448.     rf2 = RND * 20 - t
  1449.     IF y >= (z - 1) THEN '                                            yep, deflect it
  1450.         IF x < sx1 THEN
  1451.             IF fx1 = 0 THEN fx1 = x: fy1 = LMry(th1)
  1452.             x = fx1 + rf1
  1453.             y = fy1 + rf2
  1454.         ELSE
  1455.             IF fx2 = 0 THEN fx2 = x: fy2 = LMry(th2)
  1456.             x = fx2 - rf1
  1457.             y = fy2 + rf2
  1458.         END IF
  1459.     END IF
  1460.     RETURN
  1461.  
  1462. IF y >= (z - 1) THEN '                                                yep, deflect it
  1463.     IF sy1 < borgt THEN ky1 = 1: GOTO isborg
  1464.     IF eflag = 0 THEN '                                               limit flame climbing
  1465.         eflag = 1 '                                                   only once per position
  1466.         xmin2 = phg - thrust! * 1.5 '                                 point hit ground
  1467.         xmax2 = phg + thrust! * 1.5
  1468.         u1 = 0 '                                                      up count l of nozzle
  1469.         u2 = 0 '                                                      up count r of nozzle
  1470.         wu1 = 0 '                                                     worst l up count
  1471.         wu2 = 0 '                                                     worst r up count
  1472.         ky1 = 0 '                                                     keep y
  1473.         ky2 = 0 '                                                     keep y
  1474.         FOR zz = phg TO phg - h STEP -1 '                             from LM center left
  1475.             z2 = gety(-zz): IF zz = phg THEN lz = z2
  1476.             k1 = z2 - lz
  1477.             lz = z2
  1478.             IF k1 > 0 THEN '                                          down
  1479.                 u1 = 0
  1480.             ELSE
  1481.                 u1 = u1 - k1 '                                        up
  1482.                 IF u1 > wu1 THEN wu1 = u1 '                           worst up
  1483.             END IF
  1484.             IF u1 > 20 THEN xmin2 = zz + 2: EXIT FOR
  1485.             IF ABS(k1) > 20 THEN ky1 = 1 '                            90 degrees TMA etc
  1486.         NEXT zz
  1487.         FOR zz = phg TO phg + h '                                     from LM center right
  1488.             z2 = gety(-zz): IF zz = phg THEN lz = z2
  1489.             k2 = z2 - lz
  1490.             lz = z2
  1491.             IF k2 > 0 THEN '                                          down
  1492.                 u2 = 0
  1493.             ELSE
  1494.                 u2 = u2 - k2 '                                        up
  1495.                 IF u2 > wu2 THEN wu2 = u2 '                           worst up
  1496.             END IF
  1497.             IF u2 > 20 THEN xmax2 = zz - 2: EXIT FOR
  1498.             IF ABS(k2) > 20 THEN ky2 = 1 '                            90 degrees TMA etc
  1499.         NEXT zz
  1500.     END IF
  1501.  
  1502.     isborg:
  1503.     r = thrust! * 2 + (RND - pf!) * 80
  1504.     x = (phg - r) + RND * (r * 2)
  1505.     k = ABS(x - phg + a * 2) / 4
  1506.  
  1507.     tx = x + suri '                                                   McDonalds
  1508.     IF (tx >= sf(5, 0)) AND (tx <= sf(5, 1)) AND (py! > 250) THEN
  1509.         ky1 = 0: ky2 = 0
  1510.     END IF
  1511.  
  1512.     IF (ky1 = 1) OR (ky2 = 1) THEN '                                  keep
  1513.         y = z - RND * k - 1: RETURN
  1514.     END IF
  1515.  
  1516.     x2 = (RND - pf!) * 20
  1517.     IF x < xmin2 THEN x = xmin2 + RND * (xmax2 - xmin2) + x2
  1518.     IF x > xmax2 THEN x = xmin2 + RND * (xmax2 - xmin2) - x2
  1519.  
  1520.     IF (platform > 0) AND (ABS(px! - (pminx + 17)) < 20) THEN
  1521.         y = y - platform
  1522.     ELSE
  1523.         y = gety(-x) - RND * k - 1
  1524.     END IF
  1525.  
  1526.     IF (deflectat > 0) AND (y > deflectat) THEN y = deflectat - (y - deflectat)
  1527.  
  1528. CWceiling: '                                                          car wash
  1529. cwd = ABS((suri + px!) - sf(2, 2)) '                                  car wash distance
  1530. IF ASO THEN szs = 323 ELSE szs = 340 '                                safe zone start
  1531. IF (cwd < 69) AND (sy1 > 304) THEN '                                  lower than top of building
  1532.     IF sy1 >= q4 THEN '                                               touched down inside
  1533.         cc1 = -1
  1534.     ELSEIF sy2 >= q4 THEN '                                           touched down inside
  1535.         cc2 = -1