home *** CD-ROM | disk | FTP | other *** search
/ Current Shareware 1994 January / SHAR194.ISO / astronom / sol3.zip / SOL3.C < prev    next >
C/C++ Source or Header  |  1993-10-27  |  20KB  |  635 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <math.h>
  6. #include <graphics.h>
  7. #include <time.h>
  8. #include <alloc.h>
  9. #include "svga16.h"
  10.  
  11. #define DEF_INTERVAL 1.5e1 /* default simulation interval (hours) */
  12. #define TEXTCOLOR YELLOW
  13. #define TENTHofYEAR 876.6 /* hours in tenth of year */
  14. #define GMe 1.5444e-12 /* a.u.^ 3 / hour ^ 2 */
  15. #define GMs 5.1395e-7  /*         "          */
  16. #define GMm 1.8982e-14 /*         "          */
  17. #define Ve  7.1519e-4  /* a.u./hour, Earth's avg orbital velocity */
  18. #define maxBods 15
  19.  
  20. /* semi-constant graphics variables */
  21. unsigned MAX_X,MAX_Y,MAXX2,MAXY2,MAX_COL;
  22.  
  23. /* location, acceleration and velocity in x,y directions */
  24. double x[maxBods], Ax[maxBods], Vx[maxBods];
  25. double oldx[maxBods], oldy[maxBods];
  26. double y[maxBods], Ay[maxBods], Vy[maxBods];
  27. double  Gm[maxBods];                /* masses*Gravitational constant */
  28. unsigned int col[maxBods], objects; /* color of each object, # of obj */
  29. // int class[maxBods];
  30. /* save initial parameters */
  31. double xinit[maxBods],yinit[maxBods],Vxinit[maxBods],Vyinit[maxBods];
  32. /* save */
  33.  
  34. int  vx,vy; /* flags for relative velocity changes */
  35. double vrelx,vrely,relativespeed,etime,viewscale;
  36. double dt;   /* hours */
  37.  
  38. void show_info(void);
  39. void cm(void);
  40. void init1(void);
  41. void _Cdecl SVGA256_driver();
  42.  
  43. int huge DetectVGA16()
  44. {
  45. /*
  46.   int Vid;
  47.  
  48.  
  49.   printf("Which video mode would you like to use? \n");
  50.   printf("  0) 320x200x16\n");
  51.   printf("  1) 640x200x16\n");
  52.   printf("  2) 640x350x16\n");
  53.   printf("  3) 640x480x256\n");
  54.   printf("  4) 800x600x16\n");
  55.   printf("  5) 1024x768x16\n\n>");
  56.   scanf("%d",&Vid);
  57.   return Vid;
  58. */
  59.   return 4;  
  60. }
  61.  
  62. void show_elapsed(void){
  63.     static char oldmsg[25];
  64.     char msg[25];
  65.  
  66.     sprintf(msg,"%4.1lf yrs",etime/(24.0*365.25));
  67.     setcolor(0);
  68.     outtextxy(10,MAX_Y-9,oldmsg);
  69.     setcolor(TEXTCOLOR);
  70.     outtextxy(10,MAX_Y-9,msg);
  71.     strcpy(oldmsg,msg);
  72. }/* show_elapsed */
  73.  
  74. void clr_infoline(void){
  75.     setviewport(10,MAX_Y-9,MAX_X,MAX_Y,1);
  76.     clearviewport();
  77.     setviewport(0,0,MAX_X,MAX_Y,1);
  78. } //clr_infoline
  79.  
  80. void elapsed(void){/* increment elapsed time counter, update time display */
  81.  
  82.     static double next_elapsed;
  83.  
  84.     if(etime == 0.0){
  85.         next_elapsed = TENTHofYEAR;
  86.         if (dt < 0.0) next_elapsed = -next_elapsed;
  87.         show_elapsed();
  88.     }
  89.     if (dt > 0){
  90.         if (etime >= next_elapsed){
  91.             next_elapsed += TENTHofYEAR;
  92.             show_elapsed();
  93.         }
  94.     }
  95.     else{
  96.         if(etime <= next_elapsed){
  97.             next_elapsed -= TENTHofYEAR;
  98.             show_elapsed();
  99.         }
  100.     }
  101.  
  102.     etime += dt;
  103.  
  104. } /* elapsed */
  105.  
  106. void propagate(void){
  107.         int i,j;
  108.         double dx,dy;
  109.         double dist,Fx,Fy;
  110.  
  111.         for (i=0; i<objects; i++){
  112.             Vx[i] += Ax[i]*dt; Vy[i] += Ay[i]*dt;
  113.              x[i] += Vx[i]*dt;  y[i] += Vy[i]*dt;
  114.             Ax[i]  = Ay[i] = 0.0;
  115.         }
  116.  
  117.         for (i=0;i<objects-1;i++){
  118.             for (j=i+1;j<objects;j++){
  119.                 // if (class[i] == 1 && Gm[j] == 1) continue;
  120.                 // ignore the effects of Earth-size masses on each other
  121.                 dx = x[j]-x[i]; dy = y[j]-y[i];
  122.                 dist = (dx*dx+dy*dy);
  123.                 dist *= sqrt(dist);
  124.                 Fx=dx/dist; Fy=dy/dist;
  125.  
  126.                 Ax[i] += Fx*Gm[j]; Ay[i] += Fy*Gm[j];
  127.                 Ax[j] -= Fx*Gm[i]; Ay[j] -= Fy*Gm[i];
  128.             }
  129.         }
  130.         elapsed();
  131.  
  132.     /***********************************************
  133.      *            relative velocity code           *
  134.      ***********************************************/
  135.     if (vx){
  136.        for (i=0;i<objects;i++)
  137.            Vx[i]+=vrelx;
  138.            vx=0;
  139.        }
  140.     if (vy){
  141.        for (i=0;i<objects;i++)
  142.            Vy[i]+=vrely;
  143.                vy=0;
  144.     }
  145. } /*propagate*/
  146.  
  147. void savefile(void){
  148.     int i;
  149.     char filename[82], *name, *msg =
  150.     {"Enter name of file in which to save these initial parameters: "};
  151.     FILE *out;
  152.  
  153.     filename[0] = 80;
  154.     outtextxy(10,10,msg);
  155.     name = cgets(filename);
  156.     out = fopen(name,"w");
  157.     while (out == NULL){
  158.         clearviewport();
  159.         outtextxy(10,10,"Unable to open file, please reenter: ");
  160.         name = cgets(filename); out = fopen(name,"w");
  161.     }
  162.     fprintf(out,"%u %.18lg\n",objects,dt);
  163.     for(i=0;i<objects;i++)
  164.         fprintf(out,"%.18lg %.18lg %.18lg %.18lg %.18lg %u\n",
  165.         xinit[i],yinit[i],Vxinit[i],Vyinit[i],Gm[i],col[i]);
  166.     fclose(out);
  167.     show_info();
  168. }/* savefile */
  169.  
  170.  
  171. void restorefile(void){
  172.     int i;
  173.     char filename[82], *name;
  174.     FILE *in;
  175.  
  176.     filename[0] = 80;
  177.     outtextxy(10,10,"Enter file to read in: ");
  178.     name = cgets(filename);
  179.     in = fopen(name,"r");
  180.     if (in == NULL){
  181.         printf("Unable to open %s",name);
  182.         clearviewport();
  183.         return;
  184.     }
  185.     fscanf(in,"%u %lf\n",&objects,&dt);
  186.     for(i=0;i<objects;i++){
  187.         fscanf(in,"%lf %lf %lf %lf %lf %u\n",x+i,y+i,Vx+i,Vy+i,Gm+i,col+i);
  188.         xinit[i]=x[i]; yinit[i]=y[i]; Vxinit[i]=Vx[i]; Vyinit[i]=Vy[i];
  189.         Ax[i]=Ay[i]=0.0;
  190.     }
  191.     init1();
  192.     cm();
  193. }/* restorefile */
  194.  
  195. void center(){
  196.     int max= -1, i;
  197.  
  198.     /* find most massive object on the screen */
  199.     for (i=0;i<objects;i++)
  200.     // if(     fabs(x[i]/viewscale) <= MAXX2)
  201.     //    &&  fabs(y[i]/viewscale) <= MAXY2))
  202.     if(     MAXX2 >= ((int) fabs(x[i]/viewscale))
  203.         &&  MAXY2 >= ((int) fabs(y[i]/viewscale)) )
  204.  
  205.             if (max == -1) max=i; /* first on screen */
  206.             else if(Gm[max] <= Gm[i]) max=i;
  207.  
  208.     if (max == -1) return; /* exit if nothing on screen */
  209.  
  210.     /* center it on the screen, and zero its velocity */
  211.     for (i=0;i<objects;i++)
  212.         if (i != max){
  213.             Vx[i]-=Vx[max]; x[i]-=x[max];
  214.             Vy[i]-=Vy[max]; y[i]-=y[max];
  215.         }
  216.     show_info();
  217.     Vx[max]=Vy[max]=x[max]=y[max]=0.0;
  218. } //center
  219.  
  220. void cm(void){
  221.     int i;
  222.     double cmVx, cmVy, cmx, cmy, cmMass;
  223.  
  224.     cmVx=cmVy=cmx=cmy=cmMass=0.0;
  225.     /* find the center of mass of the system ON the screen */
  226.     for (i=0;i<objects;i++)
  227.     if( (fabs(x[i]/viewscale) <= MAXX2) && (fabs(y[i]/viewscale) <= MAXY2)){
  228.                 cmVx+=Vx[i]*Gm[i]; cmVy+=Vy[i]*Gm[i];
  229.                  cmx+=x[i]*Gm[i];   cmy+=y[i]*Gm[i];
  230.                            cmMass+=Gm[i];
  231.     }
  232.     if (cmMass == 0.0) return; /* exit if nothing on screen */
  233.     else {
  234.             cmVx/=cmMass;
  235.             cmVy/=cmMass;
  236.             cmx /=cmMass;
  237.             cmy /=cmMass;
  238.     }
  239.  
  240.     /* center it on the screen, and zero its velocity */
  241.     for (i=0;i<objects;i++){
  242.             Vx[i]-=cmVx; x[i]-=cmx;
  243.             Vy[i]-=cmVy; y[i]-=cmy;
  244.     }
  245.     show_info();
  246. }/* cm */
  247.  
  248. void plotBodies(void){
  249.       int  i;
  250.       double rx, ry;
  251.  
  252.       for (i=0; i<objects; i++){
  253.             rx=x[i]/viewscale+(MAXX2);
  254.             ry=y[i]/viewscale+(MAXY2);
  255.             putpixel(oldx[i],oldy[i],col[i]);
  256.             putpixel(rx,ry,YELLOW);
  257.             oldx[i]=rx;
  258.             oldy[i]=ry;
  259.       }
  260. } /*plotBodies*/
  261.  
  262. char show_masses(void){
  263.         int i, width;
  264.         char info[82];
  265.  
  266.         for (i=0;i<objects;i++)
  267.         if( (fabs(x[i]/viewscale) <= MAXX2) && (fabs(y[i]/viewscale) <= MAXY2)){
  268.             sprintf(info,"%5.3g Suns, %.4g mi/s",Gm[i]/GMs,25833.3333*sqrt(Vx[i]*Vx[i]+Vy[i]*Vy[i]));
  269.             width = textwidth(info)/2;
  270.             setcolor(col[i]);
  271.             setfillstyle(SOLID_FILL,col[i]);
  272.             fillellipse(x[i]/viewscale+MAXX2,y[i]/viewscale+MAXY2,3,3 );
  273.             if(x[i]/viewscale-width+MAXX2 >= 0 &&
  274.                x[i]/viewscale+width+MAXX2 <= MAX_X)
  275.                 outtextxy(x[i]/viewscale+MAXX2-width,y[i]/viewscale+MAXY2,info);
  276.             else if (x[i] < 0)
  277.                 outtextxy(0,y[i]/viewscale+MAXY2,info);
  278.             else
  279.                 outtextxy(x[i]/viewscale+MAXX2-2*width,y[i]/viewscale+MAXY2,info);
  280.         }
  281.         setcolor(TEXTCOLOR);
  282.         clr_infoline();
  283.         outtextxy(10,MAX_Y-9,"Press any key to continue");
  284.         return(getch());
  285. } /* show_masses */
  286.  
  287. void show_area(void){
  288.    /* write size of screen (in AUs) on lower right */
  289.     char scal[80];
  290.  
  291.     if (viewscale*MAX_Y < 10.0)
  292.         sprintf(scal,"%u objects, %2.1e x %2.1e AU",objects,viewscale*MAX_X,viewscale*MAX_Y);
  293.     else sprintf(scal,"%u objects, %.0fx%.0f AU",objects,viewscale*MAX_X,viewscale*MAX_Y);
  294.     outtextxy(MAX_X-textwidth(scal)-9,MAX_Y-9,scal);
  295. } //show_area
  296.  
  297. void show_interval(void){
  298.     char interval[30];
  299.     int halflen;
  300.  
  301.     sprintf(interval,"%4.2g hrs",dt);
  302.     halflen=textwidth(interval);
  303.     setviewport(MAXX2-halflen,MAX_Y-9,MAXX2+halflen,MAX_Y,1);
  304.     clearviewport();
  305.     setviewport(0,0,MAX_X,MAX_Y,1);
  306.     outtextxy(MAXX2-halflen,MAX_Y-9,interval);
  307. } //show_interval
  308.  
  309. void show_info(void){
  310.     clearviewport();
  311.     show_elapsed();
  312.     show_interval();
  313.     show_area();
  314. } //show_info
  315.  
  316.  
  317. void restart(void){
  318.         int i;
  319.  
  320.         for(i=0;i<objects;i++){
  321.             Vx[i]=Vxinit[i]; Vy[i]=Vyinit[i];
  322.             x[i]=xinit[i]; y[i]=yinit[i];
  323.             Ax[i]=Ay[i]=0.0;
  324.         }
  325.         init1(); cm();
  326. } //restart
  327.  
  328. void init1(void){
  329.     etime=0.0; /* elapsed time */
  330.  
  331.     vrelx=vrely=0.0;
  332.     relativespeed=0.25*Ve;
  333.     show_info();
  334.     viewscale=(25.0/MAX_Y); /* vert. screen = 25 AU */
  335. } //init1
  336.  
  337. void init(void){
  338.     int   i,mass,direction, maxsave=0;
  339.     double rx,ry,cmx,cmy,cm,theta,magV[maxBods], maxmass=0.0, dist;
  340.  
  341.     randomize();
  342.     objects = random(maxBods-3) + 4;
  343.     init1();
  344.     dt=DEF_INTERVAL;  /* time increment */
  345.     cmx=cmy=cm=0.0;
  346.  
  347.     for (i = 0;i<objects;i++){
  348.         if (i == 0) mass=0;   /* at least one "star" */
  349.         else mass = random(10);
  350.         // class[i] = 0;
  351.         if (mass < 2){
  352.             Gm[i] = GMs*(random(1000)+1.0);/* 1-1000x Solar mass */
  353.             if (Gm[i] < 500.0*GMs) col[i]=YELLOW/2;
  354.             else col[i]=LIGHTBLUE/2;
  355.             if(Gm[i] > maxmass){
  356.                 maxmass=Gm[i];
  357.                 maxsave=i;
  358.             }
  359.         }
  360.         else if (mass < 4){
  361.             Gm[i] = GMm*(random(20000)+1.0)*1e3*random(50);/* large planet */
  362.             if (Gm[i] > 10.0*GMs) col[i]=YELLOW/2;
  363.             else col[i]=WHITE/2;
  364.             if(Gm[i] > maxmass){
  365.                 maxmass=Gm[i];
  366.                 maxsave=i;
  367.             }
  368.         }
  369.         else{
  370.             do {
  371.                 col[i]=random(MAX_COL/2-1)+1;
  372.             } while( (col[i] == YELLOW/2) || (col[i] == LIGHTBLUE/2) || (col[i] == LIGHTRED/2) );
  373.             Gm[i] = GMe*(random(1000)+1); /* Earth */
  374.             // class[i] = 1;
  375.         }
  376.                                                       cm+=Gm[i];
  377.         xinit[i] = x[i] = (random(2001)-1000.0)/100.0;cmx+=Gm[i]*xinit[i];
  378.         yinit[i] = y[i] = (random(2001)-1000.0)/100.0;cmy+=Gm[i]*yinit[i];
  379.         magV[i]=(random(301)+random(300))*Ve/100.0+2*Ve;
  380.         Ax[i] = Ay[i] = 0.0;
  381.     }
  382.     cmx/=cm;
  383.     cmy/=cm;    direction=random(2);
  384.  
  385.             rx=x[maxsave]-cmx; ry=y[maxsave]-cmy;
  386.             theta=atan2(ry,rx);
  387.             if (direction){
  388.                 Vxinit[maxsave]=Vx[maxsave]=(-magV[maxsave])*sin(theta);
  389.                 Vyinit[maxsave]=Vy[maxsave]=(magV[maxsave])*cos(theta);
  390.             }
  391.             else{
  392.                 Vxinit[maxsave]=Vx[maxsave]=(magV[maxsave])*sin(theta);
  393.                 Vyinit[maxsave]=Vy[maxsave]=(-magV[maxsave])*cos(theta);
  394.             }
  395.     for (i=0;i<objects;i++){
  396.         if(i != maxsave){
  397.             rx=x[i]-x[maxsave]; ry=y[i]-y[maxsave];
  398.             dist=sqrt(rx*rx+ry*ry);
  399.             magV[i] = sqrt(Gm[maxsave]/dist);
  400.             theta=atan2(ry,rx);
  401.             if (direction){
  402.                 Vxinit[i]=Vx[i]=(-magV[i])*sin(theta)+Vxinit[maxsave];
  403.                 Vyinit[i]=Vy[i]=(magV[i])*cos(theta)+Vyinit[maxsave];
  404.             }
  405.             else{
  406.                 Vxinit[i]=Vx[i]=(magV[i])*sin(theta)+Vxinit[maxsave];
  407.                 Vyinit[i]=Vy[i]=(-magV[i])*cos(theta)+Vyinit[maxsave];
  408.             }
  409.         }
  410.  
  411.     }
  412. } /*init*/
  413.  
  414. void help(void){
  415.     char *msgs[]={
  416.         "Welcome to Sol3, a multi-star orbital dynamics simulation by",
  417.         "                Jeff Elam and Tony Acero",
  418.         "          Copyright 1990, 1993  Anibal A. Acero",
  419.         " ",
  420.         " Comments, bugs, praise, postcards and/or donations always welcome!",
  421.         " email: ace3@midway.uchicago.edu  phone: (312) 702-8214",
  422.         " US mail: 5640 S. Ellis Ave., JFI 340",
  423.         "          University of Chicago",
  424.         "          Chicago, IL 60637",
  425.         " ",
  426.         "Usage: watch screen -- if you see something interesting try to capture it on ",
  427.         "the screen using the commands below.  If the initial configuration is 'boring'",
  428.         "hit the space bar and try again. Practice makes perfect!",
  429.         " ",
  430.         "h         : this help screen.",
  431.         "x or Esc  : eXit the program.",
  432.         "Space bar : Start a new system.",
  433.         "a         : Restart the current system. (do it Again)",
  434.         "m         : Center the center of Mass of objects onscreen.",
  435.         "c         : Center the HEAVIEST object currently on the screen.",
  436.         "i         : Information on each object's mass and velocity.",
  437.         "Ins       : Zoom out. Doubles the area displayed.",
  438.         "Del       : Zoom in.  Halves the area displayed.",
  439.         "Home/End  : Clear screen, but continue w/ current system",
  440.         "s         : Save the parameters which yielded the current",
  441.         "            system into a file for later retrieval.",
  442.         "r         : Load system parameters from a file. (Retrieve)",
  443.         "t         : REVERSE TIME! Run the simulation backwards.",
  444.         "            A good check of the accuracy of the calculations.",
  445.         "+ or =    : Increase the interval between calcs. Runs faster.",
  446.         "-         : Decrease the interval between calcs. More accurate.",
  447.         "* (/)     : Double (halve) interval between calcs",
  448.         "Arrow keys: Increase the viewer's speed in the appropriate",
  449.         "            direction by the current value of the relative",
  450.         "            speed variable.  Note: it's probably better to use c or m",
  451.         "PgUp      : Double the relative speed variable",
  452.         "PgDn      : Halve  the relative speed variable",
  453.         " ",
  454.         "AAA's Comments",
  455.         " ",
  456.         "Using this program, you should be able to see many of the patterns",
  457.         "mentioned in the 930828 Science News: \"Three's Company -- Probing the",
  458.         "dynamics of multistar systems\", Vol. 144, No. 9, p. 136,  by Ron Cowen.",
  459.         "You might also begin to understand why the planets orbit the Sun in nearly",
  460.         "circular orbits, and why there are no massive planets in the inner solar",
  461.         "system.  You will see many examples of unstable orbits, slingshots and partner",
  462.         "swapping!  This implementation is probably not anywhere near as accurate as the",
  463.         "work referenced above, but is interesting in that many of the same patterns",
  464.         "recur.  In order to speed up the 'time evolution' of the simulation, ",
  465.         "unrealistically large solar masses are used.  As a visual aid, white and red",
  466.         "objects tend to be the most massive.  The initial state is COMPLETELY random:",
  467.         "random initial positions, masses, and trajectories.  Please pass along any",
  468.         "interesting initial configurations!  Some are included in the sol3\saved directory.",
  469.         " ",
  470.         "The numbers at the bottom of the screen are as follows:",
  471.         "Left: elapsed time; Center: time increment (affected by +,=,/,*,- and t)",
  472.         "Right: # of objects, dimensions of screen in Astronomical Units",
  473.         "(1AU = earth->sun distance, ~93 million miles)",
  474.         " ",
  475.         "Credits",
  476.         " ",
  477.         "Jeff came up with the original idea and programmed it in Pascal on",
  478.         "a Macintosh (in 1988!).  I  ported the program to C/MSDOS, optimized the",
  479.         "equations and added alot of bells and whistles.  This program was finished",
  480.         "in 1990 and has languished on my hard drive ever since.  Enjoy! -- AAA",
  481.         " ",
  482.         "Bugs",
  483.         " ",
  484.         "When you're using the save/restore commands you have to type blindly.",
  485.         "The name -- why the heck is it called sol3??",
  486.         " ",
  487.         "Press any key to continue...",
  488.         "\0"
  489.     };
  490.     
  491.     int i=0,j=0,len,height,startx,starty,maxlen=-1,longest,lines=0;
  492.  
  493.     while (strcmp(*(msgs+i),"\0") != 0){
  494.         lines++;
  495.         len=strlen(*(msgs+i));
  496.         if (len > maxlen){
  497.             maxlen=len;
  498.             longest=lines-1;
  499.         }
  500.         i++;
  501.     }
  502.  
  503.     height=textheight("Z");
  504.     starty= (MAX_Y - 2*lines*height)/2;
  505.     if (starty < 0 || starty>MAX_Y) starty=0;
  506.     startx= (MAX_X-textwidth(*(msgs+longest)))/2;
  507.     if (startx < 0 || startx > MAX_X) startx=0;
  508.     clearviewport();
  509.  
  510.     for(i=0;i<lines;i++){
  511.         if ( (starty + j*height) > MAX_Y-2*height){
  512.             outtextxy(startx,starty + j*height,"Press any key for more help, Esc to return...");
  513.             if (getch() == 27){show_info(); return;}
  514.             clearviewport();
  515.             j=0;
  516.         }
  517.         outtextxy(startx,starty+j*height,*(msgs+i));
  518.         j+=2;
  519.     }
  520.     if (getch() == 'h'){
  521.         help();
  522.         return;
  523.     }
  524.     show_info();
  525. }/* help */
  526.  
  527. void dokey(char c){
  528.    if (!c){ /* extended scan code is true */
  529.        switch(getch()){
  530.        case 'I': relativespeed*=2; return;       /* pgup */
  531.        case 'Q': relativespeed/=2; return;       /* pgdn */
  532.        case 'H': vrely=relativespeed; vy=1; return; /* up arrow */
  533.        case 'P': vrely=-relativespeed; vy=1; return; /* dn arrow */
  534.        case 'K': vrelx=relativespeed; vx=1; return; /* lf arrow */
  535.        case 'M': vrelx=-relativespeed; vx=1; return; /* rt arrow */
  536.        case 'R': viewscale*=1.414213562; break;   /* ins, zoom out */
  537.        case 'S': viewscale/=1.414213562; break;   /* del, zoom in  */
  538.        case 'O': show_info(); return; /* end */
  539.        case 'G':; /* home */
  540.        }
  541.        show_info();
  542.     }
  543.     else if (c == '0'){viewscale*=1.414213562;show_info();}
  544.     else if (c == '.'){viewscale/=1.414213562;show_info();}
  545.     else if (c == 'a' || c == 'A'){
  546.         double tmp;
  547.         tmp = viewscale;//save zoom value
  548.         restart();
  549.         if (c=='A') dt=DEF_INTERVAL;
  550.         viewscale=tmp;//restore zoom value
  551.         show_info();
  552.     }
  553.     else if (c == 'c' || c == 'C'){
  554.         center();
  555.         if (c == 'c') show_info();
  556.         else show_info();
  557.     }
  558.     else if (c == 'i'){
  559.         c=show_masses();
  560.         if (c== ' ')
  561.             show_info();
  562.         else
  563.             show_info();
  564.     }
  565.     else if (c == 'm' || c == 'M'){
  566.         cm();
  567.         if (c == 'm') show_info();
  568.         else show_info();
  569.     }
  570.     else if (c == 't'){
  571.         dt = -dt;
  572.       // show_info();
  573.     } /* time reverse JWE */
  574.  
  575.     else if (c == 's') savefile();
  576.     else if (c == 'r') restorefile();
  577.  
  578.     /* Note: wraparound is possible if dt is small */
  579.     else if (c == '+' || c == '='){ dt += 1.0; show_interval();}
  580.     else if (c == '*') {dt *= 2.0; show_interval();}
  581.     else if (c == '-'){dt -= 1.0; show_interval();}
  582.     else if (c == '/') {dt /= 2.0; show_interval();}
  583.     else if (c == ' '){init(); cm();}
  584.     else if (c == 'h') help();
  585.     else if (c == 'x' || c == 27){restorecrtmode(); exit(0);}
  586.     /* ignore any other keypress  */
  587.  
  588. } //dokey
  589.  
  590.  
  591. void parse_cmd(int argc, char *argv[]){
  592.     int GraphDrv=DETECT, GraphMod;
  593.  
  594.     if((argc==2) && (strcmp(argv[1],"svga")==0)){
  595.         installuserdriver("Svga16m",DetectVGA16);
  596.         registerfarbgidriver(Svga16m_fdriver); 
  597.         initgraph(&GraphDrv,&GraphMod,"");
  598.     }
  599.     else{
  600.         registerfarbgidriver(EGAVGA_driver_far);
  601.         detectgraph(&GraphDrv,&GraphMod);
  602.         if (GraphDrv == CGA)
  603.             GraphMod=CGAC0;
  604.         if (GraphDrv == MCGA)
  605.             GraphMod=MCGAC0;
  606.         initgraph(&GraphDrv,&GraphMod,"");
  607.     }
  608.     if (graphresult() != 0){
  609.         printf("Unable to initialize graphics.\n");
  610.         exit(graphresult());
  611.     }
  612. } //parse_cmd
  613.  
  614. void main(int argc, char *argv[]){
  615.  
  616.     parse_cmd(argc,argv);// and init graphics
  617.  
  618.     MAX_X=getmaxx(); MAXX2=MAX_X/2;
  619.     MAX_Y=getmaxy(); MAXY2=MAX_Y/2;
  620.     MAX_COL=getmaxcolor();
  621.  
  622.     init();
  623.     cm();
  624.     if (!kbhit()) dokey('h');
  625.     else getch();
  626.  
  627.     do{
  628.         do {
  629.             propagate();
  630.             plotBodies();
  631.         } while (!kbhit());
  632.         dokey(getch());
  633.     } while (1); /* program termination is in dokey() under 'x' */
  634. } //main
  635.