Lunar lander: a classic in a new dress

Post Reply
Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Lunar lander: a classic in a new dress

Post by Henko »

option base 1 ! option angle degrees
dim lander_x(15),lander_y(15),lx(15),ly(15)

gosub init_prog
fuel=select_level(bmin)
create_gauges(fuel,height,velocity,gas)
draw_poly(14,lx,ly,120,910-3*height/10,0,0,0,0,2)
button "start" title "start" at 324,80 size 120,40
start:
if button_pressed("start")=0 then start
button "start" delete

decending:         ' check controls
tx=touch_x(0)
if tx>-1 then
  ty=touch_y(0)
  gas=slider("throttle",600,280,400,tx,ty,0)
  end if
if button_pressed("real") then ttt=1000
if button_pressed("fast") then ttt=ttt/2
if timer()<ttt then decending
reset timer

' flight model (time step is fixed on 1 second)
thrust=gas*maxthrust/100 ! if fuel=0 then thrust=0
df=thrust/2000 ! fuel=fuel-df ! if fuel<0 then fuel=0
fv=thrust-weight-fuel ! acc=fv*gravity/(weight+fuel)
dv=acc ! velocity=velocity+dv
dh=velocity-dv/2 ! height=height+dh ! if height<0 then height=0

' update gauges
rmeter("fuel","g",384,260,120,0,400,fuel,0)
rmeter("meter","r",384,520,120,0,4000,height,0)
rmeter("m/sec","b",384,780,120,-200,200,velocity,0)

' update moon module
draw_poly(14,lx,ly,120,910-3*height/10,velocity,0,0,0,2)

' check on landing
if height>0 then goto decending else landed(velocity)
end


def select_level(bmin)
draw text "select difficulty level" at 260,10
button "easy" title "easy" at 200,40 size 120,30
button "medi" title "medium" at 340,40 size 120,30
button "diff" title "difficult" at 480,40 size 120,30
loop1: level=0
if button_pressed("easy") then level=1
if button_pressed("medi") then level=2
if button_pressed("diff") then level=3
if level=0 then loop1
button "easy" delete ! button "medi" delete ! button "diff" delete
fill rect 260,10 to 560,32
if level=1 then
  draw text "easy level" at 320,40 ! select_level=1.6*bmin
  else
  if level=2 then
    draw text "medium level" at 310,40 ! select_level=1.3*bmin
    else
    draw text "difficult level" at 290,40 ! select_level=1.1*bmin
    end if
  end if
end def

def create_gauges(b,h,v,gas)
rmeter("fuel","g",384,260,120,0,400,b,1)
rmeter("meter","r",384,520,120,0,4000,h,1)
rmeter("m/sec","b",384,780,120,-200,200,v,1)
slider ("throttle",600,280,400,0,0,1)
draw text "sim-speed" at 590,100
button "real" title "real time" at 525,130 size 100,30
button "fast" title "x2" at 645,130 size 100,30
fill color 0,0,0
fill rect 90,957.5 to 170,970 ! fill rect 110,947.5 to 150,958
fill color .8,.8,.8
end def

def landed(v)
draw font size 15
if v<-20 then 
  draw text "You made a mess of it! All destroyed and dead." at 180,930
  return
  end if
if v<-15 then
  draw text "You crashed! Module destroyed, you severely wounded (and alone!)" at 180,930
  return
  end if
if v<-10 then 
  draw text "bad landing. Module is damaged, you are lightly wounded." at 180,930
  return
  end if
if v<-5 then
  draw text "Fair landing! At least you are able to return." at 180,930
  return
  end if
if v<-2 then
  draw text "You're an ace! Return to earth to recieve Medal of Honour!" at 180,930
  return
  end if
end def

def slider (tit$,xt,yt,hgt,xtouch,ytouch,ind)
xb=xt+70 ! if hgt<120 then hgt=120 ! yb=yt+hgt+70 ! dy=hgt/10
if ind=-1 then
  fill rect xt-2,yt-2 to xb+2,yb+2 ! return
  end if
if ind=1 then
  draw size 3 ! draw font size 14
  draw rect xt,yt to xb,yb
  draw line xt,yt+20 to xb,yt+20
  draw text tit$ at xt+(68-8*len(tit$))/2,yb-20
 '  ys=yb-30 ! ys=560
  else
  if xtouch<xt or xtouch>xb or ytouch<yt or ytouch>yb then
    slider=-1
    return
    end if
  ys=ytouch
  if ys<yt+40 then ys=yt+40 ! if ys>yb-30 then ys=yb-30
  end if
draw size 2
graphics lock
fill color .8,.8,.8 ! draw font size 14
fill rect xt+2,yt+33 to xb-2,yb-25
draw rect xt+28,yt+40 to xt+32,yb-30
y=yb-30+dy
for i=0 to 100 step 10
  y=y-dy ! i$=i
  draw line xt+24,y to xt+36,y
  draw text i$ at xt+40,y-9
  next i
fill color 0,0,.6 ! fill alpha .6
fill rect xt+6,ys-4 to xt+54,ys+4
fill color .8,.8,.8 ! fill alpha 1
tt=(yb-ys-30)*100/(yb-yt-70)
fill rect xt+8,yt+2 to xb-2,yt+15
draw text n2a$(tt,5,1) at xt+8,yt
graphics unlock
draw font size 20
slider=tt
end def

def set_col(col$)
if col$="r" or col$="R" then
  draw color 1,0,0 ! fill color 1,0,0
  end if
