         Edinburgh IMP77 Compiler - Version 8.4

    1  ! IMP80 TO DO: %realslong
    2  !              %else %if <cond> without the finish/start
    3  ! - report to Bob if wrong.
    4  ! Is .001 valid syntax in Imp or does it have to be 0.001?
    5  
    6  ! Translation of
    7  ! <http://www.cs.brandeis.edu/~storer/LunarLander/LunarLander/LunarLanderListing.jpg>
    8  ! by Jim Storer from FOCAL to C and then to Imp by gtoal#gtoal.com
    9  ! C version is at https://raw.githubusercontent.com/ericeche/lunarlanderc/main/lunarlander.c
   10  
   11  %begin
   12  
   13  !%external %string (255) %fn %spec cli param
   14  !%external %routine %spec readline(%string(255)%name B)
   15  !%external %routine %spec print(%longreal R, %integer B, A)
   16  !%external %integer %fn %spec int pt(%longreal R)
   17  !%external %longreal %fn %spec frac pt(%longreal R)
   18  !%external %longreal %fn %spec sqrt(%longreal R)
   19  
   20  %const %integer TRUE = 1, FALSE = 0
   21  
   22  ! Global variables
   23  !
   24  ! A - Altitude (miles)
   25  ! G - Gravity
   26  ! I - Intermediate altitude (miles)
   27  ! J - Intermediate velocity (miles/sec)
   28  ! K - Fuel rate (lbs/sec)
   29  ! L - Elapsed time (sec)
   30  ! M - Total weight (lbs)
   31  ! N - Empty weight (lbs, Note: M - N is remaining fuel weight)
   32  ! S - Time elapsed in current 10-second turn (sec)
   33  ! T - Time remaining in current 10-second turn (sec)
   34  ! V - Downward speed (miles/sec)
   35  ! W - Temporary working variable
   36  ! Z - Thrust per pound of fuel burned
   37  
   38  %own %longreal A, G, I, J, K, L, M, N, S, T, V, W, Z;
   39  
   40  %own %integer echo input = 0
   41  
   42  %routinespec update lander state
   43  %routinespec apply thrust
   44  
   45  ! Input routines (substitutes for FOCAL ACCEPT command)
   46  %integerfnspec accept real(%longrealname value);
   47  %integerfnspec accept yes or no
   48  %routinespec accept line(%string(*)%name buffer, %integername buffer length)
   49  
   50      ! If --echo is present, then write all input back to standard output.
   51      ! (This is useful for testing with files as redirected input.)
   52      echo input = 1 %if cliparam = "--echo"
   53  
   54      printstring("CONTROL CALLING LUNAR MODULE. MANUAL CONTROL IS NECESSARY"); newline
   55      printstring("YOU MAY RESET FUEL RATE K EACH 10 SECS TO 0 OR ANY VALUE"); newline
   56      printstring("BETWEEN 8 & 200 LBS/SEC. YOU'VE 16000 LBS FUEL. ESTIMATED"); newline
   57      printstring("FREE FALL IMPACT TIME-120 SECS. CAPSULE WEIGHT-32500 LBS"); newlines(3)
   58      
   59      %cycle ;! 01.20 in original FOCAL code
   60          printstring("FIRST RADAR CHECK COMING UP"); newlines(3)
   61          printstring("COMMENCE LANDING PROCEDURE"); newline
   62          printstring("TIME,SECS   ALTITUDE,MILES+FEET   VELOCITY,MPH   FUEL,LBS   FUEL RATE"); newline
   63  
   64          A = 120
   65          V = 1
   66          M = 32500
   67          N = 16500
   68          G = 0.001
   69          Z = 1.8
   70          L = 0
   71  
   72      start turn: ;! 02.10 in original FOCAL code
   73          print(L, 7, 0)
   74          print(int pt(A), 16, 0)  { note integer being automatically converted to longreal - c would require (double) cast except that C's trunc() returns a double }
   75          print(5280 * frac pt(A), 7, 0)
   76          print(3600 * V, 15, 2)
   77          print(M - N, 12, 1)
   78          spaces(6)
   79          
   80      prompt for k:
   81          prompt("K=:")
   82          %integer is valid input
   83          is valid input = accept real(K)
   84          %if is valid input # TRUE %or K < 0 %or 0 < K < 8 %or K > 200 %start
   85              %integer x
   86              printstring("NOT POSSIBLE"); newline
   87              printsymbol('.') %for x = 1, 1, 51
   88              -> prompt for k
   89          %finish
   90  
   91          T = 10
   92  
   93      turn loop:
   94          ! 03.10 in original FOCAL code
   95          %cycle
   96              -> fuel out %if M - N < 0.001
   97              -> start turn %if T < 0.001
   98              S = T
   99              S = (M - N) / K %if N + S * K - M > 0
  100              apply thrust
  101              %exit %if I <= 0
  102              %if V > 0 %and J < 0 %start
  103                  %longreal ZZZ,QQQ,RRR
  104                  ! 08.10 in original FOCAL code
  105                  %cycle
  106                      ! FOCAL-to-C gotcha: In FOCAL, multiplication has a higher
  107                      ! precedence than division.  In C, they have the same
  108                      ! precedence and are evaluated left-to-right.  So the
  109                      ! original FOCAL subexpression `M * G / Z * K` can''t be
  110                      ! copied as-is into C: `Z * K` has to be parenthesized to
  111                      ! get the same result.
  112  
  113                      W = (1 - M * G / (Z * K)) / 2
  114                      S = M * V / (Z * K * (W + sqrt(W * W + V / (2 * Z))))
  115                      apply thrust
  116                      -> loop until on the moon %if I <= 0
  117                      update lander state
  118                      -> turn loop %if -J < 0 %or V <= 0
  119                  %repeat
  120              %finish
  121              update lander state
  122          %repeat
  123  
  124      loop until on the moon: ;! 07.10 in original FOCAL code
  125          %while S >= 0.005 %cycle
  126              S = 2 * A / (V + sqrt(V * V + 2 * A * (G - Z * K / M)))
  127              apply thrust
  128              update lander state
  129          %repeat
  130          -> on the moon
  131  
  132      fuel out: ;! 04.10 in original FOCAL code
  133          printstring("FUEL OUT AT ")
  134          print(L, 8, 2)
  135          printstring("SECS"); newline
  136          S = (sqrt(V * V + 2 * A * G) - V) / G
  137          V = V + G * S
  138          L = L + S
  139  
  140      on the moon: ;! 05.10 in original FOCAL code
  141          printstring("ON THE MOON AT ")
  142          print(L, 8, 2)
  143          printstring(" SECS"); newline
  144          W = 3600 * V
  145          printstring("IMPACT VELOCITY OF ")
  146          print(W, 8, 2)
  147          printstring(" M.P.H."); newline
  148          printstring("FUEL LEFT: ")
  149          print(M - N, 8, 2)
  150          printstring(" LBS"); newline
  151          %if W <= 1 %start
  152              printstring("PERFECT LANDING !-(LUCKY); newline")
  153          %finish %else %if W <= 10 %start
  154              printstring("GOOD LANDING-(COULD BE BETTER); newline")
  155          %finish %else %if W <= 22 %start
  156              printstring("CONGRATULATIONS ON A POOR LANDING"); newline
  157          %finish %else %if W <= 40 %start
  158              printstring("CRAFT DAMAGE. GOOD LUCK"); newline
  159          %finish %else %if W <= 60 %start
  160              printstring("CRASH LANDING-YOU'VE 5 HRS OXYGEN"); newline
  161          %finish %else %start
  162              printstring("SORRY,BUT THERE WERE NO SURVIVORS-YOU BLEW IT!"); newline
  163              printstring("IN FACT YOU BLASTED A NEW LUNAR CRATER ")
  164              print(W * 0.277777, 8, 2)
  165              printstring(" FT. DEEP"); newline
  166          %finish
  167  
  168          newlines(3)
  169          prompt("TRY AGAIN?")
  170      %repeat %until %not accept yes or no = TRUE
  171  
  172      printstring("CONTROL OUT"); newlines(3)
  173      
  174      %stop
  175  
  176  
  177  ! Subroutine at line 06.10 in original FOCAL code
  178  %routine update lander state
  179      L = L + S
  180      T = T - S
  181      M = M - S * K
  182      A = I
  183      V = J
  184  %end
  185  
  186  ! Subroutine at line 09.10 in original FOCAL code
  187  %routine apply thrust
  188      %longreal Q, Q 2, Q 3, Q 4, Q 5
  189      Q = S * K / M
  190      Q 2 = Q * Q
  191      Q 3 = Q 2 * Q
  192      Q 4 = Q 3 * Q
  193      Q 5 = Q 4 * Q
  194  
  195      J = V + G * S + Z * (-Q - Q 2 / 2 - Q 3 / 3 - Q 4 / 4 - Q 5 / 5)
  196      I = A - G * S * S / 2 - V * S + Z * S * (Q / 2 + Q 2 / 6 + Q 3 / 12 + Q 4 / 20 + Q 5 / 30)
  197  %end
  198  
  199  ! Read a floating-point value from stdin.
  200  !
  201  ! Returns 1 on success, or 0 if input did not contain a number.
  202  !
  203  ! Calls exit(-1) on EOF or other failure to read input.
  204  %integerfn accept real(%longrealname value)
  205      %string (255) buffer
  206      %integer buffer length
  207      buffer length = 0
  208      accept line(buffer, buffer length)
  209      %integer is valid input
  210      read(value)
  211      !is valid input = 0 %if is valid input # 1 
  212          %result = TRUE; !is valid input
  213  %end
?ISVALIDINPUT unused
  214  
  215  ! Reads input and returns 1 if it starts with 'Y' or 'y', or returns 0 if it
  216  ! starts with 'N' or 'n'.
  217  !
  218  ! If input starts with none of those characters, prompt again.
  219  !
  220  ! If unable to read input, calls exit(-1)
  221  %integerfn accept yes or no
  222      %integer result
  223      result = -1
  224      %cycle
  225          prompt("(ANS. YES OR NO):")
  226          %string (255) buffer; buffer = ""
  227          %integer buffer length
  228          buffer length = 0
  229          accept line(buffer, buffer length)
  230  
  231          %if buffer length > 0 %start
  232              %switch case('N':'y')
  233              -> case(charno(buffer,1))
  234              case('y'):
  235              case('Y'):
  236                  %result = 1
  237  
  238              case('n'):
  239              case('N'):
  240                  %result = 0
  241  
  242              case(*):
  243          %finish
  244  
  245      %repeat %until result >= 0
  246  
  247      %result = result
  248  %end
  249  
  250  ! Reads a line of input.  Caller is responsible for calling free() on the
  251  ! returned buffer.
  252  !
  253  ! If unable to read input, calls exit(-1).
  254  %routine accept line(%string(*)%name buffer, %integername buffer length)
  255      %on %event 9 %start
  256          newline; printstring("END OF INPUT"); newlines(2)
  257          %stop
  258      %finish
  259      readline(buffer)
  260      %if echo input=TRUE %start
  261          printstring(buffer); newline
  262      %finish
  263      buffer length = length(buffer)
  264  %end
  265  
  266  %endofprogram
?RRR unused
?QQQ unused
?ZZZ unused
?FALSE unused

  182 Statements compiled
