home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / SIMULATE.ZIP / simulate.pas next >
Pascal/Delphi Source File  |  1994-08-21  |  39KB  |  1,273 lines

  1.       (************************  BEGIN  **************************
  2.       **                                                        **
  3.       **                                                        **
  4.       **                    Flight  Simulator                   **
  5.       **                  Subsonic Jet Aircraft                 **
  6.       **                      Version  4.26                     **
  7.       **                                                        **
  8.       **                                                        **
  9.       ************************************************************
  10.  
  11.       ************************************************************
  12.       *                                                          *
  13.       *                                                          *
  14.       *            Captain Larry Thomas Brewster, Ph.D.          *
  15.       *                                                          *
  16.       *                University of Missouri-Rolla              *
  17.       *                Computer Science Department               *
  18.       *                       Feb 26, 1990                       *
  19.       *                                                          *
  20.       *                                                          *
  21.       ***********************************************************)
  22.  
  23.  
  24.       (***********************************************************
  25.       This software is made available only to individuals and only
  26.       for educational purposes. Any and all commercial use is
  27.       stricly prohibited.
  28.       ***********************************************************)
  29.  
  30.  
  31.       (***********************************************************
  32.       This program is designed to run on a Toshiba T3100 portable
  33.       computer using Borlands Pascal Version 4.0 or later compiler.
  34.       Changes in the graphics routines may be necessary
  35.       for any other computer.
  36.       ***********************************************************)
  37.  
  38.  
  39.       (********              KNOWN BUGS
  40.  
  41.       program causes math coprocessor stack overflows on an IBM XT
  42.  
  43.       bank angles of exactly zero, ninety, one-eighty, etc. cause the
  44.       horizon bar to have a length of zero.
  45.  
  46.       angle of attack (alpha) is positive in inverted flight
  47.  
  48.       graphics routines are crude - may require modification if
  49.       not 640 X 400
  50.  
  51.       this program is not a polished end product and as such no
  52.       guarantees as to performance or accuracy is implied
  53.       it is intended as an educational tool for experimentation
  54.       ********)
  55.  
  56. {$N-} { turn off math chip to prevent stack overflow }
  57.  
  58. program Simulate;
  59.  
  60.   uses Crt, Graph;
  61.  
  62.   const
  63.  
  64.   {       Aircraft Specifications             Random Aircraft          }
  65.  
  66.     Clmax                  =      1.20;   { max coef of lift           }
  67.     AR                     =      7.62;   { aspect ratio span^2/Sref   }
  68.     Tail_Arm               =        25;   { dist from a/c a.c. to tail }
  69.     max_alpha_tail         =      0.35;   { max deflection of elevator }
  70.     k_elevator             =      3.50;   { elevator constant          }
  71.     max_aileron            =      0.35;   { max aileron deflection     }
  72.     k_aileron              =      1.00;   { just a guess to look right }
  73.     maximum_mach           =      0.90;   { typical Mmo                }
  74.     maximum_ias            =    500.00;   { max guage airspeed         }
  75.     minimum_weight         =  22750.00;   { min inflight weight        }
  76.     maximum_weight         =  45500.00;   { max inflight weight        }
  77.     wing_loading           =     31.30;   { max weight over Sref       }
  78.     thrust_to_weight       =      0.30;   { thrust to weight ratio     }
  79.     maximum_altitude       =  55000.00;   { aircraft absolute ceiling  }
  80.     minimum_rpm            =     0.063;
  81.     maximum_rpm            =         1;
  82.     max_engine_rpm         =       100;
  83.  
  84.   {                  End of Aircraft Specifications                    }
  85.  
  86.   {              Constants used by equations of flight                 }
  87.  
  88.     dtime                  =      1.13;   { seconds @8MHz 2.3754 @4MHz }
  89.     text                   =         8;   { graphics text width&height }
  90.     tropopause             =  36089.00;   { feet                       }
  91.     sea_level_temperature  =   518.688;   { degrees Rankine            }
  92.     tropopause_temperature =   389.988;   { degrees Rankine            }
  93.     sea_level_density      = 0.0023769;   { slugs / cubic foot         }
  94.     Mach_1                 = 49.021424;   { sqrt(1.4*1716.5)           }
  95.     nautical_miles_to_feet =  6076.118;   { 5280*1.15078 NM to feet    }
  96.     feet_to_knots          = 0.5924835;   { 3600/(5280*1.15078)        }
  97.     knots_to_feet          = 1.6878107;   { (5280*1.15078)/3600        }
  98.     seconds_to_hour        =   3600.00;   { seconds in an hour         }
  99.     g                      = 32.174049;   { feet / sec squared         }
  100.     minimum_altitude       =      0.00;   { density equation limit     }
  101.     dev                    =     1E-20;   { minimum value used in plot }
  102.  
  103.   {             End of Constants used by equations of flight           }
  104.  
  105.   var
  106.  
  107.     w,          mach,     altitude,  attitude,
  108.     trim,       theta,    psi,       alpha_tail,  alpha_aileron,
  109.     att_last,   psi_last, tas_last,  n_last,      mach_last,
  110.     theta_last,           alt_last,               rpm_last,
  111.     last_fuelflow,        rpm,                    R : real;
  112.  
  113.     tas_lastx,  tas_lasty,  alt_lastx,  alt_lasty,
  114.     xl, xm,  yl, ym, xx, yy, zz, rcx, rcy, tbx, tby,
  115.     sky_x, sky_y, rpm_lastx, rpm_lasty,
  116.  
  117.   { graphics values }
  118.  
  119.     col_1, col_2, col_3, col_4,
  120.  
  121.     row_1, row_2, row_3, radii,
  122.  
  123.     ias_x, hdi_x, alt_x, rpm_x,
  124.     ias_y, hdi_y, alt_y, rpm_y,
  125.     ias_r, hdi_r, alt_r, rpm_r,
  126.  
  127.     tab_x, hsi_x, roc_x,
  128.     tab_y, hsi_y, roc_y,
  129.     tab_r, hsi_r, roc_r,
  130.  
  131.     GraphDriver, GraphMode, ErrorCode : integer;
  132.     Xasp, Yasp   : word;
  133.     gAR          : real;
  134.     function_key : boolean;
  135.     SaveExitProc : pointer;
  136.     s            : string;
  137.     ch           : char;
  138.  
  139.  
  140. function sigma : real;     { density / sea_level_density }
  141.   begin   { density-ratio }
  142.     sigma := exp( - (altitude/23111) + 0.294 * sin(altitude/28860)
  143.                                      + 0.213 * sin(altitude/86580) );
  144.   end {sigma};
  145.  
  146.  
  147. function density : real;   { slugs per cubic foot }
  148.   begin
  149.     density := sea_level_density * sigma;
  150.   end {density};
  151.  
  152.  
  153. function temperature : real; { degrees Rankine i.e. F + 460 }
  154.   begin
  155.     case ( altitude > tropopause ) of
  156.       true  :  temperature := tropopause_temperature;
  157.       false :  temperature := ( tropopause_temperature
  158.                               - sea_level_temperature )
  159.                               * ( altitude / tropopause )
  160.                               + sea_level_temperature;
  161.     end; { case }
  162.   end; { temperature }
  163.  
  164.  
  165. function mach_one : real;  { feet per second }
  166.   begin
  167.     mach_one := mach_1 * sqrt( temperature );
  168.   end; { mach_one }
  169.  
  170.  
  171. function V : real;  { feet per second }
  172.   begin
  173.     V := mach * mach_one;
  174.   end; { V }
  175.  
  176.  
  177. function ias : real;    { feet per second }
  178.   begin
  179.     ias := V * sqrt(sigma);
  180.   end; { ias }
  181.  
  182.  
  183. function calculate_mach_from_ias(ias_inp: real) : real;
  184.   begin           { input in knots!  output in ft/sec }
  185.     calculate_mach_from_ias  := ias_inp * knots_to_feet
  186.                                 / (sqrt(sigma)*mach_one);
  187.   end {calculate_mach_from_ias};
  188.  
  189.  
  190. function calculate_mach_from_tas(tas_inp: real) : real;
  191.   begin           { input in knots!  output in ft/sec }
  192.     calculate_mach_from_tas  := tas_inp * knots_to_feet / mach_one;
  193.   end {calculate_mach_from_tas};
  194.  
  195.  
  196. function m : real;  { slugs "pounds-sec^2/ft" }
  197.   begin
  198.     m := w / g;
  199.   end; { m }
  200.  
  201.  
  202. function q : real;
  203.   begin
  204.     q := density * sqr( V ) / 2.0;
  205.   end; { q }
  206.  
  207.  
  208. function n : real;  { load factor - or g-loading }
  209.   begin
  210.     n := ( alpha_tail + trim ) * k_elevator * q * tail_arm / m;
  211.   end; { n }
  212.  
  213.  
  214. function Cl : real;  { coefficient of lift }
  215.   begin
  216.     Cl := n * w / ( q * maximum_weight/wing_loading );
  217.   end; { Cl }
  218.  
  219.  
  220. function alpha : real;  { wing angle of attack }
  221.   const Cla0  =  0.10;  { coefficient of lift at zero angle of attack }
  222.         dClda =  3.53;  { slope of Cl versus alpha }
  223.   begin
  224.     alpha :=  (Cl - Cla0) / dClda;
  225.   end; { alpha }
  226.  
  227.  
  228. function gamma : real;  { flight path angle }
  229.   begin
  230.     gamma := attitude - alpha;
  231.   end; { gamma }
  232.  
  233.  
  234. function e : real;  { efficiency - from drag data }
  235.   const k1 = 0.87000;
  236.         k2 = 0.08355;
  237.   begin
  238.     e := k1 + k2 * sqr(mach);
  239.   end {e};
  240.  
  241.  
  242. function CDl : real;  { coefficient of drag due to lift }
  243.   begin
  244.     CDl := sqr( Cl ) / ( PI * AR * e );
  245.   end; { CDl }
  246.  
  247.  
  248. function Cd0 : real;  { coefficient of parasite drag due to airframe }
  249.   begin
  250.     Cd0   := 0.02;
  251.   end; { Cd0 }
  252.  
  253.  
  254. function D : real;    { total a/c drag }
  255.   begin
  256.     D := (Cd0 + CDl) * q * maximum_weight/wing_loading;
  257.   end; { D }
  258.  
  259.  
  260. function Xdot : real;  { horizontal velocity }
  261.   begin
  262.     Xdot := abs(V * cos(gamma));
  263.   end; { Xdot }
  264.  
  265.  
  266. function thetadot : real;  { bank angle rate of change }
  267.   begin
  268.     thetadot := alpha_aileron * k_aileron * V
  269.                 / sqrt(AR * maximum_weight/wing_loading);
  270.   end; { thetadot }
  271.  
  272.  
  273. function PsiDot : real; { horizontal turning rate }
  274.   const  k = 0.17; { cos(80) }
  275.   begin
  276.     if abs( cos(gamma) ) > k then
  277.          PsiDot := (g * n * sin(theta)) / V * cos(gamma)
  278.     else Psidot := thetadot;
  279.   end; { PsiDot }
  280.  
  281.  
  282. function gammadot : real;  { rate of change of flight path }
  283.   begin
  284.     gammadot := ( n * cos(theta) - cos(gamma) ) * g / V;
  285.   end; { gammadot }
  286.  
  287.  
  288. function maximum_thrust : real;   { in pounds }
  289.   begin
  290.     maximum_thrust := maximum_weight * thrust_to_weight * sqrt(sigma);
  291.   end {maximum_thrust};
  292.  
  293.  
  294. function T : real;   { thrust in pounds }
  295.   begin
  296.     T := maximum_thrust * rpm;
  297.   end {T};
  298.  
  299.  
  300. function Edot : real;  { energy rate of change - power }
  301.   begin
  302.     Edot := V * (T * cos(alpha) - D);
  303.   end; { Edot }
  304.  
  305.  
  306. function Vdot : real;  { acceleration }
  307.   begin
  308.     Vdot := ( (T * cos(alpha) - D) / m ) - g * sin(gamma);
  309.   end; { Vdot }
  310.  
  311.  
  312. function Hdot : real;  { vertical rate of climb }
  313.   begin
  314.     Hdot := (Edot / w) - (V * Vdot / g);
  315.   end; { Hdot }
  316.  
  317.  
  318. function Vstall : real;  {  power off flight }
  319.   begin
  320.     Vstall := sqrt( abs( (w + abs(n) * w)
  321.           / ( sea_level_density * Clmax
  322.               * maximum_weight/wing_loading)) );
  323.   end; { Vstall }
  324.  
  325.  
  326. function fuelflow : real;       { in pounds per second           }
  327.   begin                         { sfc = 0.25 lb/hr per lb thrust }
  328.       fuelflow := T * 0.25 / seconds_to_hour;
  329.   end {fuelflow};
  330.  
  331.  
  332. procedure read_character;
  333.   begin
  334.     ch    := readkey;
  335.     if ch <> #0 then function_key := false
  336.     else
  337.       begin
  338.         function_key :=    true;
  339.         ch           := readkey;
  340.       end;
  341.   end { read_character };
  342.  
  343.  
  344. procedure filter_weight;
  345.   begin
  346.     if      w < minimum_weight then w := minimum_weight
  347.     else if w > maximum_weight then w := maximum_weight ;
  348.   end {filter_weight};
  349.  
  350.  
  351. procedure filter_altitude;
  352.  begin
  353.   if altitude > maximum_altitude then altitude := maximum_altitude;
  354.   if altitude < minimum_altitude then altitude := minimum_altitude;
  355.  end {filter_altitude};
  356.  
  357.  
  358. procedure filter_rpm;
  359.   begin
  360.     if      rpm  <  minimum_rpm / sqrt(sigma) then
  361.             rpm :=  minimum_rpm / sqrt(sigma)
  362.     else if rpm  >  maximum_rpm  then
  363.             rpm :=  maximum_rpm;
  364.   end {filter_rpm};
  365.  
  366.  
  367. procedure filter_mach;
  368.   begin
  369.     if  mach > maximum_mach then mach := calculate_mach_from_ias(mach);
  370.     if ias * feet_to_knots  >  maximum_ias then
  371.         mach := calculate_mach_from_ias(maximum_ias)
  372.     else if ias < Vstall then
  373.         mach := calculate_mach_from_ias(Vstall * feet_to_knots);
  374.   end {filter_mach};
  375.  
  376.  
  377. procedure filter_psi;
  378.   begin
  379.     while psi > 2*PI do psi :=  psi - 2*PI;
  380.     while psi < 0000 do psi :=  psi + 2*PI;
  381.   end; { filter_psi }
  382.  
  383.  
  384. procedure filter_data;
  385.   begin
  386.     filter_weight;
  387.     filter_altitude;
  388.     filter_rpm;
  389.     filter_mach;
  390.     filter_psi;
  391.   end {filter_data};
  392.  
  393.  
  394. procedure initialize_variables;
  395.   begin
  396.     GetAspectRatio(  Xasp,  Yasp );
  397.     gAR   :=             Xasp/Yasp;
  398.  
  399.     col_1 :=         GetMaxX div 8;
  400.     col_2 := col_1 + GetMaxX div 4;
  401.     col_3 := col_2 + GetMaxX div 4;
  402.     col_4 := col_3 + GetMaxX div 4;
  403.  
  404.     row_1 :=         GetMaxY div 6;
  405.     row_2 := row_1 + GetMaxY div 3;
  406.     row_3 := row_2 + GetMaxY div 3;
  407.  
  408.     radii := GetMaxX div 12; R := round( 0.9 * radii );
  409.  
  410.     ias_x := col_1;    hdi_x := col_2;    alt_x := col_3;    rpm_x := col_4;
  411.     ias_y := row_1;    hdi_y := row_1;    alt_y := row_1;    rpm_y := row_1;
  412.     ias_r := radii;    hdi_r := radii;    alt_r := radii;    rpm_r := radii;
  413.  
  414.     tab_x := col_1;    hsi_x := col_2;    roc_x := col_3;
  415.     tab_y := row_2;    hsi_y := row_2;    roc_y := row_2;
  416.     tab_r := radii;    hsi_r := radii;    roc_r := radii;
  417.  
  418.     attitude      :=          2.5 * PI/180;
  419.     psi           :=        240.0 * PI/180;
  420.     rpm           :=   75 / max_engine_rpm;
  421.     mach          :=                 280.0;
  422.     altitude      :=               25000.0;
  423.     w             :=  0.9 * maximum_weight;
  424.     theta         :=        0.001 * PI/180;
  425.     alpha_tail    :=                   0.0;
  426.     alpha_aileron :=                   0.0;
  427.     trim          := m / (tail_arm * q * k_elevator);
  428.     filter_data;
  429.   end {initialize_variables};
  430.  
  431.  
  432. procedure draw_rpm(x, y : integer);
  433.   begin
  434.     rpm_last  := rpm;
  435.     str( rpm_last * max_engine_rpm:5:0, s );
  436.     outtextxy(rpm_x - 5 * (text div 2), rpm_y + text div 2, s );
  437.     line(rpm_x, rpm_y, x, y);
  438.     rpm_lastx := x;
  439.     rpm_lasty := y;
  440.   end;
  441.  
  442.  
  443. procedure rpm_needle;
  444.   var   x, y   : integer;  z   : real;
  445.   begin
  446.     z := rpm * (max_engine_rpm/100) * 16 * PI/10;
  447.     x := rpm_x + round( 0.9 * rpm_r * cos(13*PI/10 - z) );
  448.     y := rpm_y - round( 0.9 * rpm_r * sin(13*PI/10 - z) * gAR );
  449.     if  ( (abs(rpm_lastx - x) > 0)  OR  (abs(rpm_lasty - y) > 0) )
  450.     then  begin
  451.           setcolor(black);
  452.           str( rpm_last * max_engine_rpm:5:0, s );
  453.           outtextxy(rpm_x-5 * (text div 2), rpm_y + text div 2, s );
  454.           line(rpm_x, rpm_y, rpm_lastx, rpm_lasty);
  455.           setcolor(white);
  456.           draw_rpm(x, y);
  457.     end;
  458.   end; { rpm_needle }
  459.  
  460.  
  461. procedure rpmmeter;
  462.   var z : real;
  463.   begin
  464.     circle(rpm_x, rpm_y, rpm_r);
  465.     outtextxy(rpm_x+             round(rpm_r*sin((13-2*0)*PI/10)),
  466.               rpm_y-             round(gAR*rpm_r*sin((13-2*0)*PI/10)),'0');
  467.     outtextxy(rpm_x-(text  *  2)+round(rpm_r*cos((13-2*1)*PI/10)),
  468.               rpm_y-             round(gAR*rpm_r*sin((13-2*1)*PI/10)),'12');
  469.     outtextxy(rpm_x-(text  *  2)+round(rpm_r*cos((13-2*2)*PI/10)),
  470.               rpm_y-(text div 2)-round(gAR*rpm_r*sin((13-2*2)*PI/10)),'25');
  471.     outtextxy(rpm_x-(text  *  2)+round(rpm_r*cos((13-2*3)*PI/10)),
  472.               rpm_y-(text div 2)-round(gAR*rpm_r*sin((13-2*3)*PI/10)),'37');
  473.     outtextxy(rpm_x-(text      )+round(rpm_r*cos((13-2*4)*PI/10)),
  474.               rpm_y-(text      )-round(gAR*rpm_r*sin((13-2*4)*PI/10)),'50');
  475.     outtextxy(rpm_x+(text div 2)+round(rpm_r*cos((13-2*5)*PI/10)),
  476.               rpm_y-(text div 2)-round(gAR*rpm_r*sin((13-2*5)*PI/10)),'62');
  477.     outtextxy(rpm_x+(text div 2)+round(rpm_r*cos((13-2*6)*PI/10)),
  478.               rpm_y-(text div 2)-round(gAR*rpm_r*sin((13-2*6)*PI/10)),'75');
  479.     outtextxy(rpm_x+(text div 2)+round(rpm_r*cos((13-2*7)*PI/10)),
  480.               rpm_y-(text div 2)-round(gAR*rpm_r*sin((13-2*7)*PI/10)),'87');
  481.     outtextxy(rpm_x+(text div 2)+round(rpm_r*cos((13-2*8)*PI/10)),
  482.               rpm_y-             round(gAR*rpm_r*sin((13-2*8)*PI/10)),'100');
  483.   end; { rpmmeter }
  484.  
  485.  
  486. procedure draw_n;
  487.   begin
  488.     n_last := n;
  489.     str( n_last:5:2, s );
  490.     outtextxy(ias_x - 6 * (text div 2),
  491.               ias_y - round(gAR * ias_r) - text, s);
  492.   end;  { draw_n }
  493.  
  494.  
  495. procedure draw_mach;
  496.   begin
  497.     mach_last  := mach;
  498.     str( mach_last:5:3, s );
  499.     outtextxy( ias_x -     5     * (text div 2),
  500.                ias_y - round(gAR * ias_r) + text, s );
  501.   end;  { draw_mach }
  502.  
  503.  
  504. procedure draw_tas;
  505.   begin
  506.     tas_last  := V;
  507.     str( tas_last * feet_to_knots:3:0, s );
  508.     outtextxy( ias_x - 3 * (text div 2 ),
  509.                ias_y - round(gAR * ias_r) + 3 * text, s );
  510.   end;  { draw_tas }
  511.  
  512.  
  513. procedure draw_ias(x, y : integer);
  514.   begin
  515.     line(ias_x, ias_y, x, y);
  516.     tas_lastx := x;
  517.     tas_lasty := y;
  518.   end;  { draw_ias }
  519.  
  520.  
  521. procedure ias_needle;
  522.   const
  523.          range  =  500;
  524.          k      =  5.5;  { ~3.5*PI/2  }
  525.          e      =    0;
  526.   var    x, y : integer;
  527.   begin
  528.     x := ias_x + round(0.8 * ias_r
  529.             * cos( (ias * 5.5 / (range * knots_to_feet)) - PI/2) );
  530.     y := ias_y + round(gAR * 0.8 * ias_r
  531.             * sin( (ias * 5.5 / (range * knots_to_feet)) - PI/2));
  532.  
  533.     if abs(n - n_last) >= 0.01 then begin
  534.       setcolor(black);
  535.       str( n_last:5:2, s );
  536.       outtextxy(ias_x - 6*(text div 2),
  537.                 ias_y - round(gAR * ias_r) - text, s);
  538.       setcolor(white);
  539.       draw_n;
  540.     end;
  541.  
  542.     if abs(mach - mach_last) >= 0.001 then begin
  543.       setcolor(black);
  544.       str(mach_last:5:3, s);
  545.       outtextxy( ias_x -     5     * (text div 2),
  546.                  ias_y - round(gAR * ias_r) + text, s );
  547.       setcolor(white);
  548.       draw_mach;
  549.     end;
  550.  
  551.     if abs(V - tas_last) * feet_to_knots >= 1 then begin
  552.       setcolor(black);
  553.       str( tas_last * feet_to_knots:3:0, s );
  554.       outtextxy( ias_x -     3     * (text div 2 ),
  555.                  ias_y - round(gAR * ias_r) + 3 * text,    s );
  556.       setcolor(white);
  557.       draw_tas;
  558.     end;
  559.  
  560.     if  ( (abs(tas_lastx - x) > e)  OR  (abs(tas_lasty - y) > e) ) then
  561.     begin
  562.       setcolor(black);
  563.       line(ias_x, ias_y, tas_lastx, tas_lasty);
  564.       setcolor(white);
  565.       draw_ias(x, y);
  566.     end;
  567.   end; {ias_needle}
  568.  
  569.  
  570. procedure airspeed;
  571.   const
  572.     k_range = 0.011;  { arc(~3.5*PI/2) / max value 500  }
  573.   begin {airspeed}              {  5.5 / 500  }
  574.     circle(ias_x, ias_y, ias_r);
  575.     outtextxy(ias_x + 3 * text div 2 + round(ias_r * cos((060*k_range) - PI/2)),
  576.               ias_y + round(gAR*ias_r * sin((060*k_range) - PI/2)), '60');
  577.     outtextxy(ias_x + 1 * text + round(ias_r * cos((120*k_range) - PI/2)),
  578.               ias_y + round(gAR*ias_r * sin((120*k_range) - PI/2)), '120');
  579.     outtextxy(ias_x + 1 * text + round(ias_r * cos((180*k_range) - PI/2)),
  580.               ias_y + round(gAR*ias_r * sin((180*k_range) - PI/2)), '180');
  581.     outtextxy(ias_x + 0 * text + round(ias_r*cos((240*k_range)-PI/2)),
  582.               ias_y + round(gAR*ias_r * sin((240*k_range) - PI/2)),'240');
  583.     outtextxy(ias_x - 2 * text + round(ias_r*cos((300*k_range)-PI/2)),
  584.               ias_y + round(gAR*ias_r * sin((300*k_range) - PI/2)),'300');
  585.     outtextxy(ias_x - 3 * text + round(ias_r*cos((360*k_range)-PI/2)),
  586.               ias_y + round(gAR*ias_r * sin((360*k_range) - PI/2)),'360');
  587.     outtextxy(ias_x - 3 * text + round(ias_r*cos((420*k_range)-PI/2)),
  588.               ias_y + round(gAR*ias_r * sin((420*k_range) - PI/2)),'420');
  589.     outtextxy(ias_x - 7 * text div 2 + round(ias_r*cos((480*k_range)-PI/2)),
  590.               ias_y + round(gAR*ias_r * sin((480*k_range) - PI/2)),'480');
  591.   end; { airspeed }
  592.  
  593.  
  594. function Ydenom : real;
  595.   var x : real;
  596.   begin
  597.     x := sqr( sin(attitude) * sqr(cos(theta)) );
  598.     if abs(x) < dev then x := dev;
  599.     Ydenom := x;
  600.   end;
  601.  
  602.  
  603. function Yw : integer;
  604.   begin
  605.     Yw := round( gAR * R * sin(attitude) * sqr( cos(theta) )
  606.           * ( 1 + sqrt(
  607.           abs( 1 + ( sqr(sin(theta)) - sqr(sin(attitude)*cos(theta)))
  608.           / Ydenom ))));
  609.   end;
  610.  
  611.  
  612. function Yh : integer;
  613.   begin
  614.     Yh := round( gAR * R * sin(attitude) * sqr( cos(theta) )
  615.           * ( 1 - sqrt(
  616.           abs( 1 + ( sqr(sin(theta)) - sqr(sin(attitude)*cos(theta)))
  617.           / Ydenom ))));
  618.   end;
  619.  
  620.  
  621. function Xdenom : real;
  622.   var x : real;
  623.   begin
  624.     x := sqr( sin(theta) * sin(attitude) );
  625.     if abs(x) < dev then x := dev;
  626.     Xdenom := x;
  627.   end;
  628.  
  629.  
  630. function Xw : integer;
  631.   begin
  632.     Xw := round(-R * sin(attitude) * sin(theta) * cos(theta)
  633.           * ( 1 + sqrt(abs( 1 + sqr( cos(attitude) ) / Xdenom ) ) ) );
  634.   end;
  635.  
  636.  
  637. function Xh : integer;
  638.   begin
  639.     Xh := round(-R * sin(attitude) * sin(theta) * cos(theta)
  640.           * ( 1 - sqrt(abs( 1 + sqr( cos(attitude) ) / Xdenom ) ) ) );
  641.   end;
  642.  
  643.  
  644. procedure draw_hdi;
  645.   var  x0, y0 : integer;
  646.   begin
  647.     sky_x := hdi_x - round( 0.8 * hdi_r * sin(theta) * cos(attitude)
  648.                             / abs(cos(attitude)) );
  649.     sky_y := hdi_y - round( 0.8 * gAR * hdi_r * cos(theta) * cos(attitude)
  650.                             / abs(cos(attitude)) ) - text div 2;
  651.  
  652.     outtextxy(sky_x - (text div 2), sky_y, #30);
  653.  
  654.     xl := hdi_x + Xw;
  655.     xm := hdi_x + Xh;
  656.     yl := hdi_y + Yw;
  657.     ym := hdi_y + Yh;
  658.  
  659.  
  660.     line(xl, yl, xm, ym);
  661.     line(hdi_x - hdi_r div 2, hdi_y + hdi_r div 6, hdi_x, hdi_y);
  662.     line(hdi_x + hdi_r div 2, hdi_y + hdi_r div 6, hdi_x, hdi_y);
  663.     line(hdi_x - hdi_r div 2, hdi_y + hdi_r div 6,
  664.          hdi_x + hdi_r div 2, hdi_y + hdi_r div 6);
  665.     circle( (xl+xm) div 2, (yl+ym) div 2, 4 );
  666.  
  667.     circle(hdi_x, hdi_y, 3);
  668.  
  669.     att_last   := attitude;
  670.     theta_last :=    theta;
  671.   end; { draw_hdi }
  672.  
  673.  
  674. procedure horizon_bar;
  675.   begin
  676.     if (  ( abs(attitude - att_last) >= 0.005760 )   { about 0.33 deg }
  677.        or ( abs(theta - theta_last)  >= 0.017453 ) ) { about 0.99 deg }
  678.     then begin
  679.          setcolor(black);
  680.          outtextxy(sky_x - (text div 2), sky_y, #30);
  681.          circle( (xl+xm) div 2, (yl+ym) div 2, 4 );
  682.          line(xl, yl, xm, ym);
  683.          setcolor(white);
  684.          draw_hdi;
  685.     end;
  686.   end; { horizon_bar }
  687.  
  688.  
  689. procedure hdi;
  690.   var    s1, s2, s3, s4   : integer;
  691.   begin
  692.     s1 := round(hdi_r * sin( PI/6 ));
  693.     s2 := round(gAR * hdi_r * cos( PI/6 ));
  694.     s3 := round(hdi_r * sin( PI/3 ));
  695.     s4 := round(gAR * hdi_r * cos( PI/3 ));
  696.     circle(hdi_x, hdi_y, hdi_r);
  697.     setlinestyle(solidln, 0, thickwidth);
  698.     line(hdi_x-1, hdi_y-round(gAR * hdi_r),
  699.          hdi_x-1, hdi_y-round(gAR * hdi_r)-text);
  700.     line(hdi_x-s1, hdi_y-s2, hdi_x-s1-4, hdi_y-s2-4);
  701.     line(hdi_x+s1, hdi_y-s2, hdi_x+s1+4, hdi_y-s2-4);
  702.     line(hdi_x-s3, hdi_y-s4, hdi_x-s3-4, hdi_y-s4-4);
  703.     line(hdi_x+s3, hdi_y-s4, hdi_x+s3+4, hdi_y-s4-4);
  704.     setlinestyle(solidln, 0, normwidth);
  705.   end; { hdi }
  706.  
  707.  
  708. procedure draw_altitude(x, y : integer);
  709.   begin
  710.     alt_last  := altitude;
  711.     str( alt_last:5:0, s );
  712.     outtextxy(alt_x - 5 * text div 2, alt_y + text, s);
  713.     line(alt_x, alt_y, x, y);
  714.     alt_lastx := x;
  715.     alt_lasty := y;
  716.   end;
  717.  
  718.  
  719. procedure alt_needle;
  720.   const e      =       0;
  721.   var   x, y   : integer;
  722.         z      :    real;
  723.   begin
  724.     z := round( altitude / 1000 );
  725.     z := round( altitude - (z * 1000) );
  726.     x := alt_x + round( 0.82 * alt_r * cos(PI/2 - ((z/1000) * 2 * PI)));
  727.     y := alt_y - round( 0.82 * alt_r * sin(PI/2 - ((z/1000) * 2 * PI))*gAR);
  728.     if  ( (abs(alt_lastx - x) > 0)  OR  (abs(alt_lasty - y) > 0) )
  729.     then  begin
  730.           setcolor(black);
  731.           str( alt_last:5:0, s );
  732.           outtextxy(alt_x - 5 * text div 2, alt_y + text, s);
  733.           line(alt_x, alt_y, alt_lastx, alt_lasty);
  734.           setcolor(white);
  735.           draw_altitude(x, y);
  736.     end;
  737.   end; { alt_needle }
  738.  
  739.  
  740. procedure altimeter;
  741.   begin
  742.     circle(alt_x, alt_y, alt_r);
  743.     outtextxy(alt_x - (text div 2),
  744.               alt_y - (text      )-round(gAR*alt_r*sin((2*0+5)*PI/10)),'0');
  745.     outtextxy(alt_x -              round(alt_r*cos((2*1+5)*PI/10)),
  746.               alt_y - (text      )-round(gAR*alt_r*sin((2*1+5)*PI/10)),'1');
  747.     outtextxy(alt_x + (text  -  2)-round(alt_r*cos((2*2+5)*PI/10)),
  748.               alt_y - (text div 2)-round(gAR*alt_r*sin((2*2+5)*PI/10)),'2');
  749.     outtextxy(alt_x + (text  -  2)-round(alt_r*cos((2*3+5)*PI/10)),
  750.               alt_y -              round(gAR*alt_r*sin((2*3+5)*PI/10)),'3');
  751.     outtextxy(alt_x -              round(alt_r*cos((2*4+5)*PI/10)),
  752.               alt_y -              round(gAR*alt_r*sin((2*4+5)*PI/10)),'4');
  753.     outtextxy(alt_x - (text div 2)-round(alt_r*cos((2*5+5)*PI/10)),
  754.               alt_y + (text div 2)-round(gAR*alt_r*sin((2*5+5)*PI/10)),'5');
  755.     outtextxy(alt_x - (text      )-round(alt_r*cos((2*6+5)*PI/10)),
  756.               alt_y -              round(gAR*alt_r*sin((2*6+5)*PI/10)),'6');
  757.     outtextxy(alt_x - (text  +  2)-round(alt_r*cos((2*7+5)*PI/10)),
  758.               alt_y -              round(gAR*alt_r*sin((2*7+5)*PI/10)),'7');
  759.     outtextxy(alt_x - (text  +  2)-round(alt_r*cos((2*8+5)*PI/10)),
  760.               alt_y - (text div 2)-round(gAR*alt_r*sin((2*8+5)*PI/10)),'8');
  761.     outtextxy(alt_x - (text      )-round(alt_r*cos((2*9+5)*PI/10)),
  762.               alt_y - (text      )-round(gAR*alt_r*sin((2*9+5)*PI/10)),'9');
  763.   end; { altimeter }
  764.  
  765.  
  766. procedure draw_t_and_b(x, y : integer);
  767.   begin
  768.     line(tab_x, tab_y, tab_x + y, tab_y - x);
  769.     setlinestyle(solidln, 0, normwidth);
  770.     tbx := x;
  771.     tby := y;
  772.   end;  { draw_t_and_b }
  773.  
  774.  
  775. procedure t_and_b_needle;
  776.   const  k    =      10;
  777.   var    t    :    real;
  778.          x, y : integer;
  779.   begin
  780.     t := psidot * k;
  781.     if abs(t) > PI/4   then    t := (PI/4) * t / abs(t);
  782.     x := round( 0.83 * tab_r * cos(t) * gAR);
  783.     y := round( 0.83 * tab_r * sin(t) );
  784.     if ((tby <> y) or (tbx <> x)) then begin
  785.       setlinestyle(solidln, 0, thickwidth);
  786.       setcolor(black);
  787.       line(tab_x, tab_y, tab_x + tby, tab_y - tbx);
  788.       setcolor(white);
  789.       draw_t_and_b(x, y);
  790.     end;
  791.   end; { t_and_b_needle }
  792.  
  793.  
  794. procedure t_and_b;
  795.   var    s1, s2 : integer;
  796.   begin
  797.     s1 := round(tab_r * sin( PI/6 ) );
  798.     s2 := round(tab_r * cos( PI/6 ) * gAR);
  799.     circle(tab_x, tab_y, tab_r);
  800.     setlinestyle(solidln, 0, thickwidth);
  801.     line(tab_x, tab_y-round(gAR*tab_r),
  802.          tab_x, tab_y-round(gAR*tab_r)-text div 2);
  803.     line(tab_x-s1, tab_y-s2, tab_x-s1-4, tab_y-s2-4);
  804.     line(tab_x+s1, tab_y-s2, tab_x+s1+4, tab_y-s2-4);
  805.     setlinestyle(solidln, 0, normwidth);
  806.   end; {t_and_b}
  807.  
  808.  
  809. procedure draw_heading;
  810.   begin
  811.     psi_last  := psi;
  812.     str( psi_last * 180/PI:3:0, s );
  813.     outtextxy(hsi_x - length(s) * (text div 2),
  814.               hsi_y + text - round(gAR*hsi_r), s);
  815.   end;  { draw_heading }
  816.  
  817.  
  818. procedure hsi_heading;
  819. begin
  820.   if psi <> psi_last then begin
  821.     setcolor(black);
  822.     str( psi_last*180/PI:3:0, s );
  823.     outtextxy(hsi_x - length(s) * (text div 2),
  824.               hsi_y + text - round(gAR*hsi_r), s);
  825.     setcolor(white);
  826.     draw_heading;
  827.   end;
  828. end; { hsi_heading }
  829.  
  830.  
  831. procedure hsi;
  832.   begin
  833.     circle(hsi_x, hsi_y, hsi_r);
  834.     setlinestyle(solidln, 0, thickwidth);
  835.     outtextxy(hsi_x-(text div 2), hsi_y-round(gAR*hsi_r), 'v');
  836.     setlinestyle(solidln, 0, normwidth);
  837.   end; { hsi }
  838.  
  839.  
  840. procedure draw_rofc(x, y : integer);
  841.   begin
  842.     rcx := x; rcy := y;
  843.     line( roc_x, roc_y, x, y);
  844.   end;  { draw_rofc }
  845.  
  846.  
  847. procedure rofc_needle;
  848.   const  k     =  0.1132;    { 6000 ft/min = full scale i.e. 90%  }
  849.   var    x, y  : integer;    t : real;
  850.   begin
  851.     t := hdot * k;
  852.     if abs(t) > 0.9 * PI   then   t := 0.9 * PI * t / abs(t);
  853.     x := roc_x - round(0.82 * roc_r * cos(t) );
  854.     y := roc_y - round(0.82 * roc_r * sin(t)*gAR );
  855.     if ( (abs(rcx - x) > 0) or (abs(rcy - y) > 0) ) then begin
  856.       setcolor(black);
  857.       line( roc_x, roc_y, rcx, rcy);
  858.       setcolor(white);
  859.       draw_rofc(x, y);
  860.     end;
  861.   end; { rofc_needle }
  862.  
  863.  
  864. procedure rofc;
  865.   begin
  866.     circle(roc_x, roc_y, roc_r);
  867.     outtextxy(roc_x - ( 3 * text div 2) - roc_r,
  868.               roc_y-( text div 2),'0');
  869.     outtextxy(roc_x-(text  *  3) - round(roc_r*cos( 0.9*1*PI/6)),
  870.               roc_y-(text      ) - round(gAR*roc_r*sin( 0.9*1*PI/6)),'  1');
  871.     outtextxy(roc_x-(text  *  3) - round(roc_r*cos(-0.9*1*PI/6)),
  872.               roc_y-               round(gAR*roc_r*sin(-0.9*1*PI/6)),'  1');
  873.     outtextxy(roc_x-(text      ) - round(roc_r*cos( 0.9*2*PI/6)),
  874.               roc_y-(text      ) - round(gAR*roc_r*sin( 0.9*2*PI/6)),'2');
  875.     outtextxy(roc_x-(text      ) - round(roc_r*cos(-0.9*2*PI/6)),
  876.               roc_y-               round(gAR*roc_r*sin(-0.9*2*PI/6)),'2');
  877.     outtextxy(roc_x-(text div 2) - round(roc_r*cos( 0.9*4*PI/6)),
  878.               roc_y-(text      ) - round(gAR*roc_r*sin( 0.9*4*PI/6)),'4');
  879.     outtextxy(roc_x-(text div 2) - round(roc_r*cos(-0.9*4*PI/6)),
  880.               roc_y+(text div 2) - round(gAR*roc_r*sin(-0.9*4*PI/6)),'4');
  881.     outtextxy(roc_x+(text      ) - round(roc_r*cos( 0.9*6*PI/6)),
  882.               roc_y-(text      ) - round(gAR*roc_r*sin( 0.9*6*PI/6)),'6');
  883.     outtextxy(roc_x+(text      ) - round(roc_r*cos(-0.9*6*PI/6)),
  884.               roc_y-(text div 2) - round(gAR*roc_r*sin(-0.9*6*PI/6)),'6');
  885.   end; {rofc}
  886.  
  887.  
  888. procedure draw_fuelflow;
  889.   begin
  890.     last_fuelflow := fuelflow;
  891.     str( (last_fuelflow * seconds_to_hour):4:1, s );
  892.     outtextxy( col_4 - (6 * text div 2),
  893.                row_1+(row_2-row_1-text) div 2, 'ff '+s );
  894.   end;  { draw_fuelflow }
  895.  
  896.  
  897. procedure fuelflow_value;
  898.   begin
  899.     if ( abs(last_fuelflow - fuelflow) > (1/6000) ) then begin
  900.       setcolor(black);
  901.       str( (last_fuelflow * seconds_to_hour):4:1, s );
  902.       outtextxy( col_4-(6 * text div 2),
  903.                  row_1+(row_2-row_1-text) div 2, 'ff '+s );
  904.       setcolor(white);
  905.       draw_fuelflow;
  906.     end;
  907.   end; { fuelflow_value }
  908.  
  909.  
  910. procedure draw_circles;
  911.   begin
  912.     airspeed;
  913.     draw_n;
  914.     draw_mach;
  915.     draw_tas;
  916.     draw_ias(ias_x,ias_y);
  917.     hdi;
  918.     draw_hdi;
  919.     altimeter;
  920.     draw_altitude(alt_x,alt_y);
  921.     t_and_b;
  922.     draw_t_and_b(0,0);
  923.     hsi;
  924.     draw_heading;
  925.     rofc;
  926.     draw_rofc(roc_x,roc_y);
  927.     draw_fuelflow;
  928.     rpmmeter;
  929.     draw_rpm(rpm_x,rpm_y);
  930.   end; { draw_circles }
  931.  
  932.  
  933. procedure print_data;
  934.   begin {print_data}
  935.     ias_needle;
  936.     horizon_bar;
  937.     alt_needle;
  938.     t_and_b_needle;
  939.     hsi_heading;
  940.     rofc_needle;
  941.     fuelflow_value;
  942.     rpm_needle;
  943.   end {print_data};
  944.  
  945.  
  946. procedure calculate_time_changes;
  947.   begin
  948.     psi      := psi + psidot * dtime;
  949.     theta    := theta + thetadot * dtime;
  950.     attitude := attitude + gammadot * dtime;
  951.     w        := w - dtime * fuelflow;
  952.     altitude := altitude + hdot * dtime;
  953.     mach     := calculate_mach_from_tas((V+Vdot * dtime)*feet_to_knots);
  954.     filter_data;
  955.   end {calculate_time_changes};
  956.  
  957.  
  958. procedure readreal(var realnumber : real);
  959.   const  bs = #8; { backspace }
  960.   var    keys   : string;
  961.          number : real;
  962.          code   : integer;
  963.          funckey: boolean;
  964.   procedure decrease;
  965.     begin
  966.       if length(keys) > 0 then begin
  967.         keys := copy(keys, 1, length(keys)-1);
  968.       end;
  969.     end; { decrease }
  970.   begin
  971.     keys    := '';
  972.     repeat
  973.       ch    := readkey;
  974.       if ch <> #0 then funckey := false
  975.       else
  976.         begin
  977.           funckey := true;
  978.           ch      := readkey;
  979.       end;
  980.       case funckey of
  981.         true  : case ord(ch) of
  982.                   75  :  decrease;
  983.                 end;
  984.         false : case ch of
  985.                   '-','+','0'..'9', '.' : begin
  986.                                             keys := keys + ch;
  987.                                           end;
  988.                 end;
  989.       end;
  990.     until ch in [ #10, #13 ];
  991.     if pos('.', keys) = 1 then keys := '0' + keys;
  992.     val( keys, number, code );
  993.     if  (code=0)  then   realnumber := number;
  994.   end {readreal};
  995.  
  996.  
  997. procedure set_rpm;
  998.   var  x  : real;
  999.   begin
  1000.     x := rpm * max_engine_rpm;
  1001.     readreal(x);
  1002.     x := x / max_engine_rpm;
  1003.     rpm  := x;
  1004.     filter_rpm;
  1005.   end; {set_rpm}
  1006.  
  1007.  
  1008. procedure set_pitch;
  1009.   var  x  : real;
  1010.   begin
  1011.     x := attitude * 180/PI;
  1012.     readreal(x);
  1013.     attitude := x * PI/180;
  1014.   end; {set_pitch}
  1015.  
  1016.  
  1017. procedure set_elevator;
  1018.   var  x  : real;
  1019.   begin
  1020.     x := alpha_tail * 180/PI;
  1021.     readreal(x);
  1022.     x := x * PI/180;
  1023.     if x >  max_alpha_tail then x :=  max_alpha_tail;
  1024.     if x < -max_alpha_tail then x := -max_alpha_tail;
  1025.     alpha_tail  :=   x;
  1026.   end; {set_elevator}
  1027.  
  1028.  
  1029. procedure set_aileron;
  1030.   var  x  : real;
  1031.   begin
  1032.     x := alpha_aileron * 180/PI;
  1033.     readreal(x);
  1034.     x := x * PI/180;
  1035.     if x >  max_aileron then x :=  max_aileron;
  1036.     if x < -max_aileron then x := -max_aileron;
  1037.     alpha_aileron := x;
  1038.   end; {set_aileron}
  1039.  
  1040.  
  1041. procedure set_mach;
  1042.   var  x  : real;
  1043.   begin
  1044.     x := mach;
  1045.     readreal(x);
  1046.     mach  :=  x;
  1047.     filter_mach;
  1048.   end; {set_mach}
  1049.  
  1050.  
  1051. procedure set_weight;
  1052.   var  x  : real;
  1053.   begin
  1054.     x := w;
  1055.     readreal(x);
  1056.     w := x;
  1057.     filter_weight;
  1058.   end; {set_weight}
  1059.  
  1060.  
  1061. procedure set_bank;
  1062.   var  x  : real;
  1063.   begin
  1064.     x := theta * 180/PI;
  1065.     readreal(x);
  1066.     theta  := x * PI/180;
  1067.   end; {set_bank}
  1068.  
  1069.  
  1070. procedure set_heading;
  1071.   var  x  : real;
  1072.   begin
  1073.     x := psi * 180/PI;
  1074.     readreal(x);
  1075.     psi :=  x * PI/180;
  1076.     filter_psi;
  1077.   end; {set_heading}
  1078.  
  1079.  
  1080. procedure set_altitude;
  1081.   var  x  : real;
  1082.   begin
  1083.     x := altitude/100;
  1084.     readreal(x);
  1085.     altitude := x * 100;
  1086.     filter_altitude;
  1087.   end; {set_altitude}
  1088.  
  1089.  
  1090. procedure set_level; { pitch is wrong in inverted flight }
  1091.   const  e = 0.09;   { ~cos(85) }
  1092.   begin
  1093.     if ( (abs(cos(theta)) > e) and (abs(cos(alpha)) > e) ) then
  1094.     begin
  1095.       alpha_tail := 0.0;
  1096.       trim       := m / ( Tail_arm * k_elevator * q * cos(theta) );
  1097.       rpm        := D / ( maximum_thrust * cos(alpha) );
  1098.       attitude   := alpha;
  1099.       filter_data;
  1100.     end;
  1101.   end; { set_level }
  1102.  
  1103.  
  1104. procedure set_trim;
  1105.   begin
  1106.     trim       := alpha_tail + trim;
  1107.     alpha_tail :=               0.0;
  1108.   end; { set_trim }
  1109.  
  1110.  
  1111. procedure idle;
  1112.   begin
  1113.     while not keypressed do
  1114.       begin
  1115.         calculate_time_changes;
  1116.         print_data;
  1117.       end;
  1118.     read_character;
  1119.   end; {idle}
  1120.  
  1121.  
  1122. procedure pickupkeys;  { keyboard codes on page 579 of Pascal manual }
  1123.   const delta_aileron  = 2.0E-3; { These are all }
  1124.         delta_elevator = 1.0E-3; { just a bunch  }
  1125.         delta_rpm      = 1.0E-2; { of guesses    }
  1126.   begin
  1127.     repeat
  1128.       idle;
  1129.       case function_key of
  1130.         true  : case ord(ch) of
  1131.         { PgUp }  73 : begin
  1132.                          rpm := rpm + delta_rpm;
  1133.                          filter_rpm;
  1134.                        end;
  1135.         { PgDn }  81 : begin
  1136.                          rpm := rpm - delta_rpm;
  1137.                          filter_rpm;
  1138.                        end;
  1139.         { UpArw } 72 : begin
  1140.                          alpha_tail := alpha_tail - delta_elevator;
  1141.                          if alpha_tail        <    -max_alpha_tail
  1142.                             then alpha_tail  :=    -max_alpha_tail;
  1143.                        end;
  1144.         { DwnArw }80 : begin
  1145.                          alpha_tail := alpha_tail + delta_elevator;
  1146.                          if alpha_tail         >    max_alpha_tail
  1147.                             then alpha_tail   :=    max_alpha_tail;
  1148.                        end;
  1149.         { LftArw }75 : begin
  1150.                          alpha_aileron := alpha_aileron - delta_aileron;
  1151.                           if alpha_aileron        <        -max_aileron
  1152.                              then alpha_aileron  :=        -max_aileron;
  1153.                        end;
  1154.         { RtArw } 77 : begin
  1155.                          alpha_aileron := alpha_aileron + delta_aileron;
  1156.                          if alpha_aileron         >         max_aileron
  1157.                             then alpha_aileron   :=         max_aileron;
  1158.                        end;
  1159.         { End }   79 : begin
  1160.                          alpha_aileron := 0;
  1161.                          alpha_tail    := 0;
  1162.                        end;
  1163.         { Home }  71 : begin
  1164.                          alpha_aileron := 0;
  1165.                          theta         := 0.001;
  1166.                          alpha_tail    := 0;
  1167.                          trim          := m/(tail_arm * q * k_elevator);
  1168.                          attitude      := 2.25 * PI/180;
  1169.                        end;
  1170.         {
  1171.          ^LArw = 115 : ^RArw = 116 : ^End  = 117 :
  1172.          ^PgDn = 118 : ^Home = 119 : ^PgUp = 132 :
  1173.         }
  1174.                 end;
  1175.         false : case upcase(ch) of
  1176.                     'R' : set_rpm;
  1177.                     'P' : set_pitch;
  1178.                     'E' : set_elevator;
  1179.                     'A' : set_aileron;
  1180.                     'S' : set_mach;
  1181.                     'W' : set_weight;
  1182.                     'B' : set_bank;
  1183.                     'F' : set_altitude;
  1184.                     'H' : set_heading;
  1185.                     'L' : set_level;
  1186.                     'T' : set_trim;
  1187.                 end;
  1188.       end;
  1189.     until ((ch in ['Q','q']) and (function_key=false));
  1190.   end; { pickupkeys }
  1191.  
  1192.  
  1193. {$F+}    (* force far call *)
  1194. procedure CleanUp;
  1195.   begin
  1196.     ExitProc := SaveExitProc;
  1197.     CloseGraph;
  1198.   end; { CleanUp }
  1199. {$F-}
  1200.  
  1201.  
  1202. procedure SetGraphics;
  1203.   begin
  1204.     { this may need modification if graphics do not conform to AT&T format }
  1205. (*****
  1206.     GraphDriver  := ATT400;     { use this for AT&T format }
  1207.     GraphMode    := ATT400Hi;   { 2 color 640 X 400  }
  1208. *****)
  1209.  
  1210.     GraphDriver  := detect;     { use this to autodetect graphics format }
  1211.  
  1212.     InitGraph( GraphDriver, GraphMode, '');
  1213.     ErrorCode    := GraphResult;
  1214.     if ErrorCode <> grOk then begin
  1215.       Writeln('Graphics error: ', GraphErrorMsg(ErrorCode));
  1216.       writeln('Program aborted...');
  1217.       halt(1);
  1218.     end;
  1219.   end; { SetGraphics }
  1220.  
  1221.  
  1222. Begin {Simulate}
  1223.   clrscr;
  1224.   SaveExitProc := ExitProc;
  1225.   ExitProc     := @CleanUp;
  1226.   SetGraphics;
  1227.   setviewport(0, 0, getmaxx, getmaxy, clipon);
  1228.   initialize_variables;
  1229.   set_level;
  1230.  
  1231.   repeat
  1232.     clearviewport;
  1233.     draw_circles;
  1234.     print_data;
  1235.     pickupkeys;
  1236.     moveto( (GetMaxX - 27 * 8) div 2, GetMaxY - 8 );
  1237.     OutText('Quit = Q : <cr> = Continue ' );
  1238.     read_character;
  1239.   until ch in ['q','Q'];
  1240.  
  1241. End {Simulate}.
  1242.  
  1243.  
  1244.       (***********************************************************
  1245.       This software is made available only to individuals and only
  1246.       for educational purposes. Any and all commercial use is
  1247.       stricly prohibited.
  1248.       ***********************************************************)
  1249.  
  1250.  
  1251.  
  1252.  
  1253.       (************************   END   **************************
  1254.       **                                                        **
  1255.       **                                                        **
  1256.       **                    Flight  Simulator                   **
  1257.       **                  Subsonic Jet Aircraft                 **
  1258.       **                      Version  4.26                     **
  1259.       **                                                        **
  1260.       **                                                        **
  1261.       ************************************************************
  1262.  
  1263.       ************************************************************
  1264.       *                                                          *
  1265.       *                                                          *
  1266.       *            Captain Larry Thomas Brewster, Ph.D.          *
  1267.       *                                                          *
  1268.       *                University of Missouri-Rolla              *
  1269.       *                Computer Science Department               *
  1270.       *                       Feb 26, 1990                       *
  1271.       *                                                          *
  1272.       *                                                          *
  1273.       ***********************************************************)