if col$="g" or col$="G" then
  draw color 0,.7,0 ! fill color 0,.7,0
  end if
if col$="b" or col$="B" then
  draw color 0,0,1 ! fill color 0,0,1
  end if
if col$="n" or col$="N" then
  draw color 0,0,0 ! fill color .8,.8,.8
  end if
enddef

def rmeter(tit$,col$,xc,yc,rad,minval,maxval,val,mode)
if mode=-1 then
  fill circle xc,yc size rad+2
  return
  end if
graphics lock
  if mode=0 then mode_0
  set_col("n")
  draw size 3 ! draw circle xc,yc size rad
  draw size 4 ! draw circle xc,yc size rad-6
  set_col(col$)
  draw size 3 ! draw circle xc,yc size rad-3
  set_col("n")
  draw arc xc,yc,rad-50,130,410
  draw size 3
  for a=130 to 410 step 28
    xs=xc+(rad-50)*cos(a) ! ys=yc+(rad-50)*sin(a)
    xe=xc+(rad-42)*cos(a) ! ye=yc+(rad-42)*sin(a)
    draw line xs,ys to xe,ye
    next a
  draw size 1
  for a=130 to 410 step 7
    xs=xc+(rad-50)*cos(a) ! ys=yc+(rad-50)*sin(a)
    xe=xc+(rad-44)*cos(a) ! ye=yc+(rad-44)*sin(a)
    draw line xs,ys to xe,ye
    next a
  delta=(maxval-minval)/10 ! sval=minval
  draw font size 15
  for a=130 to 410 step 28
    xs=xc+(rad-28)*cos(a)-22 ! ys=yc+(rad-28)*sin(a)-10
    draw text n2a$(sval,3,0) at xs,ys
    sval=sval+delta
    next a
  draw font size 20
mode_0:
  fill circle xc,yc size rad-52
  xs=xc+(rad-80)*cos(112) ! ys=yc+(rad-80)*sin(112)
  set_col(col$)
  fill circle xc,yc size 10 ! draw text tit$ at xs-12,ys
  set_col("n")
  if val<minval then val=minval
  if val>maxval then val=maxval
  beta=130+280*(val-minval)/(maxval-minval)
  xs=xc-30*cos(beta) ! ys=yc-30*sin(beta)
  xe=xc+(rad-54)*cos(beta) ! ye=yc+(rad-54)*sin(beta)
  draw size 6 ! draw line xs,ys to xe,ye
graphics unlock
end def

def draw_poly(n,x(),y(),x_pos,y_pos,v,r,g,b,thick)
draw color r,g,b ! draw size thick
graphics lock
if v<0 then v=0
fill rect x_pos-1,y_pos+38+v to x_pos+21,y_pos-60
n=n+1 ! x(n)=x(1) ! y(n)=y(1)
xs=x(1)+x_pos ! ys=y(1)+y_pos
for i=2 to n
xe=x(i)+x_pos ! ye=y(i)+y_pos
draw line xs,ys to xe,ye ! xs=xe ! ys=ye
next i
graphics unlock
end def

def n2a$(num,lang,dec)
b$="               "
fac=10^dec
num$=int(fac*num+.5)/fac
tot=lang-len(num$)
if tot<1 then tot=1
a$=substr$(b$,1,tot) & num$
n2a$=a$
end def

def test (in$,in)
fill rect 30,900 to 400,940
a$="test " & in$ & in
draw text a$ at 30,900
button "cont" title "doorgaan ?" at 440,890
loopje:
if button_pressed("cont")=0 then goto loopje
button "cont" delete
fill rect 30,900 to 400,940
end def

init_prog:
randomize
graphics ! fill color .8,.8,.8 ! draw color 0,0,0
graphics clear .8,.8,.8
height=2300+rnd(700) ! velocity=-rnd(40)
fac=.5 ! np=14
for i=1 to np
  read lander_x(i),lander_y(i)
  lx(i)=fac*lander_x(i) ! ly(i)=fac*(75-lander_y(i))
  next i
data 20,0, 30,0, 30,25, 40,15, 40,0, 30,5, 30,55
data 20,75, 10,55, 10,5, 0,0, 0,15, 10,25, 10,0
read weight,fuel,gravity,maxthrust,gas
data 2000,100,1.6,4000,50
bmin=maxthrust*(weight+100)*sqrt(1.6*height+.5*velocity^2)
bmin=bmin/3200/(maxthrust-weight-100)
ttt=1000 ! reset timer
return

User avatar
Mr. Kibernetik
Site Admin
Posts: 4786
Joined: Mon Nov 19, 2012 10:16 pm
My devices: iPhone, iPad, MacBook
Location: Russia
Flag: Russia

Re: Lunar lander: a classic in a new dress

Post by Mr. Kibernetik »

I think that illuminator on a ship will be a cool upgrade. Also exhaust fire will add some interaction.
And time indicator will add some competition...

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Lunar lander: a classic in a new dress

Post by Henko »

Mr. Kibernetik wrote:I think that illuminator on a ship will be a cool upgrade. Also exhaust fire will add some interaction.
And time indicator will add some competition...
Anybody to add these thingies? Or one or two of them?

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Lunar lander: a classic in a new dress

Post by GeorgeMcGinn »

Before I posted my version of the Lunar Lander, or as it was called LEM, I tried this program and I had to work through a number of errors. Now I am getting a RESET not a valid command.

Was this one of the commands made obsolete, or does it need to be formatted differently.

