Lunar Lander for 1.0.6

Hi Arduino Forum, I'm trying to follow the old Lunar Lander thread, found here: http://forum.arduino.cc/index.php?topic=8688.0

That sure looks like fun! I remember I had the games for basic book years ago, and it'd be great to play Lander again through an Uno! No need to dig out the old "Trash 80"! (Radio Shack TRS80, with a whole 80KB of memory for the younger crowd)

Upon downloading the code from the thread, it will not verify. I tried changing the BYTE items to Serial.write, and got it to the point of verifying but on running, it doesn't go past displaying the fuel burn rate. On the basis of the code shown in the thread, can anyone give me precise advice on what needs to be changed to make it compatible with IDE 1.0.6?

Thanks for any help!! -Nick

Hi, Welcome to the forum.

Have you tried a later version of the IDE? You can store many different versions on your computer at anytime.

What OS are you running?

Tom.. :)

Hi Tom, Thanks for replying! My OS is windows vista, 2007 (I get stuck with the familys' hand-me-down laptops).

Is it likely that Lunar Lander will work on a newer IDE? I did not know I could have multiple IDE's available on the computer at the same time...I've had some adventures with IR Remote sketches that worked great on an older IDE and quit when switching to 1.0.6, so I try to stick with one.

-Nick

nickcinquino: My OS is windows vista, 2007 (I get stuck with the familys' hand-me-down laptops). Is it likely that Lunar Lander will work on a newer IDE?

No, that Lunar lander from the year-2010-Arduino forums-thread will not run flawlessly anywhere. Though the code will compile error-free with IDE double zero versions likeArduino-IDE 0019 or Arduino-IDE0022, it will not run in IDE version 1.0 or above, since the BYTE parameter with Serial.print is not supported since IDE 1.0 and above.

Besides of that the port to Arduinp must be wrong or better to say "miserably wrong": After removing "BYTE" with print, the code compiles. BUT: - Serial is not printing correct flight status report output for vertical velocity, fuel burning rate and height as it should. If you like: I'd give it a try and do a newly created Arduino version from scratch instead trying to fix the non-vunctional year-2010 version which was posted in this gforum six years ago.

Hi,
Try this, you will need to select “Carriage Returrn” as well as 115200baud.
It has a error message on the monitor when you run the monitor but it doesn’t stop the code.

10 PRINT TAB(33);"LUNAR"
20 PRINT TAB(l5);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" 
25 PRINT:PRINT:PRINT
30 PRINT "THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR" 
40 PRINT "LANDING CAPSULE.": PRINT: PRINT
50 PRINT "THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY" 
60 PRINT "XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY."
70 PRINT: PRINT "SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN" 
80 PRINT "0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND." 
90 PRINT "SET NEW BURN RATE EVERY 10 SECONDS.": PRINT 
100 PRINT "CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS."
110 PRINT: PRINT: PRINT: PRINT "GOOD LUCK"
120 L=0
130 PRINT: PRINT "SEC","MI + FT","MPH","LB FUEL","BURN RATE":PRINT 
140 A=120:V=1:M=33000:N=16500:G=1E-03:Z=1.8
150 PRINT L,INT(A);INT(5280*(A-INT(A))),3600*V,M-N,:INPUT K:T=10 
160 IF M-N<1E-03 THEN 240
170 IF T<1E-03 THEN 150
180 S=T: IF M>=N+S*K THEN 200
190 S=(M-N)/K
200 GOSUB 420: IF I<=O THEN 340
210 IF V<=0 THEN 230
220 IF J<0 THEN 370
230 GOSUB 330: GOTO 160
240 PRINT "FUEL OUT AT";L;"SECONDS":S=(-V+SQR(V*V+2*A*G))/G
250 V=V+G*S: L=L+S
260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH" 
274 IF W<=1.2 THEN PRINT "PERFECT LANDING!": GOTO 440 
280 IF W<=10 THEN PRINT "GOOD LANDING (COULD RE BETTER)":GOTO 440 
282 IF W>60 THEN 300
284 PRINT "CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE" 
286 PRINT "PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!" 
288 GOTO 440
300 PRINT "SORRY THERE NERE NO SURVIVORS. YOU BLOW IT!"
310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"
320 GOTO 440
330 L=L+S: T=T-S: M=M-S*K: A=I: V=J: RETURN
340 IF S<5E-03 THEN 260
350 D=V+SQR(V*V+2*A*(G-Z*K/M)):S=2*A/D
360 GOSUB 420: GOSUB 330: GOTO 340
370 W=(1-M*G/(Z*K))/2: S=M*V/(Z*K*(W+SQR(W*W+V/Z)))+.05:GOSUB 420
380 IF I<=0 THEN 340
390 GOSUB 330: IF J>0 THEN 160
400 IF V>0 THEN 370
410 GOTO 160
420 Q=S*K/M: J=V+G*S+Z*(-Q-Q*Q/2-Q^3/3-Q^4/4-Q^5/5)
430 I=A-G*S*S/2-V*S+Z*S*(Q/2+Q^2/6+Q^3/12+Q^4/20+Q^5/30):RETURN
440 PRINT:PRINT:PRINT:PRINT "TRY AGAIN??": GOTO 70

It compiled and loaded with IDE 1.6.7

Looks like fun to play with, I did similar with VIC20 many many years ago, it would be interesting to use Processing as an HMI and make a Lander Control Panel Environment.

Tom… :slight_smile:
PS Must change to SI units.

Try this, ... It compiled and loaded with IDE 1.6.7 [/quote]

Are you sure?= IDE 1.6.7 does not only compile C++, but also BASIC programming language code, really?

IMHO The code included in reply #4 ist NOT AN ARDUINO SKETCH CODE. I'd be very surprized if it compiles and runs in any version of Arduino. Can anybody confirm?

I think Tom was joking. Here is what happens when 1.6.11 is asked to compile a BASIC program:

Arduino: 1.6.11 (Windows 7), Board: "Arduino Pro or Pro Mini, ATmega328 (5V, 16 MHz)"

sketch_oct27a:1: error: expected unqualified-id before numeric constant

 10 PRINT TAB(33);"LUNAR"

 ^

sketch_oct27a:1: error: expected unqualified-id before string constant

 10 PRINT TAB(33);"LUNAR"

                  ^

sketch_oct27a:2: error: expected unqualified-id before string constant

 20 PRINT TAB(l5);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"

                  ^

sketch_oct27a:16: error: expected constructor, destructor, or type conversion before '(' token

 150 PRINT L,INT(A);INT(5280*(A-INT(A))),3600*V,M-N,:INPUT K:T=10

                       ^

sketch_oct27a:25: error: 'L' does not name a type

 240 PRINT "FUEL OUT AT";L;"SECONDS":S=(-V+SQR(V*V+2*A*G))/G

                         ^

sketch_oct27a:25: error: expected unqualified-id before string constant

 240 PRINT "FUEL OUT AT";L;"SECONDS":S=(-V+SQR(V*V+2*A*G))/G

                           ^

sketch_oct27a:27: error: 'L' does not name a type

 260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH"

                                  ^

sketch_oct27a:27: error: expected unqualified-id before string constant

 260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH"

                                    ^

sketch_oct27a:27: error: 'W' does not name a type

 260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH"

                                                                ^

sketch_oct27a:27: error: expected unqualified-id before string constant

 260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH"

                                                                  ^

sketch_oct27a:35: error: 'W' does not name a type

 310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"

                                                     ^

sketch_oct27a:35: error: expected unqualified-id before string constant

 310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"

                                                            ^

exit status 1
expected unqualified-id before numeric constant

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

it would be interesting to use Processing as an HMI and make a Lander Control Panel Environment.

When you have it running, why not improve it and make it "more Arduino" with a pot for engine burn control, an LCD display for instructions and 7seg or bar graph displays for height, velocity, remaining fuel etc.

Hi PaulRB, Yes! Thats a great idea...a small joystick module with spring return to zero, so then the simulation is running in real time, better keep an eye on that speed, altitude and fuel remaining!

I'd like to try that with the 2.4" TFT LCD shield. With the Adafruit libraries, the joystick can be applied to A5. Divide the analogRead value by 5 so we have 0-200 lbs/sec. Display bargraphs or line charts.

Does anyone know what needs to be done to remove all the BYTE items and Serial.write to change the lunar lander sketch to intake the lbs/sec burn to an integer from the pot at A5? Thanks!!

-Nick

Hi Arduino Forum, For everyone interested in this thread, I wondered if the initial conditions of the Lunar Lander game were relatively accurate, things like spacecraft initial weight and fuel weight. From this NASA/Grumman document, it looks like it is!

https://www.hq.nasa.gov/alsj/LM04_Lunar_Module_ppLV1-17.pdf

-Nick

Whooopssss…

void setup()
{
  Serial.begin(115200);
  delay(1000);
  Serial.println("\t\t\t\t LUNAR");
  Serial.println("\t       CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
//  Serial.println("\n\n");
  Serial.println("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR");
  Serial.println("LANDING CAPSULE.\n");
  Serial.println("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY");
  Serial.println("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.");
}

float L, A, V, M, N, G, Z, K, T, S, W, I, J;

float input(char *p)
{
  int ans;
  byte n;

restart:
  ans = 0;
  if (p == NULL)
    Serial.print("? ");
  else
    Serial.print(p);

  for (;;)
  {
    if (Serial.available())
    {
      n = Serial.read();
      Serial.print(n, 0);
      if ((n == '\r') || (n == '\n'))
      {
        Serial.println();
        break;
      }
      else if (n == '\010')       // backspace
      {
        Serial.print(" \010");
        ans /= 10;
      }
      else if (isdigit(n))
      {
        ans = ans * 10 + (n - '0');
      }
      else
      {
        Serial.println("\n\rERROR: BAD INPUT.  TRY AGAIN");
        goto restart;
      }
    }
  }
  return (float)ans;
}


void landing()
{
  W = 3600.0 * V;
  Serial.print("ON MOON AT ");
  Serial.print(L);
  Serial.print(" SECONDS - IMPACT VELOCITY ");
  Serial.print(W);
  Serial.println(" MPH");

  if (W <= 1.2)
    Serial.println("PERFECT LANDING!");
  else if (W <= 10.0)
    Serial.println("GOOD LANDING (COULD BE BETTER)");
  else if (W <= 60.0)
  {
    Serial.println("CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE");
    Serial.println("PARTY ARRIVES.  HOPE YOU HAVE ENOUGH OXYGEN!");
  }
  else
  {
    Serial.println("SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!");
    Serial.print("IN FACT, YOU BLASTED A NEW LUNAR CRATER ");
    Serial.print(W * 0.277);
    Serial.println(" FEET DEEP!");
  }

  Serial.println("\n\n\nTRY AGAIN?");
}

void sub420()
{
  float q, q2, q3, q4, q5;

  q  = S * K / M;
  q2 = q * q;
  q3 = q * q2;
  q4 = q * q3;
  q5 = q * q4;

  J = V + G * S + Z * (-q - (q2 / 2.0) - (q3 / 3.0) - (q4 / 4.0) - (q5 / 5.0));
  I = A - G * S * S / 2.0 - V * S + Z * S * (q / 2.0 + q2 / 6.0 + q3 / 12.0 + q4 / 20.0 + q5 / 30.0);
}

void sub330()
{
  L += S;
  T -= S;
  M -= S * K;
  A = I;
  V = J;
}

void sub340()
{
  float D;
  for ( ; S >= 5.0e-3; )  // line 340
  {
    D = V + sqrt(V * V + 2.0 * A * (G - Z * K / M));
    S = 2.0 * A / D;
    sub420();
    sub330();
  }
}

void loop()
{
  char line[80];

  Serial.println("\nSET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN");
  Serial.println("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.");
  Serial.println("SET NEW BURN RATE EVERY 10 SECONDS.\n");
  Serial.println("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.");
  Serial.println("\n\n\nGOOD LUCK");
  L = 0;
  Serial.println("\nSEC\tMI + FT \tMPH\tLB FUEL\t\tBURN RATE\n");
  A = 120.0; V = 1.0; M = 33000.0; N = 16500.0; G = 1.0e-3; Z = 1.8;

  for (;;)                          // line 150
  {
    sprintf(line, " %-d\t %d  %-4d\t %d\t %d\t\t",
            (int)L, (int)floor(A),
            (int)floor(5280.0 * (A - floor(A))),
            (int)(3600.0 * V), (int)(M - N));
    Serial.print(line);
    K = input(NULL);
    T = 10.0;

    for (;;)                      // line 160
    {
      if ((M - N) < 1.0e-3)
      {
        Serial.print("FUEL OUT AT ");
        Serial.print(L);
        Serial.println(" SECONDS");
        S = (-V + sqrt(V * V + 2 * A * G)) / G;
        V += G * S;
        L += S;
        landing();
        return;      // Game over, Man!
      }

      if (T < 1.0e-3)  // line 170
        break;

      S = T;
      if (M < (N + S * K))
        S = (M - N) / K;

      sub420();
      if (I <= 0.0)
      {
        sub340();
        landing();
        return;
      }

      if ((V <= 0.0) || (J >= 0.0))
      {
        sub330();
        continue;     // back to line 160
      }

      // line 370
      do
      {
        W = (1.0 - M * G / (Z * K)) / 2.0;
        S = M * V / (Z * K * (W + sqrt(W * W + V / Z))) + 0.05;
        sub420();

        if (I <= 0.0)
        {
          sub340();
          landing();
          return;
        }

        sub330();
        if (J > 0.0)
          break;
      }
      while (V > 0.0);
    }
  }
}

Brain fade, hayfever and not enough sleep. (I’ve become a Step-Grandad, all well, although I doubt Step_Grandad, lol)
Tom… :neutral_face:
PS. Thanks Nick, that is what I have been looking for.

TomGeorge: nks Nick, that is what I have been looking for.

Did you have a look at the code you posted? At first glance this line of pure nonsense jumps into my eyes:

while (V > 0.0);

This do-nothing-while-loop will either never execute and do nothing or execute infinitely and do nothing (Depends on the initial value of the V variable which never ever changes within the while-loop.

That is a do-while loop, and V is indeed modified elsewhere.

Lots of interesting Taylor series approximations in this code!

      do
      {
        W = (1.0 - M * G / (Z * K)) / 2.0;
        S = M * V / (Z * K * (W + sqrt(W * W + V / Z))) + 0.05;
        sub420();

        if (I <= 0.0)
        {
          sub340();
          landing();
          return;
        }

        sub330();
        if (J > 0.0)
          break;
      }
      while (V > 0.0);

jurs: Did you have a look at the code you posted? At first glance this line of pure nonsense jumps into my eyes:

while (V > 0.0);

This do-nothing-while-loop will either never execute and do nothing or execute infinitely and do nothing (Depends on the initial value of the V variable which never ever changes within the while-loop.

Hey I didn't write it, I got it to basically work. (pun intended) Tom.... :)

TomGeorge: Hey I didn't write it, I got it to basically work.

You got it to work?

Did you manage to simulate a soft landing on the moon with that Arduino sketch code? If yes: Can you provide examples for fuel burning rates to use for a soft landing ?

Hi Tom, Jurs, JRemington and PaulRB, Thanks for the continued research, and posting code! The new one does verify but does the same thing on my system (allows the fuel burn rate setting to be entered but then goes no further, no update of speed, weight,etc). Is the IDE critical? Which IDE is best to use?

Would it greatly simplify things to remove all of the serial.Write data inputs and input an integer from a pot at A5 instead? I've started looking up the essential equations needed to write a new version from scratch...this could take a while!

-Nick

The C code that Tom posted does not work on Arduino 1.6.11 – the baud rate of the serial monitor keeps getting reset, somehow.

See this page for a discussion of how the original BASIC program works (not completely understood, although it uses simple numerical integration to solve the rocket equation of motion) http://www.hpmuseum.org/forum/archive/index.php?thread-4532.html

I was puzzled by one of the Maclaurin series in the code and wanted to take a closer look, so I took a few minutes to modify Tom’s code to run on a standard C system (I used Code::Blocks to make a console application on Windows). It works fine, and reminds me of the frustration I had playing this game many years ago on an HP calculator!

Does anyone recognize this series?

f(x) = x/2 + x^3/6 + x^3/12 + x^4/20 + x^5/30 + …

term rule: X^n/(n*(n+1)), similar to e^x-1 over the interval {0,1}

Here is the running, crudely lashed up code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void setup(void);
void loop(void);

int main(void)
{
     setup();
     while(1) loop();
     return 0;
}

void setup()
{
  printf("\t\t\t\t LUNAR");
  printf("\t       CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
//  printf("\n\n");
  printf("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR\n");
  printf("LANDING CAPSULE.\n");
  printf("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY\n");
  printf("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.\n");
}

float L, A, V, M, N, G, Z, K, T, S, W, I, J;

void landing()
{
    int in;
  W = 3600.0 * V;
  printf("ON MOON AT %6.2f SECONDS - IMPACT VELOCITY %6.2f MPH\n",L,W);

  if (W <= 1.2)
    printf("PERFECT LANDING\n");
  else if (W <= 10.0)
    printf("GOOD LANDING (COULD BE BETTER)\n");
  else if (W <= 60.0)
  {
    printf("CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE\n");
    printf("PARTY ARRIVES.  HOPE YOU HAVE ENOUGH OXYGEN!\n");
  }
  else
  {
    printf("SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!\n");
    printf("IN FACT, YOU BLASTED A NEW LUNAR CRATER %6.2f FEET DEEP!\n", W*0.277);
   }

  printf("\nTRY AGAIN? 0/1 ");
  scanf("%d",&in);
  if (in == 0) exit(0);
}

void sub420()
{
  float q, q2, q3, q4, q5;

  q  = S * K / M;
  q2 = q * q;
  q3 = q * q2;
  q4 = q * q3;
  q5 = q * q4;

  J = V + G * S + Z * (-q - (q2 / 2.0) - (q3 / 3.0) - (q4 / 4.0) - (q5 / 5.0));  //log(1-q)
  I = A - G * S * S / 2.0 - V * S + Z * S * (q / 2.0 + q2 / 6.0 + q3 / 12.0 + q4 / 20.0 + q5 / 30.0);
}

void sub330()
{
  L += S;  //total time
  T -= S;  //burn time
  M -= S * K;  //total mass
  A = I; //altitude
  V = J; //velocity
}

void sub340()
{
  float D;
  for ( ; S >= 5.0e-3; )  // line 340
  {
    D = V + sqrt(V * V + 2.0 * A * (G - Z * K / M));
    S = 2.0 * A / D;
    sub420();
    sub330();
  }
}

void loop()
{

  printf("\nSET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN\n");
  printf("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.\n");
  printf("SET NEW BURN RATE EVERY 10 SECONDS.\n");
  printf("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.\n");
  printf("\n\n\nGOOD LUCK\n");
  L = 0;
  printf("\nSEC\t MI + FT \t MPH\t LB FUEL\n");
  A = 120.0; V = 1.0; M = 33000.0; N = 16500.0; G = 1.0e-3; Z = 1.8;

  for (;;)                          // line 150
  {
    printf(" %-d\t %d  %-4d\t %d\t %d\t\t",
            (int)L, (int)floor(A),
            (int)floor(5280.0 * (A - floor(A))),
            (int)(3600.0 * V), (int)(M - N));
    printf("\nburn? ");
    scanf("%f",&K);

    T = 10.0;  //time step

    for (;;)                      // line 160
    {
      if ((M - N) < 1.0e-3)
      {
        printf("FUEL OUT AT %6.2f SECONDS\n",L);
        S = (-V + sqrt(V * V + 2 * A * G)) / G;
        V += G * S;
        L += S;
        landing();
        return;      // Game over, Man!
      }

      if (T < 1.0e-3)  // line 170
        break;

      S = T;
      if (M < (N + S * K)) S = (M - N) / K;  //seconds left (fuel/burn rate)

      sub420();
      if (I <= 0.0)
      {
        sub340();
        landing();
        return;
      }

      if ((V <= 0.0) || (J >= 0.0))
      {
        sub330();
        continue;     // back to line 160
      }

      // line 370
      do
      {
        W = (1.0 - M * G / (Z * K)) / 2.0;
        S = M * V / (Z * K * (W + sqrt(W * W + V / Z))) + 0.05;
        sub420();

        if (I <= 0.0)
        {
          sub340();
          landing();
          return;
        }

        sub330();
        if (J > 0.0)
          break;
      }
      while (V > 0.0);
    }
  }
}

Nick, this is all getting a bit confusing! Post the code you are now trying to run. IDE version should not be critical at all.

IDE version should not be critical at all.

Please try the version Tom posted, with any IDE. It compiles without error but [u]does not work[/u] using 1.6.11. I have not tried it with 1.0.6.

Edit: I just tried again with the original code and IDE version 1.6.11. Now it does work. I don't know what went wrong the first time. Sorry for the confusion.

Note that for number input to work, you have to set the serial monitor to transmit carriage return.

You guys that seem to not have anything working aren’t doing something silly like forgetting to set the IDE serial monitor line ending to newline?