rem N Body Problem ...... Rev 4.4 rem A J Tooth // May 2005 rem ======================================================== rem Global variables start with a CAPITAL. rem Local variables are lower-case. rem ======================================================== rem Simulates N asteroids interacting under gravity, near to rem a massive planet, which also moves under the net rem gravitational force of the asteroids. rem ======================================================== rem on error if (err=17) then quit rem Setup proc_setup rem Initial Net View proc_astroview Trk%=0 colour 7 : print tab(1,0);"Energy Error" print tab(1,5);"Dt= "; repeat rem Calculate Resultant Force from viewpoint of each asteroid in turn proc_Force rem Main Iterative Movement Calculation proc_calc rem Energy Tracking proc_energy rem Next view proc_astroview Trk%+=1 : if Trk%=100 then Trk%=0 a$=inkey$(5) mouse x,y,b& until (a$<>"" or b&=4 or Efl%=1) a$=inkey$(20) repeat a$=inkey$(1) mouse x,y,b& until (a$<>"" or b&=4) quit end rem End of Program =================================================== rem Setup fullscreen def proc_fullscreen(return xscreen%,return yscreen%) sys "GetSystemMetrics", 0 to xscreen% sys "GetSystemMetrics", 1 to yscreen% sys "SetWindowLong",@hwnd%,-16,&16000000 sys "SetWindowPos",@hwnd%,-1,0,0,xscreen%,yscreen%,0 vdu 23,22,xscreen%;yscreen%;8,16,16,1 : rem Set fullscreen mode off : mouse off endproc rem ================================================================== rem Setup def proc_setup local a%,b&,x,y,tst%,i% himem=lomem + 20000000 *FLOAT 64 dim rgb% 3, re% 0, gr% 0, bl% 0 dim pt$(3) pt$()="short","medium","long" proc_fullscreen(xscreen%,yscreen%) *REFRESH OFF Num%=50 proc_back("How many Asteroids?",100,1250,500,100,200,0,200) proc_box(4,700,1250,200,str$(Num%),50,50,0) repeat mouse x,y,b& tst&=asc(inkey$(1)) if tst&=140 or tst&=138 then Num%+=1 if tst&=141 or tst&=139 then Num%-=1 if Num%<1 then Num%=1 if Num%>1000 then Num%=1000 if tst&=140 or tst&=141 or tst&=138 or tst&=139 then proc_box(4,700,1250,200,str$(Num%),50,50,0) tst%=0 *REFRESH until b&=4 a$=inkey$(20) proc_back("Choose a default time interval",100,1000,700,100,200,0,200) i%=0 proc_box(4,900,1000,250,pt$(i%),50,50,0) repeat mouse x,y,b& tst&=asc(inkey$(1)) if tst&=140 or tst&=138 then i%+=1 if tst&=141 or tst&=139 then i%-=1 if i%<0 then i%=2 if i%>2 then i%=0 if tst&=140 or tst&=141 or tst&=138 or tst&=139 then proc_box(4,900,1000,250,pt$(i%),50,50,0) tst%=0 *REFRESH until b&=4 t$=left$(pt$(i%),1) case t$ of when "s": DT=0.001 when "m": DT=0.005 when "l": DT=0.01 endcase G=10.0 : Flg%=0 : Efl%=0 cls *REFRESH OFF dim Ver(Num%,2), Vel(Num%,4), Acc(Num%,2), Ms(Num%), dVer(Num%,4,2) dim Dis(Num%,Num%) Xlim%=xscreen% : Ylim%=yscreen% origin Xlim%,Ylim% rem Masses, and initial positions and velocities Ms(1)=1000000.0 Ver(1,1)=0.0 Ver(2,1)=0.0 Vel(1,1)=0.0 Vel(2,1)=0.0 Vero1=0.0 Vero2=0.0 for a%=2 to Num% Ms(a%)=1000.0*rnd(5) Ver(a%,1)=1.0*(rnd(Xlim%) - Xlim%/2) Ver(a%,2)=1.0*(rnd(Ylim%) - Ylim%/2) Vel(a%,1)=100.0*(rnd(11)-6) Vel(a%,2)=100.0*(rnd(11)-6) next a% endproc rem ================================================================== rem Initial Net View def proc_astroview local a% rem Draw the vertices themselves for a%=1 to Num% if a%=1 then gcol 0 : circle fill 2*Vero1,2*Vero2,20 if Acc(a%,0)<0.5 then !rgb%=100000*a% ?re%=?rgb% ?gr%=rgb%?(1) ?bl%=rgb%?(2) colour 10,?re%,?gr%,?bl% : gcol 10 plot 2*Ver(a%,1),2*Ver(a%,2) endif if a%=1 then circle fill 2*Ver(a%,1),2*Ver(a%,2),20 : Vero1=Ver(a%,1) : Vero2=Ver(a%,2) next a% *REFRESH endproc rem ================================================================== rem Calculate Resultant Force experienced by each asteroid in turn def proc_Force local i%,j%,cumFx,cumFy,Rx,Ry,D,Cub,R,Tadj Coll%=0 : rem Set to 1 if an asteroid collides with the planet. Dt=DT : rem Default maximum value for time slot. sys "GetCurrentProcess" to hprocess% sys "SetPriorityClass", hprocess%, &100 for j%=1 to Num% cumFx=0.0 : cumFy=0.0 : Tadj=1.0 if Acc(j%,0)<0.5 then for i%=1 to Num% if (i%<>j% and Acc(i%,0)<0.5) then Rx=Ver(i%,1) - Ver(j%,1) Ry=Ver(i%,2) - Ver(j%,2) D=sqr(Rx*Rx + Ry*Ry) if D<0.01 then D=0.01 Dis(j%,i%)=D if (j%=1 and D<10.0) then Acc(i%,0)=1.0 : Coll%=1 rem Increase Tadj whenever the subject asteroid rem gets too close to any of the object asteroids if Tadj<1000/D then Tadj=1000/D Cub=D*D*D cumFx+=Ms(i%)*Rx/Cub cumFy+=Ms(i%)*Ry/Cub endif next i% endif rem Dt is set at the minimum value reached if DT/Tadj