The other issues I found were invalid characters. For example, the IF fuel<0 then fuel=0 got a syntax error, and only after I retyped it exactly as it was did it work. That tells me there might have been an invalid HEX character that I removed when I retyped it.

I know this was posted many years ago, so if you are inclined to see why it does not work for me, that fine. Either way.

The game I am going to post is one written in the 1970's that I converted to work in SmartBASIC. It has the line numbers but since it was written in TRS-80 BASIC, it needed some modifications. It is a text-based program, as most of them were back then.

Here is the code to my version of LEM (Or a version of Lunar Lander).

Code: Select all

2 PRINT TAB(34);"LEM"
4 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
5 REM ADDED PRINT FORMATTING, HEADERS, AND DESCRIPTIVE QUESTIONS (GEORGE MCGINN)
6 REM OTHERWISE, THIS PROGRAM WORKED WITHOUT MAKING ANY OTHER CHANGES.
7 REM ROCKT2 IS AN INTERACTIVE GAME THAT SIMULATES A LUNAR
8 REM LANDING IS SIMILAR TO THAT OF THE APOLLO PROGRAM.
9 REM THERE IS ABSOLUTELY NO CHANCE INVOLVED

TT$="####"
HF$="### ###"
DL$="############"
VV$="######"
HV$="#####.###"
FR$="###.###"

10 Z$="GO"
15 B1=1
20 M=17.95
25 F1=5.25
30 N=7.5
35 R0=926
40 V0=1.29
45 T=0
50 H0=60
55 R=R0+H0
60 A=-3.425
65 R1=0
70 A1=8.84361E-04
75 R3=0
80 A3=0
85 M1=7.45
90 M0=M1
95 B=750
100 T1=0
105 F=0
110 P=0
115 N=1
120 M2=0
125 S=0
130 C=0
135 IF Z$="YES" THEN 1150
140 PRINT
145 PRINT "LUNAR LANDING SIMULATION"
150 PRINT
155 PRINT "HAVE YOU FLOWN AN APOLLO/LEM MISSION BEFORE";
160 PRINT " (YES OR NO)";
165 INPUT Q$!Q$=CAPSTR$(Q$)
170 IF Q$="YES" THEN 190
175 IF Q$="NO" THEN 205
180 PRINT "JUST ANSWER THE QUESTION, PLEASE, ";
185 GOTO 160
190 PRINT
195 PRINT "INPUT MEASUREMENT OPTION NUMBER";
200 GOTO 225
205 PRINT
210 PRINT "WHICH SYSTEM OF MEASUREMENT DO YOU PREFER?"
215 PRINT " 1=METRIC     0=ENGLISH"
220 PRINT "ENTER THE APPROPRIATE NUMBER";
225 INPUT K
230 PRINT
235 IF K=0 THEN 280
240 IF K=1 THEN 250
245 GOTO 220
250 Z=1852.8
255 M$="METERS"
260 G3=3.6
265 N$=" KILOMETERS"
270 G5=1000
275 GOTO 305
280 Z=6080
285 M$="FEET"
290 G3=.592
295 N$="N.MILES"
300 G5=Z
305 IF B1=3 THEN 670
310 IF Q$="YES" THEN 485
315 PRINT
320 PRINT "  YOU ARE ON A LUNAR LANDING MISSION.  AS THE PILOT OF"
325 PRINT "THE LUNAR EXCURSION MODULE, YOU WILL BE EXPECTED TO"
330 PRINT "GIVE CERTAIN COMMANDS TO THE MODULE NAVIGATION SYSTEM."
335 PRINT "THE ON-BOARD COMPUTER WILL GIVE A RUNNING ACCOUNT"
340 PRINT "OF INFORMATION NEEDED TO NAVIGATE THE SHIP."
345 PRINT
350 PRINT
355 PRINT "THE ATTITUDE ANGLE CALLED FOR IS DESCRIBED AS FOLLOWS."
360 PRINT "+ OR -180 DEGREES IS DIRECTLY AWAY FROM THE MOON"
365 PRINT "-90 DEGREES IS ON A TANGENT IN THE DIRECTION OF ORBIT"
370 PRINT "+90 DEGREES IS ON A TANGENT FROM THE DIRECTION OF ORBIT"
375 PRINT "0 (ZERO) DEGREES IS DIRECTLY TOWARD THE MOON"
380 PRINT
385 PRINT TAB(30);"-180|+180"
390 PRINT TAB(34);"^"
395 PRINT TAB(27);"-90 < -+- > +90"
400 PRINT TAB(34);"!"
405 PRINT TAB(34);"0"
410 PRINT TAB(21);"<<<< DIRECTION OF ORBIT <<<<"
415 PRINT
420 PRINT TAB(20);"------ SURFACE OF MOON ------"
425 PRINT
430 PRINT
435 PRINT "ALL ANGLES BETWEEN -180 AND +180 DEGREES ARE ACCEPTED."
440 PRINT
445 PRINT "1 FUEL UNIT = 1 SEC. AT MAX THRUST"
450 PRINT "ANY DISCREPANCIES ARE ACCOUNTED FOR IN THE USE OF FUEL"
455 PRINT "FOR AN ATTITUDE CHANGE."
460 PRINT "AVAILABLE ENGINE POWER: 0 (ZERO) AND ANY VALUE BETWEEN"
465 PRINT "10 AND 100 PERCENT."
470 PRINT
475 PRINT "NEGATIVE THRUST OR TIME IS PROHIBITED."
480 PRINT
485 PRINT
490 PRINT "INPUT: TIME INTERVAL IN SECONDS ------ (T)"
495 PRINT "       PERCENTAGE OF THRUST ---------- (P)"
500 PRINT "       ATTITUDE ANGLE IN DEGREES ----- (A)"
505 PRINT
510 IF Q$="YES" THEN 535
515 PRINT "FOR EXAMPLE:"
520 PRINT "T,P,A? 10,65,-60"
525 PRINT "TO ABORT THE MISSION AT ANY TIME, ENTER 0,0,0"
530 PRINT
535 PRINT "OUTPUT: TOTAL TIME IN ELAPSED SECONDS"
540 PRINT "        HEIGHT IN ";M$
545 PRINT "        DISTANCE FROM LANDING SITE IN ";M$
550 PRINT "        VERTICAL VELOCITY IN ";M$;"/SECOND"
555 PRINT "        HORIZONTAL VELOCITY IN ";M$;"/SECOND"
560 PRINT "        FUEL UNITS REMAINING"
565 PRINT
566 PRINT " "&"TIME";TAB(10);"HEIGHT";TAB(23);"DISTANCE";
567 PRINT TAB(37);"V-VELOCITY";TAB(49);"H-VELOCITY";TAB(60);"FUEL LEFT"
570 GOTO 670
575 PRINT
580 REM PRINT "T,P,A";
585 INPUT "TIME INTERVAL IN SECONDS ------ (T)":T1
586 INPUT "PERCENTAGE OF THRUST ---------- (P)":F
587 INPUT "ATTITUDE ANGLE IN DEGREES ----- (A)":P
REM 585 INPUT T1,F,P
590 F=F/100
595 IF T1<0 THEN 905
600 IF T1=0 THEN 1090
605 IF ABS(F-.05)>1 THEN 945
610 IF ABS(F-.05)<.05 THEN 945
615 IF ABS(P)>180 THEN 925
620 N=20
625 IF T1<400 THEN 635
630 N=T1/20
635 T1=T1/N
640 P=P*3.14159/180
645 S=SIN(P)
650 C=COS(P)
655 M2=M0*T1*F/B
660 R3=-.5*R0*((V0/R)^2)+R*A1*A1
665 A3=-2*R1*A1/R
670 FOR I=1 TO N
675 IF M1=0 THEN 715
680 M1=M1-M2
685 IF M1>0 THEN 725
690 F=F*(1+M1/M2)
695 M2=M1+M2
700 PRINT "YOU ARE OUT OF FUEL."
705 M1=0
710 GOTO 725
715 F=0
720 M2=0
725 M=M-.5*M2
730 R4=R3
735 R3=-.5*R0*((V0/R)^2)+R*A1*A1
740 R2=(3*R3-R4)/2+.00526*F1*F*C/M
745 A4=A3
750 A3=-2*R1*A1/R
755 A2=(3*A3-A4)/2+.0056*F1*F*S/(M*R)
760 X=R1*T1+.5*R2*T1*T1
765 R=R+X
770 H0=H0+X
775 R1=R1+R2*T1
780 A=A+A1*T1+.5*A2*T1*T1
785 A1=A1+A2*T1
790 M=M-.5*M2
795 T=T+T1
800 IF H0<3.287828E-04 THEN 810
805 NEXT I
810 H=H0*Z
815 H1=R1*Z
820 D=R0*A*Z
825 D1=R*A1*Z
830 T2=M1*B/M0
835 PRINT " ";TT$:T;TAB(10);HF$:H;TAB(19);DL$:D;
840 PRINT TAB(37);VV$:H1;TAB(49);HV$:D1;TAB(60);FR$:T2
845 IF H0<3.287828E-04 THEN 880
850 IF R0*A>164.474 THEN 1050
855 IF M1>0 THEN 580
860 T1=20
865 F=0
870 P=0
875 GOTO 620
880 IF R1<-8.21957E-04 THEN 1020
885 IF ABS(R*A1)>4.93174E-04 THEN 1020
890 IF H0<-3.287828E-04 THEN 1020
895 IF ABS(D)>10*Z THEN 1065
900 GOTO 995
905 PRINT
910 PRINT "THIS SPACECRAFT IS NOT ABLE TO VIOLATE THE SPACE-";
915 PRINT "TIME CONTINUUM."
920 GOTO 575
925 PRINT
930 PRINT "IF YOU WANT TO SPIN AROUND, GO OUTSIDE THE MODULE"
935 PRINT "FOR AN E.V.A."
940 GOTO 575
945 PRINT
950 PRINT "IMPOSSIBLE THRUST VALUE ";
955 IF F<0 THEN 985
960 IF F-.05<.05 THEN 975
965 PRINT "TOO LARGE"
970 GOTO 575
975 PRINT "TOO SMALL"
980 GOTO 575
985 PRINT "NEGATIVE"
990 GOTO 575
995 PRINT
1000 PRINT "TRANQUILITY BASE HERE -- THE EAGLE HAS LANDED."
1005 PRINT "CONGRATULATIONS -- THERE WAS NO SPACECRAFT DAMAGE."
1010 PRINT "YOU MAY NOW PROCEED WITH SURFACE EXPLORATION."
1015 GOTO 1100
1020 PRINT
1025 PRINT "CRASH !!!!!!!!!!!!!!!!"
1030 PRINT "YOUR IMPACT CREATED A CRATER";ABS(H);M$;" DEEP."
1035 X1=SQR(D1*D1+H1*H1)*G3
1040 PRINT "AT CONTACT YOU WERE TRAVELING";X1;N$;"/HR"
1045 GOTO 1100
1050 PRINT
1055 PRINT "YOU HAVE BEEN LOST IN SPACE WITH NO HOPE OF RECOVERY."
1060 GOTO 1100
1065 PRINT "YOU ARE DOWN SAFELY - "
1075 PRINT
1080 PRINT "BUT MISSED THE LANDING SITE BY";ABS(D/G5);N$;"."
1085 GOTO 1100
1090 PRINT
1095 PRINT "MISSION ABENDED"
1100 PRINT 
1105 PRINT "DO YOU WANT TO TRY IT AGAIN (YES/NO)?"
1110 INPUT Z$
1115 IF Z$="YES" THEN 20
1120 IF Z$="NO" THEN 1130
1125 GOTO 1105
1130 PRINT
1135 PRINT "TOO BAD, THE SPACE PROGRAM HATES TO LOSE EXPERIENCED"
1140 PRINT "ASTRONAUTS."
1145 STOP
1150 PRINT
1155 PRINT "OK, DO YOU WANT THE COMPLETE INSTRUCTIONS OR THE INPUT -"
1160 PRINT "OUTPUT STATEMENTS?"
1165 PRINT "1=COMPLETE INSTRUCTIONS"
1170 PRINT "2=INPUT-OUTPUT STATEMENTS"
1175 PRINT "3=NEITHER"
1180 INPUT B1
1185 Q$="NO"
1190 IF B1=1 THEN 205
1195 Q$="YES"
1200 IF B1=2 THEN 190
1205 IF B1=3 THEN 190
1210 GOTO 1165
1215 END
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Lunar lander: a classic in a new dress

Post by GeorgeMcGinn »

Here is the 1970's version of the original "Lunar Lander."

It is a different game than LEM. It is closer to Henko's dressed up version.

For some reason I can find why the Burn Rate isn't printing, and I have not yet had a chance to format the output like I did for LEM game.

Enjoy

Code: Select all

10 PRINT TAB(33);"LUNAR"
20 PRINT TAB(l5);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" 
25 PRINTLINE(3)
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 PRINTLINE(3)!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!PRINT!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 PRINTLINE(3)!PRINT "TRY AGAIN??"!GOTO 70

'------------------------------------------------------
' PRINTLINE Statement:
'           This statement/function takes the place of
'           multiple PRINT statements that may be used,
'           and can get messy when used in nested IF 
'           conditions. If for example, you need to print
'           four blank lines, then PRINTLINE(4) will do
'           that for you, and look better than having a
'           a ton of PRINT statements all over your code.   
' 
DEF PRINTLINE (A)
    N=1
    DO 
          PRINT
          N=N+1
    UNTIL N > A   
ENDDEF   

George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Lunar lander: a classic in a new dress

Post by GeorgeMcGinn »

I guess the command was changed to TIME RESET. I made those changes after pulling a new copy of the code (1st time I pulled it from a quoted post, this one directly from the post itself) and all the issues with bad characters went away.

Here is Henko's working copy of Lunar Lander.

I will try to add the flames and possibly the ship exploding if it lands too hard.

I will also look for a real lunar lander graphic to replace the rocket, but for now the game works great.

Enjoy.

Code: Select all

option base 1 ! option angle degrees
dim lander_x(15),lander_y(15),lx(15),ly(15)

gosub init_prog
fuel=select_level(bmin)
create_gauges(fuel,height,velocity,gas)
draw_poly(14,lx,ly,120,910-3*height/10,0,0,0,0,2)
button "start" title "start" at 324,80 size 120,40
start:
if button_pressed("start")=0 then start
button "start" delete

decending:         ' check controls
tx=touch_x(0)
if tx>-1 then
  ty=touch_y(0)
  gas=slider("throttle",600,280,400,tx,ty,0)
  end if
if button_pressed("real") then ttt=1000
if button_pressed("fast") then ttt=ttt/2
if timer()<ttt then decending
time reset

' flight model (time step is fixed on 1 second)
thrust=gas*maxthrust/100 ! if fuel=0 then thrust=0
df=thrust/2000 ! fuel=fuel-df ! if fuel<0 then fuel=0
fv=thrust-weight-fuel ! acc=fv*gravity/(weight+fuel)
dv=acc ! velocity=velocity+dv
dh=velocity-dv/2 ! height=height+dh ! if height<0 then height=0

' update gauges
rmeter("fuel","g",384,260,120,0,400,fuel,0)
rmeter("meter","r",384,520,120,0,4000,height,0)
rmeter("m/sec","b",384,780,120,-200,200,velocity,0)

' update moon module
draw_poly(14,lx,ly,120,910-3*height/10,velocity,0,0,0,2)

' check on landing
if height>0 then goto decending else landed(velocity)
end


def select_level(bmin)
draw text "select difficulty level" at 260,10
button "easy" title "easy" at 200,40 size 120,30
button "medi" title "medium" at 340,40 size 120,30
button "diff" title "difficult" at 480,40 size 120,30
loop1: level=0
if button_pressed("easy") then level=1
if button_pressed("medi") then level=2
if button_pressed("diff") then level=3
if level=0 then loop1
button "easy" delete ! button "medi" delete ! button "diff" delete
fill rect 260,10 to 560,32
if level=1 then
  draw text "easy level" at 320,40 ! select_level=1.6*bmin
  else
  if level=2 then
    draw text "medium level" at 310,40 ! select_level=1.3*bmin
    else
    draw text "difficult level" at 290,40 ! select_level=1.1*bmin
    end if
  end if
end def

def create_gauges(b,h,v,gas)
rmeter("fuel","g",384,260,120,0,400,b,1)
rmeter("meter","r",384,520,120,0,4000,h,1)
rmeter("m/sec","b",384,780,120,-200,200,v,1)
slider ("throttle",600,280,400,0,0,1)
draw text "sim-speed" at 590,100
button "real" title "real time" at 525,130 size 100,30
button "fast" title "x2" at 645,130 size 100,30
fill color 0,0,0
fill rect 90,957.5 to 170,970 ! fill rect 110,947.5 to 150,958
fill color .8,.8,.8
end def

def landed(v)
draw font size 15
if v<-20 then 
  draw text "You made a mess of it! All destroyed and dead." at 180,930
  return
  end if
if v<-15 then
  draw text "You crashed! Module destroyed, you severely wounded (and alone!)" at 180,930
  return
  end if
if v<-10 then 
  draw text "bad landing. Module is damaged, you are lightly wounded." at 180,930
  return
  end if
if v<-5 then
  draw text "Fair landing! At least you are able to return." at 180,930
  return
  end if
if v<-2 then
  draw text "You're an ace! Return to earth to recieve Medal of Honour!" at 180,930
  return
  end if
end def

def slider (tit$,xt,yt,hgt,xtouch,ytouch,ind)
xb=xt+70 ! if hgt<120 then hgt=120 ! yb=yt+hgt+70 ! dy=hgt/10
if ind=-1 then
  fill rect xt-2,yt-2 to xb+2,yb+2 ! return
  end if
if ind=1 then
  draw size 3 ! draw font size 14
  draw rect xt,yt to xb,yb
  draw line xt,yt+20 to xb,yt+20
  draw text tit$ at xt+(68-8*len(tit$))/2,yb-20
 '  ys=yb-30 ! ys=560
  else
  if xtouch<xt or xtouch>xb or ytouch<yt or ytouch>yb then
    slider=-1
    return
    end if
  ys=ytouch
  if ys<yt+40 then ys=yt+40 ! if ys>yb-30 then ys=yb-30
  end if
draw size 2
graphics lock
fill color .8,.8,.8 ! draw font size 14
fill rect xt+2,yt+33 to xb-2,yb-25
draw rect xt+28,yt+40 to xt+32,yb-30
y=yb-30+dy
for i=0 to 100 step 10
  y=y-dy ! i$=i
  draw line xt+24,y to xt+36,y
  draw text i$ at xt+40,y-9
  next i
fill color 0,0,.6 ! fill alpha .6
fill rect xt+6,ys-4 to xt+54,ys+4
fill color .8,.8,.8 ! fill alpha 1
tt=(yb-ys-30)*100/(yb-yt-70)
fill rect xt+8,yt+2 to xb-2,yt+15
draw text n2a$(tt,5,1) at xt+8,yt
graphics unlock
draw font size 20
slider=tt
end def

def set_col(col$)
if col$="r" or col$="R" then
  draw color 1,0,0 ! fill color 1,0,0
  end if
if col$="g" or col$="G" then
  draw color 0,.7,0 ! fill color 0,.7,0
  end if
if col$="b" or col$="B" then
  draw color 0,0,1 ! fill color 0,0,1
  end if
if col$="n" or col$="N" then
  draw color 0,0,0 ! fill color .8,.8,.8
  end if
enddef

def rmeter(tit$,col$,xc,yc,rad,minval,maxval,val,mode)
if mode=-1 then
  fill circle xc,yc size rad+2
  return
  end if
graphics lock
  if mode=0 then mode_0
  set_col("n")
  draw size 3 ! draw circle xc,yc size rad
  draw size 4 ! draw circle xc,yc size rad-6
  set_col(col$)
  draw size 3 ! draw circle xc,yc size rad-3
  set_col("n")
  draw arc xc,yc,rad-50,130,410
  draw size 3
  for a=130 to 410 step 28
    xs=xc+(rad-50)*cos(a) ! ys=yc+(rad-50)*sin(a)
    xe=xc+(rad-42)*cos(a) ! ye=yc+(rad-42)*sin(a)
    draw line xs,ys to xe,ye
    next a
  draw size 1
  for a=130 to 410 step 7
    xs=xc+(rad-50)*cos(a) ! ys=yc+(rad-50)*sin(a)
    xe=xc+(rad-44)*cos(a) ! ye=yc+(rad-44)*sin(a)
    draw line xs,ys to xe,ye
    next a
  delta=(maxval-minval)/10 ! sval=minval
  draw font size 15
  for a=130 to 410 step 28
    xs=xc+(rad-28)*cos(a)-22 ! ys=yc+(rad-28)*sin(a)-10
    draw text n2a$(sval,3,0) at xs,ys
    sval=sval+delta
    next a
  draw font size 20
mode_0:
  fill circle xc,yc size rad-52
  xs=xc+(rad-80)*cos(112) ! ys=yc+(rad-80)*sin(112)
  set_col(col$)
  fill circle xc,yc size 10 ! draw text tit$ at xs-12,ys
  set_col("n")
  if val<minval then val=minval
  if val>maxval then val=maxval
  beta=130+280*(val-minval)/(maxval-minval)
  xs=xc-30*cos(beta) ! ys=yc-30*sin(beta)
  xe=xc+(rad-54)*cos(beta) ! ye=yc+(rad-54)*sin(beta)
  draw size 6 ! draw line xs,ys to xe,ye
graphics unlock
end def

def draw_poly(n,x(),y(),x_pos,y_pos,v,r,g,b,thick)
draw color r,g,b ! draw size thick
graphics lock
if v<0 then v=0
fill rect x_pos-1,y_pos+38+v to x_pos+21,y_pos-60
n=n+1 ! x(n)=x(1) ! y(n)=y(1)
xs=x(1)+x_pos ! ys=y(1)+y_pos
for i=2 to n
xe=x(i)+x_pos ! ye=y(i)+y_pos
draw line xs,ys to xe,ye ! xs=xe ! ys=ye
next i
graphics unlock
end def

def n2a$(num,lang,dec)
b$="               "
fac=10^dec
num$=int(fac*num+.5)/fac
tot=lang-len(num$)
if tot<1 then tot=1
a$=substr$(b$,1,tot) & num$
n2a$=a$
end def

def test (in$,in)
fill rect 30,900 to 400,940
a$="test " & in$ & in
draw text a$ at 30,900
button "cont" title "doorgaan ?" at 440,890
loopje:
if button_pressed("cont")=0 then goto loopje
button "cont" delete
fill rect 30,900 to 400,940
end def

init_prog:
randomize
graphics ! fill color .8,.8,.8 ! draw color 0,0,0
graphics clear .8,.8,.8
height=2300+rnd(700) ! velocity=-rnd(40)
fac=.5 ! np=14
for i=1 to np
  read lander_x(i),lander_y(i)
  lx(i)=fac*lander_x(i) ! ly(i)=fac*(75-lander_y(i))
  next i
data 20,0, 30,0, 30,25, 40,15, 40,0, 30,5, 30,55
data 20,75, 10,55, 10,5, 0,0, 0,15, 10,25, 10,0
read weight,fuel,gravity,maxthrust,gas
data 2000,100,1.6,4000,50
bmin=maxthrust*(weight+100)*sqrt(1.6*height+.5*velocity^2)
bmin=bmin/3200/(maxthrust-weight-100)
ttt=1000 ! time reset
return
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Lunar lander: a classic in a new dress

Post by rbytes »

I also added SET ORIENTATION PORTRAIT as line 2, since that is how the program needs to be oriented. After a few tries I got a perfect landing, and was given a hero's welcome on earth.

Then I thought - if the landing can be completed perfectly, how badly can it be screwed up? There is a skill to that too. It isn't easy to have the lander accelerate to more than -140 m/s before reaching the surface. To achieve that speed, your timing also needs to be perfect. See if you can do it. Maybe we need various images of destroyed ships, depending on impact speed. This one would be just a few tangled strips of metal.

IMG_2777.JPG
IMG_2777.JPG (341.71 KiB) Viewed 5367 times
The only thing that gets me down is gravity...

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Lunar lander: a classic in a new dress

Post by Henko »

I made a more realistic simulation some time ago. It's a rocket (two or three stages, i don't remember), which has a two dimensional flying space (height and horizontal). The rocket starts on the ground and you can simply go up and try to land again in a pure vertical path, as in my old, simple sim.
But it is also possible (but very difficult) to attain a stable orbit in space manually.
The forces on the rocket are the rocket engine, the weight (which varies due to fuel consumption, stage abandon, height (Newton's law)), centrifugal force, and drag in the atmosphere (height dependent).

The aim is to land again safely, or to attain a stable orbit.
Possible failures: crash while landing, overheating while returning in the atnosphere, or disappear in far space.

The user interface is very basic, designed for personal use only.
Most of it is rather self explaining.
Some of the less obvious things:
Angle: simply the attitude of the rocket; i did not implement side rockets to direct the rocket, but used a slider to direct the rocket.
The circle shows the attitude of the rocket (black) and the actual velocity vector (red)
Stat.speed: this is the needed horizontal velocity for a stable orbit on the actual height of the rocket.

The code follows the image. There is some documentation in it.

IMG_1414.PNG
IMG_1414.PNG (376.42 KiB) Viewed 5358 times

Code: Select all

graphics ! graphics clear .8,.8,.8
draw color 0,0,0 ! fill color .8,.8,.8
option angle degrees ! get screen size ww,hh

init_GUI()
mo=10000 ! inf1=.05*mo ! inf2=.1*mo ! bo=mo-inf1-inf2
dbodt=mo/250 ! fM=3.6E+14
m=mo ! b=bo ! tr=0 ! gam=90 ! beta=90 ! v=0 ! vh=0 ! vv=0 ! h=0 ! s=0
ro=6.E+6 ! slt=1/11 ! t=0 ! pdt=1 ! dt=.2
buttons()
do ! slowdown
'----- check user input via de sliders
  sl_t=slider_changed("throttle")
  sl_a=slider_changed("angle")
  sl_s=slider_changed("simspeed")
'----- check if something happened yet
  if sl_t + sl_a + sl_s + h = 0 then continue
'----- check for returning on earth ground
  if t>5 and h<0 then
    h=0 ! button "message" show
    if v<10 then ! button "message" text "LANDED OK !!!"
      else ! button "message" text "CRASHED !!!"
      end if
    pause 2 ! stop
    end if
'----- throttle slider has been moved
  if sl_t>0 and b>0 then
    slt=slider_value("throttle")
    dbdt=(1.1*slt-.1)*dbodt ! tr=5000*dbdt
    end if
'----- angle slider has been moved
  if sl_a>0 then ! sla=slider_value("angle") ! gam=180*sla-90 ! end if
'----- simulation speed slider has been moved
  if sl_s>0 then
    sls=slider_value("simspeed")
    pdt=1-sls ! dt=.2+sls
    end if
'----- check for heat load on the capsule due to drag
  drag=0.4*rho(h)*v^2 ! heat=drag*v
  if heat>5E+7 then
    button "message" show
    if heat<5E+8 then
      button "message" text "HEATING !!!"
      else
      button "message" text "MELTED !!!"
      pause 2 ! stop
      end if
    else
    button "message" hide
    end if
'----- calculate velocity vector (flight path)
  beta=deg_atan(vh,vv)
'----- calculate hor. and vert. forces
  kh=tr*cos(gam)-drag*cos(beta)
  kv=tr*sin(gam)-drag*sin(beta)+m*vh^2/(ro+h)-fM*m/(ro+h)^2
'----- calculate accelerations and elapsed time
  ah=kh/m ! av=kv/m ! t+=dt
'----- calculate velocities and distances
  dvh=ah*dt ! s+=(vh+dvh/2)*dt ! vh+=dvh
  dvv=av*dt !  ! vv+=dvv ! if vv<0 and h<=.1 then vv=0
  h+=(vv+dvv/2)*dt ! h=max(.1,h)
'----- calculate resultant velocity for drag and heating
  v=sqrt(vh^2+vv^2)
'----- calculate fuel consunption and remaining fuel
  db=abs(dbdt)*dt ! b-=db
'----- check for decoupling of rocket segment
  if b<=bo/2 then ! inf2/=2 ! bo=b ! end if
'----- check if out of fuel
  if b<=0 then
    b=0 ! dbdt=0 ! tr=0 ! slt=1/11 ! slider "throttle" value 1/11
    end if
'----- calculate mass, gravity and weight
  m=inf1+inf2+b ! g=fM/(ro+h)^2 ! w=m*g
  pause pdt
' debug pause
buttons()

until forever
end

def init_GUI()
read header1$,header2$
data "weight      fuel      thrust%    angle     velocity   height"
data "thrust   vert.force stat.speed    time"
split header1$ to but1$,nb with " "
split header2$ to but2$,nb with " "
draw text header1$ at 20,10 ! draw text header2$ at 150,80
sx=100 ! sy=30
for i=0 to 5
  button but1$(i) text "" at 10+i*(sx+30),30 size sx,sy
  if i<4 then button but2$(i) text "" at 140+i*(sx+30),100 size sx,sy
  next i
slider "throttle" value 1/11 at 50,540 size 480 angle -90
draw font size 15 ! draw color 0,0,1 ! draw size 2
draw text "Thrust" at 22,560
for y=540 to 100 step -40
  draw line 50,y to 60,y
  draw text (500-y)/4 & "%" at 65,y-7
  next y
slider "simspeed" value 0 at 50,800 size 200 angle -90
draw text "Simspeed" at 22,820
for y=800 to 640 step -40
  draw line 50,y to 60,y
  next y
slider "angle" value 1 at 730,640 size 570 angle -90
draw text "Angle" at 710,660
for y=640 to 100 step -30
  draw line 720,y to 730,y
  xt=(370-y)/3 ! if xt<0 then dxt=9 else dxt=0
  draw text xt at 690-dxt,y-7
  next y
button "message" text "" at 300,180 size 120,40
button "message" hide
draw circle .ww/2,400 size 102
end def

def rho(h) = exp(-0.00011*h)
def bp(a$) = button_pressed(a$)

def buttons()
button "weight"  text int(.w)
button "fuel"    text int(.b)
button "thrust%" text int(110*.slt-10)&"%"
button "angle"   text int(.gam)&chr$(176)
if .v<1000 then v$=int(.v)&"m/s" else v$=int(.v/10)/100&"km/s"
button "velocity" text v$
if .h<10000 then h$=int(.h)&"m" else h$=int(.h/100)/10&"km"
button "height" text h$
button "thrust" text int(.tr) 
button "vert.force" text int(.kv)
ss=int(sqrt(.fM/(.ro+.h)))
button "stat.speed" text ss&" m/s"
m$=floor(.t/60) ! s$=int(.t%60)
button "time" text m$ & "m" & s$ & "s"
w=.ww/2 ! fill circle w,400 size 100
draw color 0,0,0
px=80*cos(.gam) ! py=80*sin(.gam) ! draw line w,400 to w+px,400-py
draw color 1,0,0
px=80*cos(.beta) ! py=80*sin(.beta) ! draw line w,400 to w+px,400-py
draw color 0,0,1
end def

def deg_atan(x,y)
if x=0 then return 90*(2-sign(y)) else ta=atan(y/x)
if x<0 then ! ta+=180 ! else ! if y<0 then ! ta+=360 ! end if ! end if
return ta
end def



User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Lunar lander: a classic in a new dress

Post by rbytes »

George, here are some items you can use as sprites to dress up the lunar lander. All three items
are transparent, so they can be used on any background.

The actual lander, a png image:
IMG_2831.PNG
IMG_2831.PNG (271.34 KiB) Viewed 5342 times
An animated gif rocket flame - it will look more realistic at a faster cycle rate:
IMG_2824.GIF
IMG_2824.GIF (49.62 KiB) Viewed 5342 times
And an animated gif explosion - looks better at a slower cycle rate:
IMG_2829.GIF
IMG_2829.GIF (66.31 KiB) Viewed 5342 times
The only thing that gets me down is gravity...

Post Reply