home *** CD-ROM | disk | FTP | other *** search
/ Black Art of 3D Game Programming / Black_Art_of_3D_Game_Programming.iso / source / msc / chap_9 / blazer.c < prev    next >
C/C++ Source or Header  |  1994-12-18  |  205KB  |  7,206 lines

  1.  
  2. // STARBLAZER.C - Version 1.0
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17.  
  18. // include all of our stuff
  19.  
  20. #include "black3.h"
  21. #include "black4.h"
  22. #include "black5.h"
  23. #include "black6.h"
  24. #include "black8.h"
  25. #include "black9.h"
  26.  
  27. // D E F I N E S /////////////////////////////////////////////////////////////
  28.  
  29. // digital sound system
  30.  
  31. #define BLZCLK_VOC      0       // engaging the cloaking device
  32. #define BLZEXP1_VOC     1       // standard explosion
  33. #define BLZEXP2_VOC     2       // the super nova
  34. #define BLZLAS_VOC      3       // laser torpedo sound
  35. #define BLZNRG_VOC      4       // energy up sound
  36. #define BLZSHLD_VOC     5       // shields engaging
  37. #define BLZTAC_VOC      6       // tactical heads up
  38. #define BLZSCN_VOC      7       // scanners turning on
  39. #define BLZMISS_VOC     8       // mission debriefing
  40.  
  41. #define BLZBIOS_VOC     9       // bios is ok
  42. #define BLZENTR_VOC     10      // entering game arena
  43. #define BLZABRT_VOC     11      // function aborted
  44. #define BLZSEL_VOC      12      // a selection was made
  45. #define BLZKEY_VOC      13      // a key has been pressed
  46. #define BLZDIAL_VOC     14      // the computer is dialing
  47.  
  48. #define BLZLOS_VOC      15      // the loser sound
  49. #define BLZWIN_VOC      16      // the loser sound
  50.  
  51.  
  52. #define NUM_SOUND_FX    17     // the number of sound fx loaded in
  53.  
  54. // music system
  55.  
  56. #define NUM_INTRO_SEQUENCES  11 // the number of elements in intro music score
  57. #define NUM_GAME_SEQUENCES   18 // the number of elements in game music score
  58.  
  59. // modem defines
  60.  
  61. // defines for briefing instructions
  62.  
  63. #define NUM_PAGES          12
  64. #define NUM_LINES_PAGE     17
  65.  
  66. // defines for the super nova explosion
  67.  
  68. #define NUM_CINDERS        20     // maximum number of cinders per explosion
  69.  
  70. #define CINDER_START_COLOR 48     // starting cinder color
  71. #define CINDER_END_COLOR   48+15  // ending cinder color
  72.  
  73. #define NUM_NOVAS          3      // maximum number of super novas in game
  74.  
  75. #define NOVA_ACTIVE        1      // states of the novas
  76. #define NOVA_INACTIVE      0
  77.  
  78. // heads up display defines
  79.  
  80. #define SCANNER_X             128  // position of scanner on screen
  81. #define SCANNER_Y             166
  82.  
  83. #define MAX_BLIPS             50   // maximum number of scanner blips
  84.  
  85. #define BLIP_ASTEROID         9    // colors dor scanner blips
  86. #define BLIP_PLAYER           10
  87. #define BLIP_REMOTE           12
  88. #define BLIP_ALIEN            13
  89.  
  90. #define RIGHT_HEADS_TEXT_X    240  // position of rightmost text for headsup
  91. #define RIGHT_HEADS_TEXT_Y    120
  92.                                    // position of leftmost text for headsup
  93. #define LEFT_HEADS_TEXT_X     0
  94. #define LEFT_HEADS_TEXT_Y     120
  95.  
  96. #define HEADS_CLOAK         1    // bitmap indices for various headsup elements
  97. #define HEADS_SCANNER       2
  98. #define HEADS_COMM          3
  99. #define HEADS_SHIPS         4
  100. #define HEADS_ENERGY        5
  101. #define HEADS_SHIELDS
  102.  
  103. #define HEADS_1             1
  104. #define HEADS_2             2
  105. #define HEADS_3             3
  106.  
  107. #define HEADS_GAUGE_1       1
  108.  
  109. // fuel cell defines
  110.  
  111. #define NUM_FUEL_CELLS      4   // number of fuel cells in game
  112. #define NUM_FUEL_FRAMES     3   // number of animation frames for fuel cells
  113.  
  114. #define FUEL_CELL_ACTIVE    1   // states of a fuel cell
  115. #define FUEL_CELL_ABSORBED  0
  116.  
  117. // alien defines
  118.                                 // number of alien animation frames
  119. #define NUM_ALIEN_FRAMES    4
  120. #define ALIEN_ODDS          50  // probabiliy of alien comming out
  121.  
  122. #define ALIEN_INACTIVE      0  // states of the alien
  123. #define ALIEN_RANDOM        1  // the three modes of intelligence
  124. #define ALIEN_CHASE_PLAYER  2
  125. #define ALIEN_CHASE_REMOTE  3
  126.  
  127. // worm hole defines
  128.  
  129. #define NUM_WORMHOLE_FRAMES 8     // number of wormhole animation frames
  130.  
  131. #define WORMHOLE_X          1250  // position of wormhole
  132. #define WORMHOLE_Y          1250
  133.  
  134. // starting position of the intro startup sequence
  135.  
  136. #define START_MESS_X        2
  137. #define START_MESS_Y        8
  138.  
  139. // general explosions
  140.  
  141. #define NUM_EXPLOSIONS        4  // number of explosions that can run at once
  142. #define NUM_EXPLOSION_FRAMES  6  // number frames in explosion
  143.  
  144. #define EXPLOSION_INACTIVE    0  // state of an inactive explosion
  145. #define EXPLOSION_ACTIVE      1  // state of a live explosion
  146.  
  147. // missile defines
  148.  
  149. #define GENERIC_MISSILE    0
  150.  
  151. #define PLAYER_MISSILE     1   // this missile was fired by the local player
  152. #define REMOTE_MISSILE     2   // this missile was fired by remote player
  153.  
  154. #define MISS_ACTIVE        1   // flags that a missile is alive
  155. #define MISS_INACTIVE      0   // flags that a missile is dead
  156. #define NUM_MISSILES       12  // number of total missiles allowed in world
  157.  
  158. // state of the game itself
  159.  
  160. #define GAME_SETUP                  0   // the game is in the setup mode
  161. #define GAME_LINKING                1   // the communications link is being established
  162. #define GAME_RUNNING                2   // the game is running
  163. #define GAME_PAUSED                 3   // the game is paused (not implemented)
  164. #define GAME_OVER                   4   // what do you think
  165.  
  166. // general object states
  167.  
  168. #define DEAD                        0   // these are general states for any
  169. #define ALIVE                       1   // object
  170. #define DYING                       2
  171.  
  172. // defines for setup selections
  173.  
  174. #define SETUP_PLAY_SOLO             0
  175. #define SETUP_MAKE_CONNECTION       1
  176. #define SETUP_WAIT_FOR_CONNECTION   2
  177. #define SETUP_SELECT_SHIP           3
  178. #define SETUP_SET_COMM_PORT         4
  179. #define SETUP_BRIEFING              5
  180. #define SETUP_EXIT                  6
  181.  
  182. #define NUM_SETUP                   7   // number of setup choices
  183.  
  184. // the coordinates of the setup display window
  185.  
  186. #define DISPLAY_X                   243 // position of the small setup display
  187. #define DISPLAY_Y                   68  // box
  188. #define DISPLAY_WIDTH               73  // size of window
  189. #define DISPLAY_HEIGHT              28
  190.  
  191. #define DISPLAY_IMG_SHIPS           0   // commands to the display function
  192. #define DISPLAY_IMG_PORTS           1   // indicating icons to display
  193.  
  194. // size of the "tech" font used in intro
  195.  
  196. #define TECH_FONT_WIDTH         4   // width of high tech font
  197. #define TECH_FONT_HEIGHT        7   // height of high tech font
  198. #define NUM_TECH_FONT           64  // number of characters in tech font
  199.  
  200. // asteroid defines
  201.  
  202. #define ASTEROID_SMALL          0   // different asteroid sizes
  203. #define ASTEROID_MEDIUM         1
  204. #define ASTEROID_LARGE          2
  205.  
  206. #define ASTEROID_INACTIVE       0   // asteroid states
  207. #define ASTEROID_ACTIVE         1
  208. #define ASTEROID_INOP           2
  209.  
  210. #define NUM_LARGE_ASTEROIDS     6   // max number of large asteroids in the game
  211. #define NUM_MEDIUM_ASTEROIDS    10  // max number of medium asteroids in game
  212. #define NUM_SMALL_ASTEROIDS     24  // max number of small asteroids in game
  213.  
  214. #define START_LARGE_ASTEROIDS   0   // starting index of large asteroids
  215. #define START_MEDIUM_ASTEROIDS  6   // starting index of medium asteroids
  216. #define START_SMALL_ASTEROIDS   16  // starting index of small asteroids
  217.  
  218. #define END_LARGE_ASTEROIDS     (0+6-1)    // ending indices
  219. #define END_MEDIUM_ASTEROIDS    (6+10-1)
  220. #define END_SMALL_ASTEROIDS     (16+24-1)
  221.  
  222. #define ASTEROID_LARGE_WIDTH    34  // size of large asteroids
  223. #define ASTEROID_LARGE_HEIGHT   28
  224.  
  225. #define ASTEROID_MEDIUM_WIDTH   16  // size of medium asteroids
  226. #define ASTEROID_MEDIUM_HEIGHT  14
  227.  
  228. #define ASTEROID_SMALL_WIDTH    8   // size of small asteroids
  229. #define ASTEROID_SMALL_HEIGHT   6
  230.  
  231. #define NUM_ASTEROID_FRAMES     8   // number of asteroid animation frames
  232.  
  233. #define NUM_ASTEROIDS  (6+10+24)    // total number of asteroids in universe
  234.  
  235. // defines for the star field
  236.  
  237. #define NUM_STARS                50   // number of stars in universe
  238.  
  239. #define STAR_PLANE_0             0    // far plane
  240. #define STAR_PLANE_1             1    // near plane
  241. #define STAR_PLANE_2             2
  242.  
  243. #define STAR_COLOR_0             8    // color of farthest star plane
  244. #define STAR_COLOR_1             7
  245. #define STAR_COLOR_2             15   // color of nearest star plane
  246.  
  247. // dimensions of the universe
  248.  
  249. #define UNIVERSE_WIDTH           2500
  250. #define UNIVERSE_HEIGHT          2500
  251. #define UNIVERSE_BORDER          160   // the thickness of the border around
  252.                                        // the universe
  253. // defines for ships
  254.  
  255. #define GRYFON_SHIP             0
  256. #define RAPTOR_SHIP             1
  257.  
  258. #define SHIP_WIDTH              22     // size of both ships
  259. #define SHIP_HEIGHT             18
  260.  
  261.  
  262. // shield defines
  263.  
  264. #define PLAYERS_SHIELD_REG      240   // color registers of players shield
  265. #define REMOTES_SHIELD_REG      241   // color and remotes shield color
  266.  
  267. // engine defines
  268.  
  269. #define PLAYERS_ENGINE_REG      242  // color registers for engine flicker
  270. #define REMOTES_ENGINE_REG      243
  271.  
  272. // introduction panel colors
  273.  
  274. #define END_PANEL_REG           41   // the color register range for the
  275. #define START_PANEL_REG         32   // scrolling red lights on setup screen
  276.  
  277. // general identifiers for the player and remote
  278.  
  279. #define THE_PLAYER             0
  280. #define THE_REMOTE             1
  281.  
  282. #define WINNER_NONE            0
  283. #define WINNER_PLAYER          1
  284. #define WINNER_REMOTE          2
  285.  
  286.  
  287. // remote keyboard events
  288.  
  289. #define REMOTE_RIGHT           1   // each one of these bits is set or reset
  290. #define REMOTE_LEFT            2   // in a single byte and sent to the remote
  291. #define REMOTE_THRUST          4   // to indicate what the local player did
  292. #define REMOTE_SHIELDS         8
  293. #define REMOTE_CLOAK           16
  294. #define REMOTE_FIRE            32
  295. #define REMOTE_ESC             64
  296.  
  297. // S T R U C T U R E S ///////////////////////////////////////////////////////
  298.  
  299. // this is the structure for the asteroids
  300.  
  301. typedef struct asteroid_typ
  302.         {
  303.         int xv;                 // x velocity of asteroid
  304.         int yv;                 // y velocity of asteroid
  305.         int x,y;                // universe coordinates
  306.  
  307.         int type;               // type of asteroid, big, medium, small
  308.         sprite rock;            // the asteroid sprite
  309.  
  310.         } asteroid, *asteroid_ptr;
  311.  
  312. // this is the structure for the stars
  313.  
  314. typedef struct star_typ
  315.         {
  316.         int x,y;                   // position of star
  317.         int color;                 // color of star
  318.         int plane;                 // plane that star is in
  319.         int back_color;            // the color of the pixel under the star
  320.  
  321.         } star, *star_ptr;
  322.  
  323. // this is the structure used for weapons and explosion particles
  324.  
  325. typedef struct particle_type
  326.         {
  327.         int x,y;                    // universe position
  328.         int sx,sy;                  // screen coordinates
  329.         int xv,yv;                  // velocity
  330.         int type;                   // type of particle
  331.         int state;                  // state of particle
  332.         int counter;                // general counter
  333.         int threshold;              // threshold for counter
  334.         int color;                  // color of particle
  335.         int back_color;             // the color of the pixel under the particle
  336.         int visible;                // helps speed clipping
  337.         int lifetime;               // the liftime of the particle in frames
  338.  
  339.         } particle, *particle_ptr;
  340.  
  341. // this is the structure for a super nova explosion
  342.  
  343. typedef struct nova_typ
  344.         {
  345.         int state;                      // state of super nova explosion
  346.         int x,y;                        // position of super nova explosion
  347.         int lifetime;                   // the lifetime of the super nova
  348.  
  349.         particle cinders[NUM_CINDERS]; // particles of the explosion
  350.  
  351.         } nova, *nova_ptr;
  352.  
  353. // this is the structure for all simple creatures
  354.  
  355. typedef struct monster_typ
  356.         {
  357.  
  358.         int x,y;        // position in universe coordinates
  359.         int xv,yv;      // velocity of monster
  360.         int state;      // state fo monster
  361.         int type;       // type of monster
  362.  
  363.         sprite body;    // the body sprite for monster
  364.  
  365.         } monster, *monster_ptr;
  366.  
  367. // this is a scanner object
  368.  
  369. typedef struct blip_typ
  370.         {
  371.         int x,y;    // position of blip
  372.         int color;  // color of blip i.e. type of scanner object
  373.  
  374.         } blip, *blip_ptr;
  375.  
  376. // P R O T O T Y P E S //////////////////////////////////////////////////////
  377.  
  378. void Init_Stars(void);
  379.  
  380. void Move_Stars(void);
  381.  
  382. void Draw_Stars(void);
  383.  
  384. void Erase_Stars(void);
  385.  
  386. void Under_Stars(void);
  387.  
  388. void Init_Asteroids(int small, int medium, int large);
  389.  
  390. void Start_Asteroid(int x,int y,int type);
  391.  
  392. void Erase_Asteroids(void);
  393.  
  394. void Draw_Asteroids(void);
  395.  
  396. void Under_Asteroids(void);
  397.  
  398. void Move_Asteroids(void);
  399.  
  400. void Font_Engine_1(int x,int y,
  401.                    int font,int color,
  402.                    char *string,unsigned char far *destination);
  403.  
  404. void Clear_Display(int color);
  405.  
  406. void Intro_Title(void);
  407.  
  408. void Intro_Controls(void);
  409.  
  410. void Load_Icons(void);
  411.  
  412. void Load_Ships(void);
  413.  
  414. void Do_Starburst(void);
  415.  
  416. int Display_Select(int current);
  417.  
  418. void Copy_Frames(sprite_ptr dest, sprite_ptr source);
  419.  
  420. void Shield_Control(int ship,int on);
  421.  
  422. void Reset_System(void);
  423.  
  424. void Start_Players_Death(void);
  425.  
  426. void Reset_Player(void);
  427.  
  428. void Reset_Remote(void);
  429.  
  430. void Start_Remotes_Death(void);
  431.  
  432. void Panel_FX(void);
  433.  
  434. void Erase_Missiles(void);
  435.  
  436. void Under_Missiles(void);
  437.  
  438. void Draw_Missiles(void);
  439.  
  440. void Init_Missiles(void);
  441.  
  442. void Move_Missiles(void);
  443.  
  444. int Start_Missile(int x,int y,int xv,int yv, int color,int type);
  445.  
  446. void Start_Explosion(int x,int y,int speed);
  447.  
  448. void Under_Explosions(void);
  449.  
  450. void Erase_Explosions(void);
  451.  
  452. void Draw_Explosions(void);
  453.  
  454. void Animate_Explosions(void);
  455.  
  456. void Init_Explosions(void);
  457.  
  458. void Tech_Print(int x,int y,char *string,unsigned char far *destination);
  459.  
  460. void Load_Wormhole(void);
  461.  
  462. void Init_Wormhole(void);
  463.  
  464. void Under_Wormhole(void);
  465.  
  466. void Erase_Wormhole(void);
  467.  
  468. void Draw_Wormhole(void);
  469.  
  470. void Animate_Wormhole(void);
  471.  
  472. void Load_Alien(void);
  473.  
  474. void Init_Alien(void);
  475.  
  476. void Alien_Control(void);
  477.  
  478. void Under_Alien(void);
  479.  
  480. void Erase_Alien(void);
  481.  
  482. void Draw_alien(void);
  483.  
  484. void Move_Alien(void);
  485.  
  486. void Load_Fuel_Cells(void);
  487.  
  488. void Init_Fuel_Cells(void);
  489.  
  490. void Under_Fuel_Cells(void);
  491.  
  492. void Erase_Fuel_Cells(void);
  493.  
  494. void Draw_Fuel_Cells(void);
  495.  
  496. void Animate_Fuel_Cells(void);
  497.  
  498. void Init_Scanner(void);
  499.  
  500. void Erase_Scanner(void);
  501.  
  502. void Draw_Scanner(void);
  503.  
  504. void Init_Novas(void);
  505.  
  506. void Erase_Novas(void);
  507.  
  508. void Under_Novas(void);
  509.  
  510. void Draw_Novas(void);
  511.  
  512. void Move_Novas(void);
  513.  
  514. void Start_Nova(int x,int y);
  515.  
  516. void Music_Init(void);
  517.  
  518. void Music_Close(void);
  519.  
  520. void Digital_FX_Init(void);
  521.  
  522. void Digital_FX_Close(void);
  523.  
  524. int Digital_FX_Play(int the_effect, int priority);
  525.  
  526. void Draw_Blips(void);
  527.  
  528. void Under_Blips(void);
  529.  
  530. void Erase_Blips(void);
  531.  
  532. // G L O B A L S  ////////////////////////////////////////////////////////////
  533.  
  534. pcx_picture image_pcx,  // general PCX image used to load background and imagery
  535.             image_controls;  // this holds the controls screen
  536.  
  537.  
  538. RGB_color color_1,color_2; // used for temporaries during color rotation
  539.  
  540. RGB_palette game_palette;  // this will hold the startup system palette
  541.                            // so we can restore it after screen FX
  542.  
  543. sprite button_1,        // the setup buttons
  544.        button_2,
  545.        button_3,
  546.        displays,        // the display bitmaps
  547.        starburst,       // the startburt sprite
  548.        gryfon_r,        // this holds a generic gryfon ship with remote colors
  549.        raptor_r,        // this holds a generic raptor ship with remote colors
  550.        gryfon_l,        // this holds a generic gryfon ship with local colors
  551.        raptor_l,        // this holds a generic raptor ship with local colors
  552.        players_ship,    // this is the players ship
  553.        remotes_ship,    // this is the remotes ship
  554.        wormhole,        // a stationary worm hole in the game
  555.        fuel_cells[NUM_FUEL_CELLS], // the stationary fuel cells in the game
  556.  
  557.        heads_text,      // heads up display sprites
  558.        heads_numbers,
  559.        heads_gauge;
  560.  
  561.  
  562. monster alien;                     // the alien saucer that comes out of the
  563.                                    // wormhole
  564.  
  565. sprite explosions[NUM_EXPLOSIONS]; // the explosions in the game
  566.  
  567. nova novas[NUM_NOVAS];             // the super nova explosions!
  568.  
  569. int active_explosions=0;           // number of active explosions
  570.  
  571. asteroid asteroids[NUM_ASTEROIDS]; // the asteroid fields
  572.  
  573. star stars[NUM_STARS];             // the star fields
  574.  
  575. particle missiles[NUM_MISSILES];   // all the projectiles
  576.  
  577. bitmap tech_font[NUM_TECH_FONT];   // the tech font bitmaps
  578.  
  579. int game_state = GAME_SETUP;  // the overall state of the game
  580.  
  581. int comm_port         = 0,    // currently selected comm port
  582.     players_ship_type = 0,    // currently selected local ship type
  583.     remotes_ship_type = 1;    // the remotes ships type
  584.  
  585.  
  586. int comm_port_to_address[2] = {COM_1,COM_2}; // converts the selected com port
  587.                                             // to an address
  588.  
  589. int master            = 1,    // the the player dials up a player
  590.     slave             = 0,    // then he is master else he is slave
  591.     linked            = 0,    // state of the modem communications system
  592.     winner = WINNER_NONE;     // the winner of the game
  593.  
  594. // the start up arrays used to differentiate the player and remote
  595.  
  596. // master is index 1, slave is index 0
  597.  
  598. int game_start_x[] = {1200,1300};
  599. int game_start_y[] = {1200,1200};
  600.  
  601. // the variables for the player
  602.  
  603. int players_last_x      = 0,    // the last postiion of player
  604.     players_last_y      = 0,
  605.     players_x           = 0,    // current players position
  606.     players_y           = 0,
  607.     players_dx          = 0,       // players position deltas since last frame
  608.     players_dy          = 0,
  609.     players_xv          = 0,       // velocity of ship
  610.     players_yv          = 0,
  611.     players_engine      = 0,       // state of engines
  612.     players_stability   = 8,       // how long it takes for gravity
  613.     players_flame_count = 0,       // used for engine flicker
  614.     players_flame_time  = 1,
  615.     players_gravity     = 0,       // current gravitron count
  616.     players_shields     = 0,       // state of the shields
  617.     players_shield_time = 0,       // how long sheilds have been on
  618.     players_cloak       = -1,      // state of the shields  -1 off 1 on
  619.     players_heads       = -1,      // state of heads up display
  620.     players_comm        = -1,      // state of comm link
  621.     players_scanner     = -1,      // space scanner
  622.     players_num_ships   = 3,       // number of players ship
  623.     players_shield_strength = 22000, // the amount of energy players shields have
  624.     players_energy          = 22000, // the amount of ship energy
  625.     players_score           = 0,     // the score of the player
  626.     players_active_missiles = 0,     // the number of missiles the player has fired
  627.     players_state           = ALIVE, // satte of player
  628.     players_death_count     = 0;     // how long death sequence will last
  629.  
  630.  
  631. int debounce_hud        = 0,       // these are used to debounce the players
  632.     debounce_scan       = 0,       // inputs one some keys
  633.     debounce_cloak      = 0,
  634.     debounce_thrust     = 0,
  635.     debounce_fire       = 0,
  636.     debounce_shields    = 0;
  637.  
  638. int refresh_heads = 0,              // used to track when hud needs refreshing
  639.     under_players_blip,             // these hold the pixels under the scanner
  640.     under_remotes_blip;             // blip image of the player and remote
  641.  
  642. // remote variables
  643.  
  644. int remotes_last_x      = 0,    // the last postiion of player
  645.     remotes_last_y      = 0,
  646.     remotes_x           = 0,    // current remotes position
  647.     remotes_y           = 0,
  648.     remotes_dx          = 0,       // remotes position deltas since last frame
  649.     remotes_dy          = 0,
  650.     remotes_xv          = 0,       // velocity of ship
  651.     remotes_yv          = 0,
  652.     remotes_engine      = 0,       // state of engines
  653.     remotes_stability   = 8,       // how long it takes for gravity
  654.     remotes_flame_count = 0,       // used for engine flicker
  655.     remotes_flame_time  = 1,
  656.     remotes_gravity     = 0,       // current gravitron count
  657.     remotes_shields     = 0,       // state of the shields
  658.     remotes_shield_time = 0,       // how long sheilds have been on
  659.     remotes_cloak       = -1,      // state of the shields  -1 off 1 on
  660.     remotes_heads       = -1,      // state of heads up display
  661.     remotes_comm        = -1,      // comm link
  662.     remotes_scanner     = -1,      // space scanner
  663.     remotes_num_ships   = 3,       // number of remotes ship
  664.     remotes_shield_strength = 22000, // the amount of energy remotes shields have
  665.     remotes_energy          = 22000, // the amount of ship energy
  666.     remotes_score           = 0,     // the remotes score
  667.     remotes_active_missiles = 0,     // the number of missiles the remote has fired
  668.     remotes_state           = ALIVE, // state of remote
  669.     remotes_death_count     = 0;     // how long death sequence will last
  670.  
  671. // unit motion look up tables
  672.  
  673. int motion_dx[16] = {0,1,2,2,3,2,2,1,0,-1,-2,-2,-3,-2,-2,-1};
  674. int motion_dy[16] = {-3,-2,-2,-1,0,1,2,2,3,2,2,1,0,-1,-2,-2};
  675.  
  676. // musical sequence information
  677.  
  678. int music_enabled   = 0,      // flags that enable music and sound FX
  679.     digital_enabled = 0;
  680.  
  681. int digital_FX_priority = 10; // the priority tracker of the current effect
  682.  
  683. int intro_sequence[] = {0,2,3,4,3,4,2,3,4,3,3};
  684. int intro_seq_index  = 0;
  685.  
  686. int game_sequence[] = {0+5,1+5,4+5,5+5,4+5,2+5,1+5,3+5,1+5,5+5,5+5,4+5,1+5,
  687.                        2+5,3+5,2+5,4+5,4+5};
  688.  
  689. int game_seq_index  = 0;
  690.  
  691. music song;    // the music structure
  692.  
  693. // sound fx stuff
  694.  
  695. sound digital_FX[NUM_SOUND_FX];
  696.  
  697. // these colors are used for the shields on the ships
  698.  
  699. RGB_color  primary_red   = {63,0,0},    // pure red
  700.            primary_blue  = {0,0,63},    // pure blue
  701.            primary_green = {0,63,0},    // pure green
  702.            primary_black = {0,0,0},     // pure black
  703.            primary_white = {63,63,63},  // pure white
  704.  
  705.            remotes_shield_color={0,0,0}, // the current color of the remotes shield
  706.            players_shield_color={0,0,0}, // the current color of the players shields
  707.  
  708.            players_engine_color={0,0,0}, // the color or the players engine
  709.            remotes_engine_color={0,0,0}; // the color or the remotes engine
  710.  
  711. // the instruction pages
  712.  
  713. char *instructions[]={
  714.  
  715.                "STARBLAZER MISSION BRIEFING,       ",
  716.                "STAR DATE: 2595.001                ",
  717.                "                                   ",
  718.                "LONG RANGE SCANS HAVE DETECTED THE ",
  719.                "PRESENCE OF AN UNKNOWN VESSEL IN   ",
  720.                "THE TALLEON ASTEROID BELT. YOUR    ",
  721.                "MISSION IS SIMPLE: SEEK OUT THE    ",
  722.                "AGGRESSOR AND DESTROY IT.          ",
  723.                "                                   ",
  724.                "THE ASTEROID BELT IS FAIRLY SPARSE ",
  725.                "AND POSES MINIMAL THREAT TO YOUR   ",
  726.                "SHIP, BUT THE ASTEROIDS ARE DEADLY ",
  727.                "IF THEY BREACH YOUR SHIPS HULL.    ",
  728.                "                                   ",
  729.                "                                   ",
  730.                "                                   ",
  731.                "               1                   ",
  732.                "THE ASTEROID BELT EXISTS AT        ",
  733.                "COORDINATES (0.0) TO (2500.2500),  ",
  734.                "(USING THE STANDARD CENTRAL        ",
  735.                "NAVIGATION MULTIVARIATE VECTOR     ",
  736.                "POSITIONING SYSTEM). IF YOU TRY TO ",
  737.                "GO BEYOND THESE BOUNDS YOUR SHIP   ",
  738.                "WILL AUTOMATICALLY HYPERWARP TO    ",
  739.                "THE OPPOSITE EDGE OF THE SECTOR.   ",
  740.                "THUS,YOU CAN NOT LEAVE UNTIL YOU   ",
  741.                "HAVE COMPLETED YOUR MISSION!       ",
  742.                "                                   ",
  743.                "THERE HAVE ALSO BEEN REPORTS OF A  ",
  744.                "STABLE WORMHOLE IN THIS SECTOR. THE",
  745.                "WORMHOLE SEEMS TO BE A SINGLE POLE ",
  746.                "TRANSVERSE DISTURBANCE AND EMITS NO",
  747.                "GRAVITRONS.                        ",
  748.                "               2                   ",
  749.                "BUT REPORTS DO DETIAL MATTER AND   ",
  750.                "ENERGY EMMISIONS FROM THE WORMHOLE,",
  751.                "SO STAY CLEAR OF IT! IT IS LOCATED ",
  752.                "AT COORDINATES (1200.1200).        ",
  753.                "                                   ",
  754.                "FINALLY, A SMALL SHIP HAS BEEN     ",
  755.                "DETECTED,HOWEVER,IT SEEMS TO HAVE  ",
  756.                "NO HOSTILE INTENTIONS. MOREOVER,IT ",
  757.                "APPEARS THAT IT HAS A SYMETRICAL   ",
  758.                "SUB-SPACE FIELD SHIELDING SYSTEM   ",
  759.                "WHICH OUR BEST SCIENTISTS STILL DO ",
  760.                "NOT FULLY UNDERSTAND. NEEDLESS TO  ",
  761.                "SAY, YOUR WEAPONS ARE USELESS      ",
  762.                "AGAINST IT...                      ",
  763.                "                                   ",
  764.                "                                   ",
  765.                "               3                   ",
  766.                "SPECIFICATIONS                     ",
  767.                "                                   ",
  768.                "YOUR SHIP IS EQUIPPED WITH ALL OF  ",
  769.                "THE LATEST FEATURES INCLUDING:     ",
  770.                "HEADS UP DISPLAYS, SECTOR SCANNER, ",
  771.                "TWIN TACHION DRIVE, AUTOFIRE       ",
  772.                "PARTICLE CANNONS, PLASMA-FIELD-    ",
  773.                "EFFECT SUB-SPACE SHIELDS,AND A     ",
  774.                "CLOAKING DEVICE BUILT IN THE       ",
  775.                "ANTARUS SYSTEM SPECIFICALLY FOR    ",
  776.                "YOUR SHIP.                         ",
  777.                "                                   ",
  778.                "FINALLY, YOUR SHIP HAS THE NEW     ",
  779.                "PROTOTYPE SHAPE SHIFTING PLASMA    ",
  780.                "ENERGY HULL SYSTEM.                ",
  781.                "                                   ",
  782.                "               4                   ",
  783.                "ENTERING INTO COMBAT               ",
  784.                "                                   ",
  785.                "TO PLAY THE GAME YOU CAN EITHER    ",
  786.                "PLAY IN THE SOLO MODE FOR PRACTICE ",
  787.                "OR MODEM-2-MODEM. TO PLAY SOLO     ",
  788.                "MODE,SELECT THE SHIP YOU LIKE BY   ",
  789.                "USING THE SELECT SHIP OPTION ON    ",
  790.                "THE MAIN MENU. ONCE YOU HAVE       ",
  791.                "SELECTED THE SHIP OF YOUR CHOICE,  ",
  792.                "USE THE PLAY SOLO OPTION AND YOU   ",
  793.                "WILL BE WARPED TO THE TALLEON      ",
  794.                "ASTEROID BELT FOR A PRACTICE       ",
  795.                "SESSION.                           ",
  796.                "                                   ",
  797.                "                                   ",
  798.                "                                   ",
  799.                "               5                   ",
  800.                "TO PLAY MODEM-2-MODEM, YOU CAN     ",
  801.                "EITHER DIAL UP A COMPETITOR OR WAIT",
  802.                "FOR A COMPETITOR TO CALL. HOWEVER, ",
  803.                "BEFORE YOU CAN DO THIS, YOU MUST   ",
  804.                "SELECT WHICH COMMUNICATIONS PORT   ",
  805.                "YOUR MODEM IS ON. THIS CAN BE DONE ",
  806.                "WITH THE SELECT COMM PORT MENU     ",
  807.                "OPTION.                            ",
  808.                "                                   ",
  809.                "ONCE YOU HAVE SELECTED THE COMM    ",
  810.                "PORT THEN EITHER DIAL UP A         ",
  811.                "COMPETITOR WITH THE MAKE CONNECTION",
  812.                "MENU ITEM OR WAIT FOR A CALL VIA   ",
  813.                "THE WAIT FOR CONNECTION MENU ITEM. ",
  814.                "ONCE A CONNECTION HAS BEEN MADE YOU",
  815.                "WILL BE WARPED INTO BATTLE.        ",
  816.                "               6                   ",
  817.                "CONTROLING THE SHIP                ",
  818.                "                                   ",
  819.                "NAVIGATION:                        ",
  820.                "                                   ",
  821.                "TO NAVIAGATE THE SHIP USE THE RIGHT",
  822.                "AND LEFT ARROWS TO TURN. TO THRUST ",
  823.                "FOWARD USE THE UP ARROW.           ",
  824.                "                                   ",
  825.                "SHIELDS:                           ",
  826.                "                                   ",
  827.                "TO ENGAGE YOUR SHIELDS PRESS THE   ",
  828.                "<ALT> KEY. THEY WILL LAST FOR      ",
  829.                "APPROXIMATELY 5 SECS BEFORE        ",
  830.                "SHUTTING DOWN.                     ",
  831.                "                                   ",
  832.                "                                   ",
  833.                "               7                   ",
  834.                "CLOAKING DEVICE:                   ",
  835.                "                                   ",
  836.                "THE CLOAKING DEVICE CAN BE TOGGLED ",
  837.                "BY PRESSING THE <C> KEY. CLOAKING  ",
  838.                "EXHIBITS HIGH POWER CONSUMPTION AND",
  839.                "YOUR SHIELDS ARE USELESS WHEN      ",
  840.                "CLOAKED.                           ",
  841.                "                                   ",
  842.                "HEADS UP DISPLAY:                  ",
  843.                "                                   ",
  844.                "THE HEADS UP DISPLAY CAN BE TOGGLED",
  845.                "WITH THE <H> KEY. IT DISPLAYS      ",
  846.                "PERTAINENT TACTICAL INFORMATION IN ",
  847.                "REAL-TIME.                         ",
  848.                "                                   ",
  849.                "                                   ",
  850.                "               8                   ",
  851.                "LONG RANGE SCANNERS:               ",
  852.                "                                   ",
  853.                "YOUR SHIP IS EQUIPPED WITH A LONG  ",
  854.                "RANGE SECTOR SCAN THAT WILL DISPLAY",
  855.                "ALL OBJECTS IN THE SECTOR. YOUR    ",
  856.                "SHIP IS MARKED GREEN, THE ENEMY IS ",
  857.                "MARKED RED. ALL OTHER OBJECTS ARE  ",
  858.                "BLUE. ENGAGE AND DISENGAGE THE     ",
  859.                "SCANNER BY PRESSING THE <S> KEY.   ",
  860.                "                                   ",
  861.                "WEAPONS:                           ",
  862.                "                                   ",
  863.                "TO FIRE YOUR CANNONS PRESS THE     ",
  864.                "<SPACE> KEY. THEY SUPPORT THE ATF  ",
  865.                "OPTION(ALL SHIPS BUILT AFTER       ",
  866.                "2491.300 SUPPORT RAPID FIRE).      ",
  867.                "               9                   ",
  868.                "EXITING THE GAME:                  ",
  869.                "                                   ",
  870.                "THE GAME CAN BE EXITED BY PRESSING ",
  871.                "<ESC> AT ANY TIME. IF THERE IS A   ",
  872.                "CONNECTIONM IT WILL BE TERMINATED. ",
  873.                "AFTER EXITING THE GAME, YOU WILL BE",
  874.                "SENT BACK TO THE MAIN MENU SYSTEM. ",
  875.                "                                   ",
  876.                "WARNINGS:                          ",
  877.                "                                   ",
  878.                "YOUR SHIP CONSUMES A GREAT DEAL OF ",
  879.                "POWER SINCE IT IS A FIGHTER. YOU   ",
  880.                "CAN MINIMIZE THIS POWER CONSUMPTION",
  881.                "BY USING YOUR WEAPONS,THRUSTER,AND ",
  882.                "CLOAKING DEVICE SPARINGLY.         ",
  883.                "                                   ",
  884.                "               10                  ",
  885.                "YOUR SHIELDS OPERATE BY A FUSION   ",
  886.                "REACTION OF TRI-RUBIDIUM, THUS ONCE",
  887.                "YOUR SHIELD STRENGTH IS DEPLETED,  ",
  888.                "YOUR SHIELDS ARE INOPERABLE!       ",
  889.                "                                   ",
  890.                "THE ORIGINAL REPORTS OF THE SECTOR ",
  891.                "NOTE LARGE ENERGY FLUX SOURCES     ",
  892.                "FLOATING AROUND FROM TIME TO TIME. ",
  893.                "IT MAY BE POSSIBLE TO EXTRACT THE  ",
  894.                "ENERGY FROM THESE ENERGY PODS.     ",
  895.                "                                   ",
  896.                "                                   ",
  897.                "                                   ",
  898.                "                                   ",
  899.                "                                   ",
  900.                "                                   ",
  901.                "               11                  ",
  902.                "TO HELP YOUR SHIP FACILITATE THIS, ",
  903.                "AN EXTERNAL ENERGION ACCEPTOR      ",
  904.                "MATRIX HAS BEEN FITTED TO THE HULL ",
  905.                "OF YOUR SHIP. YOU MAY BE ABLE TO   ",
  906.                "ABSORB THE ENERGY OF THE PODS BY   ",
  907.                "COMING IN CONTACT WITH THEM, BUT   ",
  908.                "THIS IS THEORETICAL AND YOU DO SO  ",
  909.                "AT YOUR OWN RISK.                  ",
  910.                "                                   ",
  911.                "GOOD HUNTING                       ",
  912.                "MAY THE WIND BE AT YOUR BACK...    ",
  913.                "                                   ",
  914.                "                                   ",
  915.                "                                   ",
  916.                "                                   ",
  917.                "                                   ",
  918.                "          END BREIFING             "};
  919.  
  920. // F U N C T I O N S ////////////////////////////////////////////////////////
  921.  
  922. int Get_Line(char *buffer)
  923. {
  924. // this function implements a crude line editor, it's used to input strings
  925. // from keyboard
  926.  
  927. int index=0,
  928.     ch;
  929.  
  930. // get the input string
  931.  
  932. while(1)
  933.      {
  934.  
  935.      // has user hiy a key?
  936.  
  937.      if (kbhit())
  938.         {
  939.         // make a sound
  940.  
  941.         Digital_FX_Play(BLZKEY_VOC,2);
  942.  
  943.         // get the key
  944.  
  945.         ch = getch();
  946.  
  947.         // test for a numeric character
  948.  
  949.         if (ch>='0' && ch<='9')
  950.            {
  951.  
  952.            buffer[index]   = ch;
  953.            buffer[index+1] = 0;
  954.  
  955.            Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2+8,0,0,
  956.                          buffer,
  957.                          video_buffer);
  958.  
  959.            // test if end of line reached
  960.  
  961.            if (++index==12)
  962.               index=11;
  963.  
  964.            } // end if numeric
  965.         else
  966.         if (ch==13)  // test for enter
  967.            {
  968.            // user is done, so exit
  969.  
  970.            // null terminate
  971.  
  972.            buffer[index] = 0;
  973.  
  974.            return(1);
  975.  
  976.            } // end if carriage return
  977.         else
  978.         if (ch==8 || ch==127) // back space or delete
  979.            {
  980.            if (--index <0)
  981.               index=0;
  982.  
  983.            buffer[index]  =' ';
  984.            buffer[index+1]=0;
  985.  
  986.            Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2+8,0,0,
  987.                          buffer,
  988.                          video_buffer);
  989.  
  990.            buffer[index]=0;
  991.  
  992.            // erase the character
  993.  
  994.            } // end if backspace
  995.         else
  996.         if (ch==27)
  997.            return(0);
  998.  
  999.         } // end if kbhit
  1000.  
  1001.      } // end while
  1002.  
  1003. } // end Get_Line
  1004.  
  1005. //////////////////////////////////////////////////////////////////////////////
  1006.  
  1007. void Init_Novas(void)
  1008. {
  1009. // this function initializes all the super novas
  1010.  
  1011. int index_n, // looping variables
  1012.     index_c;
  1013.  
  1014. // process each nova
  1015.  
  1016. for (index_n=0; index_n<NUM_NOVAS; index_n++)
  1017.     {
  1018.  
  1019.     // set all novas to inactive
  1020.  
  1021.     novas[index_n].state    = NOVA_INACTIVE;
  1022.     novas[index_n].lifetime = 0;
  1023.  
  1024.     // intialize each cinder
  1025.  
  1026.     for (index_c=0; index_c<NUM_CINDERS; index_c++)
  1027.         {
  1028.         // clear out all fields
  1029.  
  1030.         novas[index_n].cinders[index_c].x = 0;
  1031.         novas[index_n].cinders[index_c].y = 0;
  1032.  
  1033.         novas[index_n].cinders[index_c].xv = 0;
  1034.         novas[index_n].cinders[index_c].yv = 0;
  1035.  
  1036.         novas[index_n].cinders[index_c].sx = 0;
  1037.         novas[index_n].cinders[index_c].sy = 0;
  1038.  
  1039.         novas[index_n].cinders[index_c].color = 0;
  1040.         novas[index_n].cinders[index_c].back_color = 0;
  1041.  
  1042.         // set timing fields
  1043.  
  1044.         novas[index_n].cinders[index_c].lifetime = 0;
  1045.  
  1046.         novas[index_n].cinders[index_c].counter   = 0;
  1047.         novas[index_n].cinders[index_c].threshold = 0;
  1048.  
  1049.         } // end for index
  1050.  
  1051.     } // end for index_n
  1052.  
  1053. } // end Init_Novas
  1054.  
  1055. /////////////////////////////////////////////////////////////////////////////
  1056.  
  1057. void Erase_Novas(void)
  1058. {
  1059. // this function replaces the what was under the novas
  1060.  
  1061. int index_n, // looping variables
  1062.     index_c;
  1063.  
  1064. particle_ptr bits;  // used as a high speed alias into cinders array
  1065.  
  1066. // process each nova
  1067.  
  1068. for (index_n=0; index_n<NUM_NOVAS; index_n++)
  1069.     {
  1070.  
  1071.     // is this nova active ?
  1072.  
  1073.     if (novas[index_n].state==NOVA_ACTIVE)
  1074.        {
  1075.  
  1076.        // alias a pointer to cinder array for speed
  1077.  
  1078.        bits = (particle_ptr)novas[index_n].cinders;
  1079.  
  1080.        // process each cinder
  1081.  
  1082.        for (index_c=0; index_c<NUM_CINDERS; index_c++)
  1083.            {
  1084.  
  1085.            // is this cinder visible?
  1086.  
  1087.            if (bits[index_c].visible)
  1088.               Write_Pixel_DB(bits[index_c].sx,bits[index_c].sy,
  1089.                              bits[index_c].back_color);
  1090.  
  1091.            } // end for index_c
  1092.  
  1093.        } // end if nova active
  1094.  
  1095.     } // end for index_n
  1096.  
  1097. } // end Erase_Novas
  1098.  
  1099. /////////////////////////////////////////////////////////////////////////////
  1100.  
  1101. void Under_Novas(void)
  1102. {
  1103.  
  1104. // this function scans whats under a nova
  1105.  
  1106. int index_n, // looping variables
  1107.     index_c,
  1108.     px_window,   // the starting postion of the players window
  1109.     py_window,
  1110.     cx,cy;       // local aliases for speed
  1111.  
  1112. particle_ptr bits;  // used as a high speed alias into cinders array
  1113.  
  1114. // compute starting position of players window so screen mapping can be done
  1115.  
  1116. px_window = players_x - 160+11;
  1117. py_window = players_y - 100+9;
  1118.  
  1119. // process each nova
  1120.  
  1121. for (index_n=0; index_n<NUM_NOVAS; index_n++)
  1122.     {
  1123.  
  1124.     // is this nova active ?
  1125.  
  1126.     if (novas[index_n].state==NOVA_ACTIVE)
  1127.        {
  1128.  
  1129.        // alias a pointer to cinder array for speed
  1130.  
  1131.        bits = (particle_ptr)novas[index_n].cinders;
  1132.  
  1133.        // process each cinder
  1134.  
  1135.        for (index_c=0; index_c<NUM_CINDERS; index_c++)
  1136.            {
  1137.  
  1138.            cx=bits[index_c].sx = (bits[index_c].x - px_window);
  1139.            cy=bits[index_c].sy = (bits[index_c].y - py_window);
  1140.  
  1141.            // test if cinder is visible on screen?
  1142.  
  1143.            if (cx>=320 || cx <0 || cy>=200  || cy<0)
  1144.               {
  1145.  
  1146.               // this cindere is invisible and has been clipped
  1147.  
  1148.               bits[index_c].visible = 0;
  1149.  
  1150.               // process next cinder
  1151.  
  1152.               continue;
  1153.  
  1154.               } // end visibility test
  1155.  
  1156.            // scan under cinder
  1157.  
  1158.            bits[index_c].back_color = Read_Pixel_DB(cx,cy);
  1159.  
  1160.            // set visibility flag
  1161.  
  1162.            bits[index_c].visible = 1;
  1163.  
  1164.            } // end for index_c
  1165.  
  1166.        } // end if nova active
  1167.  
  1168.     } // end for index_n
  1169.  
  1170. } // end Under_Novas
  1171.  
  1172. /////////////////////////////////////////////////////////////////////////////
  1173.  
  1174. void Draw_Novas(void)
  1175. {
  1176.  
  1177. // this function draws the novas
  1178.  
  1179. int index_n, // looping variables
  1180.     index_c;
  1181.  
  1182. particle_ptr bits;  // used as a high speed alias into cinders array
  1183.  
  1184. // process each nova
  1185.  
  1186. for (index_n=0; index_n<NUM_NOVAS; index_n++)
  1187.     {
  1188.  
  1189.     // is this nova active ?
  1190.  
  1191.     if (novas[index_n].state==NOVA_ACTIVE)
  1192.        {
  1193.  
  1194.        // alias a pointer to cinder array for speed
  1195.  
  1196.        bits = (particle_ptr)novas[index_n].cinders;
  1197.  
  1198.        // process each cinder
  1199.  
  1200.        for (index_c=0; index_c<NUM_CINDERS; index_c++)
  1201.            {
  1202.  
  1203.            // is this cinder visible?
  1204.  
  1205.            if (bits[index_c].visible)
  1206.               Write_Pixel_DB(bits[index_c].sx,bits[index_c].sy,
  1207.                              bits[index_c].color);
  1208.  
  1209.            } // end for index_c
  1210.  
  1211.        } // end if nova active
  1212.  
  1213.     } // end for index_n
  1214.  
  1215. } // end Draw_Novas
  1216.  
  1217. /////////////////////////////////////////////////////////////////////////////
  1218.  
  1219. void Move_Novas(void)
  1220. {
  1221.  
  1222. // this function draws the novas
  1223.  
  1224. int index_n, // looping variables
  1225.     index_c;
  1226.  
  1227. particle_ptr bits;  // used as a high speed alias into cinders array
  1228.  
  1229. // process each nova
  1230.  
  1231. for (index_n=0; index_n<NUM_NOVAS; index_n++)
  1232.     {
  1233.  
  1234.     // is this nova active ?
  1235.  
  1236.     if (novas[index_n].state==NOVA_ACTIVE)
  1237.        {
  1238.  
  1239.        // alias a pointer to cinder array for speed
  1240.  
  1241.        bits = (particle_ptr)novas[index_n].cinders;
  1242.  
  1243.        // process each cinder
  1244.  
  1245.        for (index_c=0; index_c<NUM_CINDERS; index_c++)
  1246.            {
  1247.            // move the cinder
  1248.  
  1249.            bits[index_c].x+=bits[index_c].xv;
  1250.            bits[index_c].y+=bits[index_c].yv;
  1251.  
  1252.            // animate the cinder color
  1253.  
  1254.            if (++bits[index_c].counter > bits[index_c].threshold)
  1255.               {
  1256.               // decrement color
  1257.  
  1258.               if (++bits[index_c].color >= CINDER_END_COLOR)
  1259.                  bits[index_c].color = CINDER_END_COLOR;
  1260.  
  1261.               // reset counter
  1262.  
  1263.               bits[index_c].counter = 0;
  1264.  
  1265.               } // end if color change
  1266.  
  1267.            } // end for index_c
  1268.  
  1269.        // age the nova
  1270.  
  1271.        if (--novas[index_n].lifetime<=0)
  1272.           novas[index_n].state=NOVA_INACTIVE;
  1273.  
  1274.        } // end if nova active
  1275.  
  1276.     } // end for index_n
  1277.  
  1278. } // end Move_Novas
  1279.  
  1280. ///////////////////////////////////////////////////////////////////////////////
  1281.  
  1282. void Start_Nova(int x,int y)
  1283. {
  1284. // this function starts a super nova explosion
  1285.  
  1286. int index_c, // loopnig variables
  1287.     index_n;
  1288.  
  1289.  
  1290. // hunt for an inactive nove
  1291.  
  1292. for (index_n=0; index_n<NUM_NOVAS; index_n++)
  1293.     {
  1294.  
  1295.     // test for inactive nova
  1296.  
  1297.     if (novas[index_n].state==NOVA_INACTIVE)
  1298.        {
  1299.  
  1300.        // activate nova
  1301.  
  1302.        novas[index_n].state = NOVA_ACTIVE;
  1303.  
  1304.        // set lifetime in frames
  1305.  
  1306.        novas[index_n].lifetime = 50 + rand()%20;
  1307.  
  1308.        // intialize each cinder or restart a single cinder
  1309.  
  1310.        for (index_c=0; index_c<NUM_CINDERS; index_c++)
  1311.            {
  1312.            // fill in position, velocity and color of cinder
  1313.  
  1314.            novas[index_n].cinders[index_c].x   = x;
  1315.            novas[index_n].cinders[index_c].y   = y;
  1316.            novas[index_n].cinders[index_c].sx  = 0;
  1317.            novas[index_n].cinders[index_c].sy  = 0;
  1318.            novas[index_n].cinders[index_c].xv  = -8 + rand()%16;
  1319.            novas[index_n].cinders[index_c].yv  = -8 + rand()%16;
  1320.  
  1321.            novas[index_n].cinders[index_c].color      = CINDER_START_COLOR;
  1322.            novas[index_n].cinders[index_c].back_color = 0;
  1323.  
  1324.            // set timing fields
  1325.  
  1326.            novas[index_n].cinders[index_c].counter = 0;
  1327.            novas[index_n].cinders[index_c].threshold = 2 + rand()%6;
  1328.  
  1329.            } // end for index_c
  1330.  
  1331.            // make sound
  1332.  
  1333.            Digital_FX_Play(BLZEXP2_VOC,0);
  1334.  
  1335.        // break out of out for
  1336.  
  1337.        break;
  1338.  
  1339.        } // end if nova found
  1340.  
  1341.     } // end for index_n
  1342.  
  1343. } // end Start_Nova
  1344.  
  1345. //////////////////////////////////////////////////////////////////////////////
  1346.  
  1347. void Line_H_2(int x1,int x2,int y,int color,unsigned char far *dest)
  1348. {
  1349. // draw a horizontal line to the destination buffer
  1350.  
  1351. _fmemset((char far *)(dest + ((y<<8) + (y<<6)) + x1),
  1352.          (unsigned char)color,x2-x1+1);
  1353.  
  1354. } // end Line_H_2
  1355.  
  1356. //////////////////////////////////////////////////////////////////////////////
  1357.  
  1358. void Line_V_2(int y1,int y2,int x,int color, unsigned char far *dest)
  1359. {
  1360. // draw a vertical line to destination buffer
  1361.  
  1362. unsigned char far *start_offset; // starting memory offset of line
  1363.  
  1364. int index; // loop index
  1365.  
  1366. // compute starting position
  1367.  
  1368. start_offset = dest + ((y1<<8) + (y1<<6)) + x;
  1369.  
  1370. for (index=0; index<=y2-y1; index++)
  1371.     {
  1372.     // set the pixel
  1373.  
  1374.     *start_offset = (unsigned char)color;
  1375.  
  1376.     // move downward to next line
  1377.  
  1378.     start_offset+=320;
  1379.  
  1380.     } // end for index
  1381.  
  1382. } // end Line_V_2
  1383.  
  1384. //////////////////////////////////////////////////////////////////////////////
  1385.  
  1386. void Init_Stars(void)
  1387. {
  1388. // this function initializes all the stars in the star field
  1389.  
  1390. int index; // looping variable
  1391.  
  1392. for (index=0; index<NUM_STARS; index++)
  1393.     {
  1394.  
  1395.     // select plane that star will be in
  1396.  
  1397.     switch(rand()%3)
  1398.           {
  1399.           case STAR_PLANE_0:
  1400.                {
  1401.                stars[index].color = STAR_COLOR_0;
  1402.                stars[index].plane = STAR_PLANE_0;
  1403.                } break;
  1404.  
  1405.           case STAR_PLANE_1:
  1406.                {
  1407.                stars[index].color = STAR_COLOR_1;
  1408.                stars[index].plane = STAR_PLANE_1;
  1409.                } break;
  1410.  
  1411.           case STAR_PLANE_2:
  1412.                {
  1413.                stars[index].color = STAR_COLOR_2;
  1414.                stars[index].plane = STAR_PLANE_2;
  1415.                } break;
  1416.  
  1417.           default:break;
  1418.  
  1419.           } // end switch
  1420.  
  1421.      // set fields that aren't plane specific
  1422.  
  1423.      stars[index].x = rand()%320;  // change this latter to reflect clipping
  1424.      stars[index].y = rand()%200;  // region
  1425.      stars[index].back_color = 0;
  1426.  
  1427.     } // end for index
  1428.  
  1429. } // end Init_Stars
  1430.  
  1431. /////////////////////////////////////////////////////////////////////////////
  1432.  
  1433. void Move_Stars(void)
  1434. {
  1435. // this function moves the star field, note that the star field is always
  1436. // ins screen coordinates, otherwise, we would need thousands of stars to
  1437. // fill up the universe instead of 50!
  1438.  
  1439. int index,   // looping variable
  1440.     star_x,  // used as fast aliases to star position
  1441.     star_y,
  1442.     plane_0_dx,
  1443.     plane_0_dy,
  1444.     plane_1_dx,
  1445.     plane_1_dy,
  1446.     plane_2_dx,
  1447.     plane_2_dy;
  1448.  
  1449. // pre-compute plane translations
  1450.  
  1451. plane_0_dx = players_dx >> 2;
  1452. plane_0_dy = players_dy >> 2;
  1453.  
  1454. plane_1_dx = players_dx >> 1;
  1455. plane_1_dy = players_dy >> 1;
  1456.  
  1457. plane_2_dx = players_dx;
  1458. plane_2_dy = players_dy;
  1459.  
  1460. // move all the stars based on the motion of the player
  1461.  
  1462. for (index=0; index<NUM_STARS; index++)
  1463.     {
  1464.     // locally cache star position to speed up calculations
  1465.  
  1466.     star_x = stars[index].x;
  1467.     star_y = stars[index].y;
  1468.  
  1469.     // test which star field star is in so it is translated with correct
  1470.     // perspective
  1471.  
  1472.     switch(stars[index].plane)
  1473.           {
  1474.           case STAR_PLANE_0:
  1475.                {
  1476.                // move the star based on differntial motion of player
  1477.                // far plane is divided by 4
  1478.  
  1479.                star_x+=plane_0_dx;
  1480.                star_y+=plane_0_dy;
  1481.  
  1482.                } break;
  1483.  
  1484.           case STAR_PLANE_1:
  1485.                {
  1486.                // move the star based on differntial motion of player
  1487.                // middle plane is divided by 2
  1488.  
  1489.                star_x+=plane_1_dx;
  1490.                star_y+=plane_1_dy;
  1491.  
  1492.                } break;
  1493.  
  1494.           case STAR_PLANE_2:
  1495.                {
  1496.                // move the star based on differntial motion of player
  1497.                // near plane is divided by 1
  1498.  
  1499.                star_x+=plane_2_dx;
  1500.                star_y+=plane_2_dy;
  1501.  
  1502.                } break;
  1503.  
  1504.           } // end switch plane
  1505.  
  1506.     // test if a star has flown off an edge
  1507.  
  1508.     if (star_x >= 320)
  1509.         star_x = star_x-320;
  1510.     else
  1511.     if (star_x < 0)
  1512.         star_x = 320 + star_x;
  1513.  
  1514.     if (star_y >= 200)
  1515.         star_y = star_y-200;
  1516.     else
  1517.     if (star_y < 0)
  1518.         star_y = 200+star_y;
  1519.  
  1520.     // reset stars position in structure
  1521.  
  1522.     stars[index].x = star_x;
  1523.     stars[index].y = star_y;
  1524.  
  1525.     } // end for index
  1526.  
  1527. } // end Move_Stars
  1528.  
  1529. /////////////////////////////////////////////////////////////////////////////
  1530.  
  1531. void Draw_Stars(void)
  1532. {
  1533. // this function draws all the stars
  1534.  
  1535. int index; // looping variable
  1536.  
  1537. for (index=0; index<NUM_STARS; index++)
  1538.     Write_Pixel_DB(stars[index].x,stars[index].y,stars[index].color);
  1539.  
  1540. } // end Draw_Stars
  1541.  
  1542. /////////////////////////////////////////////////////////////////////////////
  1543.  
  1544. void Erase_Stars(void)
  1545. {
  1546. // this function erases all the stars
  1547.  
  1548. int index; // looping variable
  1549.  
  1550. for (index=0; index<NUM_STARS; index++)
  1551.     Write_Pixel_DB(stars[index].x,stars[index].y,stars[index].back_color);
  1552.  
  1553. } // end Erase_Stars
  1554.  
  1555. /////////////////////////////////////////////////////////////////////////////
  1556.  
  1557. void Under_Stars(void)
  1558. {
  1559. // this function scans under each star
  1560.  
  1561. int index; // looping variable
  1562.  
  1563. for (index=0; index<NUM_STARS; index++)
  1564.     stars[index].back_color = Read_Pixel_DB(stars[index].x,stars[index].y);
  1565.  
  1566. } // end Under_Stars
  1567.  
  1568. /////////////////////////////////////////////////////////////////////////////
  1569.  
  1570. void Init_Asteroids(int small, int medium, int large)
  1571. {
  1572. // this function loads in the imagery for the asteroids, allocates all the
  1573. // memory for them, sets up all the fields and starts them at random positions
  1574.  
  1575. int index,  // looping variables
  1576.     frame;
  1577.  
  1578. static int first_time=1;  // used to track first time this function is called
  1579.  
  1580. // intialize all the large asteroid sprites
  1581.  
  1582. for (index=START_LARGE_ASTEROIDS; index<=END_LARGE_ASTEROIDS; index++)
  1583.     {
  1584.  
  1585.     if (first_time)
  1586.     Sprite_Init((sprite_ptr)&asteroids[index].rock,
  1587.                 0,0,
  1588.                 ASTEROID_LARGE_WIDTH,ASTEROID_LARGE_HEIGHT,
  1589.                 0,0,0,0,0,0);
  1590.  
  1591.     // set position,velocity and type fields
  1592.  
  1593.     asteroids[index].xv         = -8 + rand()%16;
  1594.     asteroids[index].yv         = -8 + rand()%16;
  1595.     asteroids[index].x          = rand()%UNIVERSE_WIDTH;
  1596.     asteroids[index].y          = rand()%UNIVERSE_HEIGHT,
  1597.  
  1598.     asteroids[index].type       = ASTEROID_LARGE;
  1599.     asteroids[index].rock.state = ASTEROID_INACTIVE;
  1600.  
  1601.     // use this to control rotation rate
  1602.  
  1603.     asteroids[index].rock.threshold_1 = 1 + rand()%3;
  1604.  
  1605.     } // end for index
  1606.  
  1607. // intialize all the medium asteroid sprites
  1608.  
  1609. for (index=START_MEDIUM_ASTEROIDS; index<=END_MEDIUM_ASTEROIDS; index++)
  1610.     {
  1611.  
  1612.     if (first_time)
  1613.     Sprite_Init((sprite_ptr)&asteroids[index].rock,
  1614.                 0,0,
  1615.                 ASTEROID_MEDIUM_WIDTH,ASTEROID_MEDIUM_HEIGHT,
  1616.                 0,0,0,0,0,0);
  1617.  
  1618.     // set velocity and type fields
  1619.  
  1620.     asteroids[index].xv         = -6 + rand()%12;
  1621.     asteroids[index].yv         = -6 + rand()%12;
  1622.     asteroids[index].x          = rand()%UNIVERSE_WIDTH;
  1623.     asteroids[index].y          = rand()%UNIVERSE_HEIGHT,
  1624.     asteroids[index].type       = ASTEROID_MEDIUM;
  1625.     asteroids[index].rock.state = ASTEROID_INACTIVE;
  1626.  
  1627.     // use this to control rotation rate
  1628.  
  1629.     asteroids[index].rock.threshold_1 = 1 + rand()%3;
  1630.  
  1631.     } // end for index
  1632.  
  1633. // intialize all the small asteroid sprites
  1634.  
  1635. for (index=START_SMALL_ASTEROIDS; index<=END_SMALL_ASTEROIDS; index++)
  1636.     {
  1637.  
  1638.     if (first_time)
  1639.     Sprite_Init((sprite_ptr)&asteroids[index].rock,
  1640.                 0,0,
  1641.                 ASTEROID_SMALL_WIDTH,ASTEROID_SMALL_HEIGHT,
  1642.                 0,0,0,0,0,0);
  1643.  
  1644.     // set velocity and type fields
  1645.  
  1646.     asteroids[index].xv         = -4 + rand()%8;
  1647.     asteroids[index].yv         = -4 + rand()%8;
  1648.     asteroids[index].x          = rand()%UNIVERSE_WIDTH;
  1649.     asteroids[index].y          = rand()%UNIVERSE_HEIGHT,
  1650.     asteroids[index].type       = ASTEROID_SMALL;
  1651.     asteroids[index].rock.state = ASTEROID_INACTIVE;
  1652.  
  1653.     // use this to control rotation rate
  1654.  
  1655.     asteroids[index].rock.threshold_1 = 1 + rand()%3;
  1656.  
  1657.     } // end for index
  1658.  
  1659. // now load the imagery for the large asteroids
  1660.  
  1661. if (first_time)
  1662. {
  1663.  
  1664. PCX_Init((pcx_picture_ptr)&image_pcx);
  1665. PCX_Load("blazelas.pcx", (pcx_picture_ptr)&image_pcx,1);
  1666.  
  1667. // extract the bitmaps for the asteroid, there are 8 animation cells
  1668.  
  1669. for (index=0; index<NUM_ASTEROID_FRAMES; index++)
  1670.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  1671.                    (sprite_ptr)&asteroids[START_LARGE_ASTEROIDS].rock,
  1672.                    index,index,0);
  1673.  
  1674. // now alias pointers of remaining asteroids sprites to same data that
  1675. // was allocated for the first large asteroids, this saves a lot of memory!
  1676.  
  1677. for (index=START_LARGE_ASTEROIDS+1; index<=END_LARGE_ASTEROIDS; index++)
  1678.     {
  1679.     // alias all the frame image pointer of this asteroid to the frames
  1680.     // of the first asteroid, no need to replicate this data in memory!
  1681.  
  1682.     for (frame=0; frame<NUM_ASTEROID_FRAMES; frame++)
  1683.         {
  1684.         // the image frames are within the sprite which is called rock which
  1685.         // is within the asteroid structure
  1686.  
  1687.         asteroids[index].rock.frames[frame] =
  1688.                 asteroids[START_LARGE_ASTEROIDS].rock.frames[frame];
  1689.  
  1690.         } // end for frame
  1691.  
  1692.     // set number of frames field
  1693.  
  1694.     asteroids[index].rock.num_frames =
  1695.             asteroids[START_LARGE_ASTEROIDS].rock.num_frames;
  1696.  
  1697.     } // end for index
  1698.  
  1699. // delete the pcx file
  1700.  
  1701. PCX_Delete((pcx_picture_ptr)&image_pcx);
  1702.  
  1703.  
  1704. // now load the imagery for the medium asteroids
  1705.  
  1706. PCX_Init((pcx_picture_ptr)&image_pcx);
  1707. PCX_Load("blazemas.pcx", (pcx_picture_ptr)&image_pcx,1);
  1708.  
  1709. // extract the bitmaps for the asteroid, there are 8 animation cells
  1710.  
  1711. for (index=0; index<NUM_ASTEROID_FRAMES; index++)
  1712.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  1713.                    (sprite_ptr)&asteroids[START_MEDIUM_ASTEROIDS].rock,
  1714.                    index,index,0);
  1715.  
  1716. // now alias pointers of remaining asteroids sprites to same data that
  1717. // was allocated for the first large asteroids, this saves a lot of memory!
  1718.  
  1719. for (index=START_MEDIUM_ASTEROIDS+1; index<=END_MEDIUM_ASTEROIDS; index++)
  1720.     {
  1721.     // alias all the frame image pointer of this asteroid to the frames
  1722.     // of the first asteroid, no need to replicate this data in memory!
  1723.  
  1724.     for (frame=0; frame<NUM_ASTEROID_FRAMES; frame++)
  1725.         {
  1726.         // the image frames are within the sprite which is called rock which
  1727.         // is within the asteroid structure
  1728.  
  1729.         asteroids[index].rock.frames[frame] =
  1730.                        asteroids[START_MEDIUM_ASTEROIDS].rock.frames[frame];
  1731.  
  1732.         } // end for frame
  1733.  
  1734.     // set number of frames field
  1735.  
  1736.     asteroids[index].rock.num_frames =
  1737.             asteroids[START_MEDIUM_ASTEROIDS].rock.num_frames;
  1738.  
  1739.     } // end for index
  1740.  
  1741. // delete the pcx file
  1742.  
  1743. PCX_Delete((pcx_picture_ptr)&image_pcx);
  1744.  
  1745. // finally load the imagery for the small asteroids
  1746.  
  1747. PCX_Init((pcx_picture_ptr)&image_pcx);
  1748. PCX_Load("blazesas.pcx", (pcx_picture_ptr)&image_pcx,1);
  1749.  
  1750. // extract the bitmaps for the asteroid, there are 8 animation cells
  1751.  
  1752. for (index=0; index<NUM_ASTEROID_FRAMES; index++)
  1753.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  1754.                    (sprite_ptr)&asteroids[START_SMALL_ASTEROIDS].rock,
  1755.                    index,index,0);
  1756.  
  1757. // now alias pointers of remaining asteroids sprites to same data that
  1758. // was allocated for the first large asteroids, this saves a lot of memory!
  1759.  
  1760. for (index=START_SMALL_ASTEROIDS+1; index<=END_SMALL_ASTEROIDS; index++)
  1761.     {
  1762.     // alias all the frame image pointer of this asteroid to the frames
  1763.     // of the first asteroid, no need to replicate this data in memory!
  1764.  
  1765.     for (frame=0; frame<NUM_ASTEROID_FRAMES; frame++)
  1766.         {
  1767.         // the image frames are within the sprite which is called rock which
  1768.         // is within the asteroid structure
  1769.  
  1770.         asteroids[index].rock.frames[frame] =
  1771.                        asteroids[START_SMALL_ASTEROIDS].rock.frames[frame];
  1772.  
  1773.         } // end for frame
  1774.  
  1775.     // set number of frames field
  1776.  
  1777.     asteroids[index].rock.num_frames =
  1778.             asteroids[START_SMALL_ASTEROIDS].rock.num_frames;
  1779.  
  1780.     } // end for index
  1781.  
  1782. // delete the pcx file
  1783.  
  1784. PCX_Delete((pcx_picture_ptr)&image_pcx);
  1785.  
  1786. } // end if first time
  1787.  
  1788.  
  1789.  
  1790. // now start up the requested number of asteroids
  1791.  
  1792. // first the large
  1793.  
  1794. for (index=0; index<large; index++)
  1795.     {
  1796.     // look for inactive asteroids to start up
  1797.  
  1798.     if (asteroids[index+START_LARGE_ASTEROIDS].rock.state == ASTEROID_INACTIVE)
  1799.         asteroids[index+START_LARGE_ASTEROIDS].rock.state = ASTEROID_ACTIVE;
  1800.  
  1801.     } // end for index
  1802.  
  1803. // now the medium
  1804.  
  1805. for (index=0; index<medium; index++)
  1806.     {
  1807.     // look for inactive asteroids to start up
  1808.  
  1809.     if (asteroids[index+START_MEDIUM_ASTEROIDS].rock.state == ASTEROID_INACTIVE)
  1810.         asteroids[index+START_MEDIUM_ASTEROIDS].rock.state = ASTEROID_ACTIVE;
  1811.  
  1812.     } // end for index
  1813.  
  1814. // finally the small
  1815.  
  1816. for (index=0; index<small; index++)
  1817.     {
  1818.     // look for inactive asteroids to start up
  1819.  
  1820.     if (asteroids[index+START_SMALL_ASTEROIDS].rock.state == ASTEROID_INACTIVE)
  1821.         asteroids[index+START_SMALL_ASTEROIDS].rock.state = ASTEROID_ACTIVE;
  1822.  
  1823.     } // end for index
  1824.  
  1825. // test if this was the first tmie the function was called
  1826.  
  1827. if (first_time)
  1828.     first_time=0;
  1829.  
  1830. // what a pain!
  1831.  
  1832. } // end Init_Asteroids
  1833.  
  1834. /////////////////////////////////////////////////////////////////////////////
  1835.  
  1836. void Start_Asteroid(int x,int y,int type)
  1837. {
  1838. // this function is used to start up an asteroid at the sent position
  1839. // later possible implement velocity?
  1840.  
  1841. int index;  // looping variable
  1842.  
  1843. // which kind of asteroid is being requested?
  1844.  
  1845. switch(type)
  1846.       {
  1847.       case ASTEROID_LARGE:
  1848.            {
  1849.            // scan for inactive asteroid
  1850.  
  1851.            for (index=START_LARGE_ASTEROIDS; index<=END_LARGE_ASTEROIDS; index++)
  1852.                {
  1853.                // is this asteroid being used?
  1854.  
  1855.                if (asteroids[index].rock.state==ASTEROID_INACTIVE)
  1856.                   {
  1857.                   // set fields of asteroid and return
  1858.                   asteroids[index].xv         = -8 + rand()%16;
  1859.                   asteroids[index].yv         = -8 + rand()%16;
  1860.                   asteroids[index].x          = x;
  1861.                   asteroids[index].y          = y,
  1862.                   asteroids[index].rock.state = ASTEROID_ACTIVE;
  1863.                   return;
  1864.  
  1865.                   } // end if found an asteroid
  1866.  
  1867.                } // end for index
  1868.  
  1869.            } break;
  1870.  
  1871.       case ASTEROID_MEDIUM:
  1872.            {
  1873.            // scan for inactive asteroid
  1874.  
  1875.            for (index=START_MEDIUM_ASTEROIDS; index<=END_MEDIUM_ASTEROIDS; index++)
  1876.                {
  1877.                // is this asteroid being used?
  1878.  
  1879.                if (asteroids[index].rock.state==ASTEROID_INACTIVE)
  1880.                   {
  1881.                   // set fields of asteroid and return
  1882.                   asteroids[index].xv         = -6 + rand()%12;
  1883.                   asteroids[index].yv         = -6 + rand()%12;
  1884.                   asteroids[index].x          = x;
  1885.                   asteroids[index].y          = y,
  1886.                   asteroids[index].rock.state = ASTEROID_ACTIVE;
  1887.                   return;
  1888.  
  1889.                   } // end if found an asteroid
  1890.  
  1891.                } // end for index
  1892.  
  1893.            } break;
  1894.  
  1895.       case ASTEROID_SMALL:
  1896.            {
  1897.            // scan for inactive asteroid
  1898.  
  1899.            for (index=START_SMALL_ASTEROIDS; index<=END_SMALL_ASTEROIDS; index++)
  1900.                {
  1901.                // is this asteroid being used?
  1902.  
  1903.                if (asteroids[index].rock.state==ASTEROID_INACTIVE)
  1904.                   {
  1905.                   // set fields of asteroid and return
  1906.  
  1907.                   asteroids[index].xv         = -4 + rand()%8;
  1908.                   asteroids[index].yv         = -4 + rand()%8;
  1909.                   asteroids[index].x          = x;
  1910.                   asteroids[index].y          = y,
  1911.                   asteroids[index].rock.state = ASTEROID_ACTIVE;
  1912.                   return;
  1913.  
  1914.                   } // end if found an asteroid
  1915.  
  1916.                } // end for index
  1917.  
  1918.            } break;
  1919.  
  1920.       } // end swtich
  1921.  
  1922. } // end Start_Asteroid
  1923.  
  1924. //////////////////////////////////////////////////////////////////////////////
  1925.  
  1926. void Erase_Asteroids(void)
  1927. {
  1928. // this function traverses the asteroid list and erases all asteroids that
  1929. // are active
  1930.  
  1931. int index;
  1932.  
  1933. // erase all asteroids that are within screen window
  1934.  
  1935. for (index=0; index<NUM_ASTEROIDS; index++)
  1936.     {
  1937.     // test if this asteroids is active
  1938.  
  1939.     if (asteroids[index].rock.state==ASTEROID_ACTIVE)
  1940.        Sprite_Erase_Clip((sprite_ptr)&asteroids[index].rock,double_buffer);
  1941.  
  1942.     } // end for index
  1943.  
  1944. } // Erase_Asteroids
  1945.  
  1946. //////////////////////////////////////////////////////////////////////////////
  1947.  
  1948. void Draw_Asteroids(void)
  1949. {
  1950. // this function traverses the asteroid list and draws all asteroids that
  1951. // are active
  1952.  
  1953. int index;
  1954.  
  1955. for (index=0; index<NUM_ASTEROIDS; index++)
  1956.     {
  1957.     // test if this asteroids is active
  1958.  
  1959.     if (asteroids[index].rock.state==ASTEROID_ACTIVE)
  1960.         Sprite_Draw_Clip((sprite_ptr)&asteroids[index].rock,double_buffer,1);
  1961.  
  1962.     } // end for index
  1963.  
  1964. } // Draw_Asteroids
  1965.  
  1966. //////////////////////////////////////////////////////////////////////////////
  1967.  
  1968. void Under_Asteroids(void)
  1969. {
  1970.  
  1971. // this function traverses the asteroid list and scans under all asteroids that
  1972. // are active, note that this function is the only one that computes the screen
  1973. // coordinates of the asteroid sprites, placing the computation in the other
  1974. // functions would be redundant, hence the sprite coordinates at this function
  1975. // are undefined, and after this function they have been remapped to the video
  1976. // screen relative to the players position
  1977.  
  1978.  
  1979. int index,
  1980.     px_window,   // the starting postion of the players window
  1981.     py_window;
  1982.  
  1983. // compute starting position of players window so screen mapping can be done
  1984.  
  1985. px_window = players_x - 160+11;
  1986. py_window = players_y - 100+9;
  1987.  
  1988. // now scan under all asteroids
  1989.  
  1990. for (index=0; index<NUM_ASTEROIDS; index++)
  1991.     {
  1992.     // test if this asteroids is active
  1993.  
  1994.     if (asteroids[index].rock.state==ASTEROID_ACTIVE)
  1995.        {
  1996.  
  1997.        // postion asteroid correctly on view screen, note this is very similar
  1998.        // to what we will do in 3-D when we translate all the objects in the
  1999.        // universe to the viewer position
  2000.  
  2001.        asteroids[index].rock.x = (asteroids[index].x-px_window);
  2002.        asteroids[index].rock.y = (asteroids[index].y-py_window);
  2003.  
  2004.        Sprite_Under_Clip((sprite_ptr)&asteroids[index].rock,double_buffer);
  2005.  
  2006.        } // end if active
  2007.  
  2008.     } // end for index
  2009.  
  2010. } // Under_Asteroids
  2011.  
  2012. //////////////////////////////////////////////////////////////////////////////
  2013.  
  2014. void Move_Asteroids(void)
  2015. {
  2016.  
  2017. // this function traverses the asteroid list and moves and test for collsions
  2018. // note that the sprite positions of the asteroids are not touched only the
  2019. // universe or "world" coordinates are
  2020.  
  2021. int index,         // looping variable
  2022.     ast_x,ast_y;   // used for aliasing
  2023.  
  2024. // process each asteroid
  2025.  
  2026. for (index=0; index<NUM_ASTEROIDS; index++)
  2027.     {
  2028.     // test if this asteroids is active
  2029.  
  2030.     if (asteroids[index].rock.state==ASTEROID_ACTIVE)
  2031.        {
  2032.        // move the asteroid
  2033.  
  2034.        ast_x=asteroids[index].x;
  2035.        ast_y=asteroids[index].y;
  2036.  
  2037.        ast_x+=asteroids[index].xv;
  2038.        ast_y+=asteroids[index].yv;
  2039.  
  2040.        // test if asteroid is off screen bounadary
  2041.  
  2042.        if (ast_x>UNIVERSE_WIDTH+UNIVERSE_BORDER)
  2043.            ast_x = -UNIVERSE_BORDER;
  2044.        else
  2045.        if (ast_x<-UNIVERSE_BORDER)
  2046.            ast_x = UNIVERSE_WIDTH+UNIVERSE_BORDER;
  2047.  
  2048.        if (ast_y>UNIVERSE_HEIGHT+UNIVERSE_BORDER)
  2049.            ast_y = -UNIVERSE_BORDER;
  2050.        else
  2051.        if (ast_y<-UNIVERSE_BORDER)
  2052.            ast_y = UNIVERSE_HEIGHT+UNIVERSE_BORDER;
  2053.  
  2054.        // restore variables in structure
  2055.  
  2056.        asteroids[index].x = ast_x;
  2057.        asteroids[index].y = ast_y;
  2058.  
  2059.        // animate asteroid
  2060.  
  2061.        if (++asteroids[index].rock.counter_1>=asteroids[index].rock.threshold_1)
  2062.           {
  2063.           // reset counter
  2064.  
  2065.           asteroids[index].rock.counter_1 = 0;
  2066.  
  2067.           if (++asteroids[index].rock.curr_frame >= NUM_ASTEROID_FRAMES)
  2068.               asteroids[index].rock.curr_frame = 0;
  2069.  
  2070.           } // end if time to animate
  2071.  
  2072.        // test if asteroid has hit player
  2073.  
  2074.        // test for collision
  2075.  
  2076.        if (players_x+SHIP_WIDTH/2  >= ast_x                             &&
  2077.            players_y+SHIP_HEIGHT/2 >= ast_y                             &&
  2078.            players_x+SHIP_WIDTH/2  <= ast_x+asteroids[index].rock.width &&
  2079.            players_y+SHIP_HEIGHT/2 <= ast_y+asteroids[index].rock.height)
  2080.           {
  2081.           // kill the asteroid and the missile
  2082.  
  2083.           asteroids[index].rock.state = ASTEROID_INACTIVE;
  2084.  
  2085.           // what kind of asteroid did we have?
  2086.  
  2087.           switch(asteroids[index].type)
  2088.                 {
  2089.  
  2090.                 case ASTEROID_LARGE:
  2091.                      {
  2092.  
  2093.                      // start one medium and one small asteroid
  2094.                      //  (if possible)
  2095.  
  2096.                      Start_Asteroid(asteroids[index].x,
  2097.                                     asteroids[index].y,
  2098.                                     ASTEROID_MEDIUM);
  2099.  
  2100.                      Start_Asteroid(asteroids[index].x+ASTEROID_LARGE_WIDTH/2,
  2101.                                     asteroids[index].y+ASTEROID_LARGE_HEIGHT/2,
  2102.                                     ASTEROID_SMALL);
  2103.  
  2104.                      } break;
  2105.  
  2106.                 case ASTEROID_MEDIUM:
  2107.                      {
  2108.  
  2109.                      // start two small asteroids (if possible)
  2110.  
  2111.                      Start_Asteroid(asteroids[index].x,
  2112.                                     asteroids[index].y,
  2113.                                     ASTEROID_SMALL);
  2114.  
  2115.                      Start_Asteroid(asteroids[index].x+ASTEROID_MEDIUM_WIDTH/2,
  2116.                                     asteroids[index].y+ASTEROID_MEDIUM_HEIGHT/2,
  2117.                                     ASTEROID_SMALL);
  2118.  
  2119.                      } break;
  2120.  
  2121.                 case ASTEROID_SMALL:
  2122.                      {
  2123.  
  2124.                      // start a randomly positioned asteroid of any size
  2125.                      // at the worm hole
  2126.  
  2127.                      Start_Asteroid(WORMHOLE_X,WORMHOLE_Y,rand()%3);
  2128.  
  2129.                      } break;
  2130.  
  2131.                 default:break;
  2132.  
  2133.                 } // end switch
  2134.  
  2135.           // were shields up?
  2136.  
  2137.           if (players_shields)
  2138.              {
  2139.              // start explosion
  2140.              Start_Explosion(players_x,players_y,2);
  2141.              } // end if shields up
  2142.           else
  2143.              { // say bye bye!
  2144.  
  2145.              Start_Explosion(players_x,players_y,2);
  2146.              Start_Nova(players_x+SHIP_WIDTH/2,players_y+SHIP_HEIGHT/2);
  2147.  
  2148.              // start players death sequence
  2149.  
  2150.              Start_Players_Death();
  2151.  
  2152.              } // end if else
  2153.  
  2154.           } // end if player has been hit
  2155.  
  2156.        // test if asteroid has hit remote
  2157.  
  2158.        // test for collision
  2159.  
  2160.        if (linked)
  2161.        {
  2162.        if (remotes_x+SHIP_WIDTH/2  >= ast_x                             &&
  2163.            remotes_y+SHIP_HEIGHT/2 >= ast_y                             &&
  2164.            remotes_x+SHIP_WIDTH/2  <= ast_x+asteroids[index].rock.width &&
  2165.            remotes_y+SHIP_HEIGHT/2 <= ast_y+asteroids[index].rock.height)
  2166.           {
  2167.           // kill the asteroid and the missile
  2168.  
  2169.           asteroids[index].rock.state = ASTEROID_INACTIVE;
  2170.  
  2171.           // what kind of asteroid did we have?
  2172.  
  2173.           switch(asteroids[index].type)
  2174.                 {
  2175.  
  2176.                 case ASTEROID_LARGE:
  2177.                      {
  2178.                      // start one medium and one small asteroid
  2179.                      //  (if possible)
  2180.  
  2181.                      Start_Asteroid(asteroids[index].x,
  2182.                                     asteroids[index].y,
  2183.                                     ASTEROID_MEDIUM);
  2184.  
  2185.                      Start_Asteroid(asteroids[index].x+ASTEROID_LARGE_WIDTH/2,
  2186.                                     asteroids[index].y+ASTEROID_LARGE_HEIGHT/2,
  2187.                                     ASTEROID_SMALL);
  2188.  
  2189.                      } break;
  2190.  
  2191.                 case ASTEROID_MEDIUM:
  2192.                      {
  2193.                      // start two small asteroids (if possible)
  2194.  
  2195.                      Start_Asteroid(asteroids[index].x,
  2196.                                     asteroids[index].y,
  2197.                                     ASTEROID_SMALL);
  2198.  
  2199.                      Start_Asteroid(asteroids[index].x+ASTEROID_MEDIUM_WIDTH/2,
  2200.                                     asteroids[index].y+ASTEROID_MEDIUM_HEIGHT/2,
  2201.                                     ASTEROID_SMALL);
  2202.  
  2203.                      } break;
  2204.  
  2205.                 case ASTEROID_SMALL:
  2206.                      {
  2207.  
  2208.                      // start a randomly positioned asteroid of any size
  2209.                      // at the worm hole
  2210.  
  2211.                      Start_Asteroid(WORMHOLE_X,WORMHOLE_Y,rand()%3);
  2212.  
  2213.                      } break;
  2214.  
  2215.                 default:break;
  2216.  
  2217.                 } // end switch
  2218.  
  2219.           // were shields up?
  2220.  
  2221.           if (remotes_shields)
  2222.              {
  2223.              // start explosion
  2224.              Start_Explosion(remotes_x,remotes_y,2);
  2225.              } // end if shields up
  2226.           else
  2227.              { // say bye bye!
  2228.  
  2229.              Start_Explosion(remotes_x,remotes_y,2);
  2230.              Start_Nova(remotes_x+SHIP_WIDTH/2,remotes_y+SHIP_HEIGHT/2);
  2231.  
  2232.              // start remotes death sequence
  2233.  
  2234.              Start_Remotes_Death();
  2235.  
  2236.              } // end if else
  2237.  
  2238.           } // end if remote has been hit
  2239.  
  2240.        } // end if linked
  2241.  
  2242.        } // end if asteroids is active
  2243.  
  2244.     } // end for index
  2245.  
  2246. } // Move_Asteroids
  2247.  
  2248. //////////////////////////////////////////////////////////////////////////////
  2249.  
  2250. void Tech_Print(int x,int y,char *string,unsigned char far *destination)
  2251. {
  2252. // this function is used to print text out like a teletypwriter,it looks
  2253. // cool, trust me!
  2254.  
  2255. int length,  // length of input string
  2256.     index,   // looping variable
  2257.     counter; // used to time process
  2258.  
  2259. char buffer[3];  // a little string used to call font engine with
  2260.  
  2261. // compute length of input string
  2262.  
  2263. length = strlen(string);
  2264.  
  2265. // print the string out a character at a time
  2266.  
  2267. for (index=0; index<length; index++)
  2268.     {
  2269.     // the first character is the actual printable character
  2270.  
  2271.     buffer[0] = string[index];
  2272.  
  2273.     // this is a little cursor kind of thing
  2274.  
  2275.     buffer[1] = '<';
  2276.  
  2277.     // null terminate
  2278.  
  2279.     buffer[2] = 0;
  2280.  
  2281.     // print the string
  2282.  
  2283.     Font_Engine_1(x,y,0,0,buffer,destination);
  2284.  
  2285.     // move to next position
  2286.  
  2287.     x+=(TECH_FONT_WIDTH+1);
  2288.  
  2289.     // wait a bit  1/70th of a second
  2290.  
  2291.     Wait_For_Vertical_Retrace();
  2292.  
  2293.     // clear the cursor
  2294.  
  2295.     } // end for
  2296.  
  2297.     // clear the cursor
  2298.  
  2299.     buffer[0] = ' ';
  2300.     buffer[1] = ' ';
  2301.     buffer[2] = 0;
  2302.  
  2303.     Font_Engine_1(x,y,0,0,buffer,destination);
  2304.  
  2305. // done!
  2306.  
  2307. } // end Tech_Print
  2308.  
  2309. //////////////////////////////////////////////////////////////////////////////
  2310.  
  2311. void Font_Engine_1(int x,int y,
  2312.                    int font,int color,
  2313.                    char *string,unsigned char far *destination)
  2314. {
  2315. // this function prints a string out using one of the graphics fonts that
  2316. // we have drawn, note this first version doesn't use the font field, but
  2317. // we'll throw it in to keep the interface open for a future version
  2318.  
  2319. static int font_loaded=0;   // this is used to track the first time the
  2320.                             // function is loaded
  2321.  
  2322. int index,    // loop index
  2323.     c_index,  // character index
  2324.     length;   // used to compute lengths of strings
  2325.  
  2326. // test if this is the first time this function is called, if so load the
  2327. // font
  2328.  
  2329. if (!font_loaded)
  2330.    {
  2331.  
  2332.    // load the 4x7 tech font
  2333.  
  2334.    PCX_Init((pcx_picture_ptr)&image_pcx);
  2335.    PCX_Load("blazefnt.pcx", (pcx_picture_ptr)&image_pcx,1);
  2336.  
  2337.    // allocate memory for each bitmap and load character
  2338.  
  2339.    for (index=0; index<NUM_TECH_FONT; index++)
  2340.        {
  2341.        // allocate memory for charcter
  2342.  
  2343.        Bitmap_Allocate((bitmap_ptr)&tech_font[index],
  2344.                        TECH_FONT_WIDTH,TECH_FONT_HEIGHT);
  2345.  
  2346.        // set size of character
  2347.  
  2348.        tech_font[index].width = TECH_FONT_WIDTH;
  2349.        tech_font[index].height= TECH_FONT_HEIGHT;
  2350.  
  2351.        // extract bitmap from PCX buffer
  2352.  
  2353.        tech_font[index].x = 1 + (index % 16) * (TECH_FONT_WIDTH+1);
  2354.        tech_font[index].y = 1 + (index / 16) * (TECH_FONT_HEIGHT+1);
  2355.  
  2356.        Bitmap_Get((bitmap_ptr)&tech_font[index],
  2357.                   (unsigned char far *)image_pcx.buffer);
  2358.  
  2359.        } // end for index
  2360.    // font is loaded, delete pcx file and set flag
  2361.  
  2362.    PCX_Delete((pcx_picture_ptr)&image_pcx);
  2363.  
  2364.    font_loaded=1;
  2365.  
  2366.    } // end if first time
  2367. else
  2368.    {
  2369.    // print the sent string
  2370.  
  2371.    // pre-compute length of string
  2372.  
  2373.    length=strlen(string);
  2374.  
  2375.    // print the string character by character
  2376.  
  2377.    for (index=0; index<length; index++)
  2378.        {
  2379.        // extract the character index from the space character
  2380.  
  2381.        c_index = string[index] - ' ';
  2382.  
  2383.        // set bitmap position
  2384.  
  2385.        tech_font[c_index].y = y;
  2386.        tech_font[c_index].x = x;
  2387.  
  2388.        // display bitmap
  2389.  
  2390.        Bitmap_Put((bitmap_ptr)&tech_font[c_index],
  2391.                   (unsigned char far*)destination,0);
  2392.  
  2393.        // move to next character position
  2394.  
  2395.        x+=(TECH_FONT_WIDTH+1);
  2396.  
  2397.        } // end for index
  2398.  
  2399.    } // end else print string
  2400.  
  2401. } // end Font_Engine_1
  2402.  
  2403. /////////////////////////////////////////////////////////////////////////////
  2404.  
  2405. void Clear_Display(int color)
  2406. {
  2407. // this function fills the setup display screen with a color
  2408.  
  2409. int y;
  2410.  
  2411. // clear display with horizontal lines
  2412.  
  2413. for (y=DISPLAY_Y; y<DISPLAY_Y + DISPLAY_HEIGHT; y++)
  2414.      Line_H(DISPLAY_X,DISPLAY_X+DISPLAY_WIDTH-1,y,color);
  2415.  
  2416. } // end Clear_Display
  2417.  
  2418. /////////////////////////////////////////////////////////////////////////////
  2419.  
  2420. void Intro_Title(void)
  2421. {
  2422.  
  2423. // load in the starblazer title screen
  2424.  
  2425. PCX_Init((pcx_picture_ptr)&image_pcx);
  2426. PCX_Load("blazeint.pcx",(pcx_picture_ptr)&image_pcx,1);
  2427.  
  2428. // done with data so delete it
  2429.  
  2430. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2431.  
  2432. // show the PCX buffer
  2433.  
  2434. PCX_Show_Buffer((pcx_picture_ptr)&image_pcx);
  2435.  
  2436. // do special effects
  2437.  
  2438. // wait for a sec
  2439.  
  2440. Time_Delay(10);
  2441.  
  2442. Do_Starburst();
  2443.  
  2444. Time_Delay(50);
  2445.  
  2446. } // end Intro_Title
  2447.  
  2448. //////////////////////////////////////////////////////////////////////////////
  2449.  
  2450. void Closing_Screen(void)
  2451. {
  2452. // this function prints the credits
  2453.  
  2454. // blank the screen
  2455.  
  2456. Fill_Screen(0);
  2457.  
  2458. // restore pallete
  2459.  
  2460. Write_Palette(0,255,(RGB_palette_ptr)&game_palette);
  2461.  
  2462. if (music_enabled)
  2463.    {
  2464.    Music_Stop();
  2465.    Music_Play((music_ptr)&song,10);
  2466.    }
  2467.  
  2468. // draw the credits
  2469.  
  2470. Tech_Print(10,50,"MUSICAL MASTERY BY",video_buffer);
  2471. Time_Delay(20);
  2472. Tech_Print(20,60,"DEAN HUDSON OF",video_buffer);
  2473. Time_Delay(20);
  2474. Tech_Print(30,70,"ECLIPSE PRODUCTIONS",video_buffer);
  2475. Time_Delay(20);
  2476.  
  2477. Tech_Print(10,100,"MIDPAK INSTRUMENTATION CONSULTING BY",video_buffer);
  2478. Time_Delay(20);
  2479. Tech_Print(20,110,"ROB WALLACE OF",video_buffer);
  2480. Time_Delay(20);
  2481. Tech_Print(30,120,"WALLACE MUSIC & SOUND",video_buffer);
  2482.  
  2483. // wait a sec
  2484.  
  2485. Time_Delay(125);
  2486.  
  2487. // fade away
  2488.  
  2489. Screen_Transition(SCREEN_DARKNESS);
  2490.  
  2491. } // end Closing_Screen
  2492.  
  2493. //////////////////////////////////////////////////////////////////////////////
  2494.  
  2495. void Intro_Waite(void)
  2496. {
  2497.  
  2498. // load in the waite group title screen
  2499.  
  2500. PCX_Init((pcx_picture_ptr)&image_pcx);
  2501. PCX_Load("waite.pcx",(pcx_picture_ptr)&image_pcx,1);
  2502.  
  2503. // done with data so delete it
  2504.  
  2505. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2506.  
  2507. // show the PCX buffer
  2508.  
  2509. PCX_Show_Buffer((pcx_picture_ptr)&image_pcx);
  2510.  
  2511. // do special effects
  2512.  
  2513. // wait for a sec
  2514.  
  2515. Time_Delay(40);
  2516.  
  2517. Screen_Transition(SCREEN_WHITENESS);
  2518.  
  2519. // blank the screen
  2520.  
  2521. Fill_Screen(0);
  2522.  
  2523. } // end Intro_Waite
  2524.  
  2525. //////////////////////////////////////////////////////////////////////////////
  2526.  
  2527. void Intro_Controls(void)
  2528. {
  2529. // this function displays the controls screen
  2530.  
  2531. // load in the starblazer controls screen
  2532.  
  2533. PCX_Init((pcx_picture_ptr)&image_controls);
  2534. PCX_Load("blazecon.pcx",(pcx_picture_ptr)&image_controls,1);
  2535.  
  2536. // copy controls data to video buffer
  2537.  
  2538. PCX_Show_Buffer((pcx_picture_ptr)&image_controls);
  2539.  
  2540. // scan under button sprite and draw
  2541.  
  2542. Sprite_Under((sprite_ptr)&button_1,video_buffer);
  2543. Sprite_Draw((sprite_ptr)&button_1,video_buffer,1);
  2544.  
  2545. // delete pcx file
  2546.  
  2547. PCX_Delete((pcx_picture_ptr)&image_controls);
  2548.  
  2549. } // end Intro_Controls
  2550.  
  2551. ////////////////////////////////////////////////////////////////////////////
  2552.  
  2553. void Intro_Briefing(void)
  2554. {
  2555. // this function displays the controls screen
  2556.  
  2557. int done=0, // exit flag
  2558.     page=0, // current page user is reading
  2559.     index;  // looping variable
  2560.  
  2561. // load in the starblazer controls screen
  2562.  
  2563. PCX_Init((pcx_picture_ptr)&image_controls);
  2564. PCX_Load("blazeins.pcx",(pcx_picture_ptr)&image_controls,1);
  2565.  
  2566. // copy controls data to video buffer
  2567.  
  2568. PCX_Show_Buffer((pcx_picture_ptr)&image_controls);
  2569.  
  2570. // delete pcx file
  2571.  
  2572. PCX_Delete((pcx_picture_ptr)&image_controls);
  2573.  
  2574. // display the first page
  2575.  
  2576. for (index=0; index<NUM_LINES_PAGE; index++)
  2577.     Font_Engine_1(78,24+index*8,0,0,instructions[index+page*17],video_buffer);
  2578.  
  2579. // enter main event loop
  2580.  
  2581. while(!done)
  2582.      {
  2583.      // has the user pressed a key
  2584.  
  2585.      if (keys_active>0)
  2586.         {
  2587.  
  2588.         if (keyboard_state[MAKE_UP])
  2589.            {
  2590.            // page up
  2591.  
  2592.            if (--page<0)
  2593.               page = 0;
  2594.  
  2595.            // press button
  2596.  
  2597.            button_3.x = 185;
  2598.            button_3.y = 170;
  2599.            button_3.curr_frame = 3;
  2600.  
  2601.            Sprite_Draw((sprite_ptr)&button_3,video_buffer,1);
  2602.  
  2603.            Digital_FX_Play(BLZKEY_VOC,2);
  2604.  
  2605.            Time_Delay(2);
  2606.  
  2607.            button_3.curr_frame = 2;
  2608.  
  2609.            Sprite_Draw((sprite_ptr)&button_3,video_buffer,1);
  2610.  
  2611.            } // end if up
  2612.  
  2613.         if (keyboard_state[MAKE_DOWN])
  2614.            {
  2615.            // page down
  2616.  
  2617.            if (++page>=NUM_PAGES)
  2618.               page = NUM_PAGES-1;
  2619.  
  2620.  
  2621.            // press button
  2622.  
  2623.            button_3.x = 106;
  2624.            button_3.y = 170;
  2625.            button_3.curr_frame = 1;
  2626.  
  2627.            Sprite_Draw((sprite_ptr)&button_3,video_buffer,1);
  2628.  
  2629.            Digital_FX_Play(BLZKEY_VOC,2);
  2630.  
  2631.            Time_Delay(2);
  2632.  
  2633.            button_3.curr_frame = 0;
  2634.  
  2635.            Sprite_Draw((sprite_ptr)&button_3,video_buffer,1);
  2636.  
  2637.            } // end if down
  2638.  
  2639.         if (keyboard_state[MAKE_ESC])
  2640.            {
  2641.            done=1;
  2642.            } // end if esc
  2643.  
  2644.         // refresh display
  2645.  
  2646.         for (index=0; index<NUM_LINES_PAGE; index++)
  2647.             Font_Engine_1(78,24+index*8,0,0,instructions[index+page*17],video_buffer);
  2648.  
  2649.         } // end if a key has been pressed
  2650.  
  2651.      // do the scrolling lite thing
  2652.  
  2653.      Panel_FX();
  2654.  
  2655.      // wait a sec
  2656.  
  2657.      Time_Delay(1);
  2658.  
  2659.      } // end main while
  2660.  
  2661. } // end Intro_Briefing
  2662.  
  2663. ////////////////////////////////////////////////////////////////////////////
  2664.  
  2665. void Load_Explosions(void)
  2666. {
  2667. // this function loads the bitmap explosions
  2668.  
  2669. int index,  // looping variable
  2670.     frames; // looping variable
  2671.  
  2672. // load the imagery for the explosions
  2673.  
  2674. PCX_Init((pcx_picture_ptr)&image_pcx);
  2675. PCX_Load("blazeexp.pcx", (pcx_picture_ptr)&image_pcx,1);
  2676.  
  2677. // load each explosion in
  2678.  
  2679. for (index=0; index<NUM_EXPLOSIONS; index++)
  2680.     {
  2681.     // initialize each sprite
  2682.  
  2683.     Sprite_Init((sprite_ptr)&explosions[index],0,0,28,22,0,0,0,0,0,0);
  2684.  
  2685.     // extract the animation frames
  2686.  
  2687.     for (frames=0; frames<NUM_EXPLOSION_FRAMES; frames++)
  2688.         PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&explosions[index],frames,frames,0);
  2689.  
  2690.     } // end index
  2691.  
  2692. // delete the pcx file
  2693.  
  2694. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2695.  
  2696. } // end Load_Explosions
  2697.  
  2698. ////////////////////////////////////////////////////////////////////////////
  2699.  
  2700. void Load_Icons(void)
  2701. {
  2702. // this function loads various icons for the game
  2703.  
  2704. int index; // looping variable
  2705.  
  2706. // load the imagery for the control buttons on the setup screen
  2707.  
  2708. PCX_Init((pcx_picture_ptr)&image_pcx);
  2709. PCX_Load("blazebt1.pcx", (pcx_picture_ptr)&image_pcx,1);
  2710.  
  2711. // intialize the button sprite
  2712.  
  2713. Sprite_Init((sprite_ptr)&button_1,118-10,63,10,8,0,0,0,0,0,0);
  2714.  
  2715. button_1.counter_1 = 0;  // button is on the 0th element in the list
  2716.  
  2717. // extract the bitmaps for the button, there are 4 animation cells
  2718.  
  2719. for (index=0; index<4; index++)
  2720.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&button_1,index,index,0);
  2721.  
  2722. // load in display selection buttons
  2723.  
  2724. // intialize the button sprite
  2725.  
  2726. Sprite_Init((sprite_ptr)&button_2,0,DISPLAY_Y+DISPLAY_HEIGHT-6,10,8,0,0,0,0,0,0);
  2727.  
  2728. // extract the bitmaps for the button, there are 2 animation cells
  2729.  
  2730. for (index=0; index<2; index++)
  2731.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&button_2,index,index,1);
  2732.  
  2733. // done with this PCX file so delete memory associated with it
  2734.  
  2735. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2736.  
  2737.  
  2738. // load the imagery for the briefing control buttons
  2739.  
  2740. PCX_Init((pcx_picture_ptr)&image_pcx);
  2741. PCX_Load("blazebt3.pcx", (pcx_picture_ptr)&image_pcx,1);
  2742.  
  2743. // intialize the button sprite
  2744.  
  2745. Sprite_Init((sprite_ptr)&button_3,0,0,42,12,0,0,0,0,0,0);
  2746.  
  2747. // extract the bitmaps for the button, there are 4 animation cells
  2748.  
  2749. for (index=0; index<4; index++)
  2750.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&button_3,index,index,0);
  2751.  
  2752. // done with this PCX file so delete memory associated with it
  2753.  
  2754. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2755.  
  2756. // load the imagery for the display bitmaps
  2757.  
  2758. PCX_Init((pcx_picture_ptr)&image_pcx);
  2759. PCX_Load("blazedis.pcx", (pcx_picture_ptr)&image_pcx,1);
  2760.  
  2761. // intialize the display sprite
  2762.  
  2763. Sprite_Init((sprite_ptr)&displays,DISPLAY_X,DISPLAY_Y+6,72,20,0,0,0,0,0,0);
  2764.  
  2765. // extract the bitmaps for the display bitmaps, there are 2 images
  2766.  
  2767. for (index=0; index<2; index++)
  2768.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&displays,index,index,0);
  2769.  
  2770. // done with this PCX file so delete memory associated with it
  2771.  
  2772. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2773.  
  2774. } // end Load_Icons
  2775.  
  2776. ////////////////////////////////////////////////////////////////////////////
  2777.  
  2778. void Load_Ships(void)
  2779. {
  2780. int index; // looping variable
  2781.  
  2782. // load the imagery for the local ships
  2783.  
  2784. PCX_Init((pcx_picture_ptr)&image_pcx);
  2785. PCX_Load("blazeshl.pcx", (pcx_picture_ptr)&image_pcx,1);
  2786.  
  2787. // load in the imagery for the local gryfon and raptor
  2788.  
  2789. Sprite_Init((sprite_ptr)&gryfon_l,0,0,22,18,0,0,0,0,0,0);
  2790. Sprite_Init((sprite_ptr)&raptor_l,0,0,22,18,0,0,0,0,0,0);
  2791.  
  2792. // there are 32 animation cells per ship
  2793.  
  2794. for (index=0; index<16; index++)
  2795.     {
  2796.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&gryfon_l,index,index%12,index/12);
  2797.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&raptor_l,index,index%12,2+index/12);
  2798.  
  2799.     // these frames are with engines on
  2800.  
  2801.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&gryfon_l,index+16,index%12,4+index/12);
  2802.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&raptor_l,index+16,index%12,4+2+index/12);
  2803.  
  2804.     } // end for index
  2805.  
  2806. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2807.  
  2808. // now the remote gryfon and raptor
  2809.  
  2810. PCX_Init((pcx_picture_ptr)&image_pcx);
  2811. PCX_Load("blazeshr.pcx", (pcx_picture_ptr)&image_pcx,1);
  2812.  
  2813. Sprite_Init((sprite_ptr)&gryfon_r,0,0,22,18,0,0,0,0,0,0);
  2814. Sprite_Init((sprite_ptr)&raptor_r,0,0,22,18,0,0,0,0,0,0);
  2815.  
  2816.  
  2817. // there are 32 animation cells per ship
  2818.  
  2819. for (index=0; index<16; index++)
  2820.     {
  2821.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&gryfon_r,index,index%12,index/12);
  2822.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&raptor_r,index,index%12,2+index/12);
  2823.  
  2824.     // these frames are with engines on
  2825.  
  2826.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&gryfon_r,index+16,index%12,4+index/12);
  2827.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&raptor_r,index+16,index%12,4+2+index/12);
  2828.  
  2829.     } // end for index
  2830.  
  2831. // initialize the player and remote sprites
  2832.  
  2833. Sprite_Init((sprite_ptr)&players_ship,160-11,100-9,22,18,0,0,0,0,0,0);
  2834. Sprite_Init((sprite_ptr)&remotes_ship,0,0,22,18,0,0,0,0,0,0);
  2835.  
  2836. // intialize the starburst
  2837.  
  2838. Sprite_Init((sprite_ptr)&starburst,0,0,22,18,0,0,0,0,0,0);
  2839.  
  2840. // extract the bitmaps for the startburst, there are 6 animation cells
  2841.  
  2842. for (index=0; index<6; index++)
  2843.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&starburst,index,index,8);
  2844.  
  2845. PCX_Delete((pcx_picture_ptr)&image_pcx);
  2846.  
  2847. } // end Load_Ships
  2848.  
  2849. ////////////////////////////////////////////////////////////////////////////
  2850.  
  2851. void Do_Starburst(void)
  2852. {
  2853. int x,y,number,index;
  2854.  
  2855. // select a random number of startb bursts
  2856.  
  2857. number = 2+rand()%3;
  2858.  
  2859. for (index=0; index<number; index++)
  2860.     {
  2861.  
  2862.     // select position for starburst
  2863.  
  2864.     starburst.x=160+(rand()%140);
  2865.     starburst.y=80+rand()%20;
  2866.  
  2867.     Sprite_Under((sprite_ptr)&starburst,video_buffer);
  2868.  
  2869.     // do starburst
  2870.  
  2871.     for (starburst.curr_frame=0; starburst.curr_frame<6; starburst.curr_frame++)
  2872.         {
  2873.         Sprite_Erase((sprite_ptr)&starburst,video_buffer);
  2874.         Sprite_Under((sprite_ptr)&starburst,video_buffer);
  2875.         Sprite_Draw((sprite_ptr)&starburst,video_buffer,1);
  2876.  
  2877.         Time_Delay(1+rand()%2);
  2878.  
  2879.         } // end for starburst frame
  2880.  
  2881.         // erase the starburst
  2882.  
  2883.         Sprite_Erase((sprite_ptr)&starburst,video_buffer);
  2884.  
  2885.     } // end index
  2886.  
  2887. } // end Do_Starburst
  2888.  
  2889. ////////////////////////////////////////////////////////////////////////////
  2890.  
  2891. int Display_Select(int current)
  2892. {
  2893. // this function is used to select between two choices in the display window
  2894.  
  2895. // compute starting position of selection icon based on default selection
  2896.  
  2897. button_2.x = DISPLAY_X + 14 + current*40;
  2898.  
  2899. // scan under selection icon
  2900.  
  2901. Sprite_Under((sprite_ptr)&button_2,video_buffer);
  2902. Sprite_Draw((sprite_ptr)&button_2,video_buffer,1);
  2903.  
  2904. // until user exits process event loop
  2905.  
  2906. while(1)
  2907.      {
  2908.      // get input
  2909.  
  2910.      if (keys_active>0)
  2911.         {
  2912.  
  2913.         // what is user trying to do?
  2914.  
  2915.         if (keyboard_state[MAKE_RIGHT])
  2916.            {
  2917.            if (++current>1)
  2918.               current = 0;
  2919.  
  2920.            Digital_FX_Play(BLZKEY_VOC,2);
  2921.  
  2922.            Time_Delay(1);
  2923.  
  2924.            } // if if right
  2925.  
  2926.  
  2927.         else
  2928.         if (keyboard_state[MAKE_LEFT])
  2929.            {
  2930.            if (--current<0)
  2931.               current = 1;
  2932.  
  2933.            Digital_FX_Play(BLZKEY_VOC,2);
  2934.  
  2935.            Time_Delay(1);
  2936.  
  2937.            } // end if left
  2938.  
  2939.         else
  2940.         if (keyboard_state[MAKE_ESC])
  2941.            {
  2942.            // print that selection was aborted
  2943.  
  2944.            Clear_Display(0);
  2945.  
  2946.            Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  2947.                          "ABORTED...",
  2948.                          video_buffer);
  2949.  
  2950.            Digital_FX_Play(BLZABRT_VOC,1);
  2951.  
  2952.            Time_Delay(5);
  2953.  
  2954.            Clear_Display(0);
  2955.  
  2956.            // return selection aborted
  2957.  
  2958.            return(-1);
  2959.  
  2960.            } // end if esc
  2961.  
  2962.         else
  2963.         if (keyboard_state[MAKE_ENTER])
  2964.            {
  2965.            // carriage return, making selection
  2966.            // illuminate button for a second
  2967.  
  2968.            // draw button down
  2969.  
  2970.            button_2.curr_frame = 1;
  2971.            Sprite_Draw((sprite_ptr)&button_2,video_buffer,1);
  2972.  
  2973.            Digital_FX_Play(BLZKEY_VOC,2);
  2974.  
  2975.            Time_Delay(5);
  2976.  
  2977.            // now draw button up
  2978.  
  2979.            button_2.curr_frame = 0;
  2980.            Sprite_Draw((sprite_ptr)&button_2,video_buffer,1);
  2981.  
  2982.            Clear_Display(0);
  2983.  
  2984.            Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  2985.                          "SELECTION",
  2986.                          video_buffer);
  2987.  
  2988.            Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2+8,0,0,
  2989.                          "RECORDED",
  2990.                          video_buffer);
  2991.  
  2992.            Digital_FX_Play(BLZSEL_VOC,1);
  2993.  
  2994.            Time_Delay(5);
  2995.  
  2996.            Clear_Display(0);
  2997.  
  2998.            // return the selection
  2999.  
  3000.            return(current);
  3001.  
  3002.            } // end if enter
  3003.  
  3004.         // erase selection icon
  3005.  
  3006.         Sprite_Erase((sprite_ptr)&button_2,video_buffer);
  3007.  
  3008.         // compute x position
  3009.  
  3010.         button_2.x = DISPLAY_X + 14 + current*40;
  3011.  
  3012.         // scan under and draw selection icon
  3013.  
  3014.         Sprite_Under((sprite_ptr)&button_2,video_buffer);
  3015.         Sprite_Draw((sprite_ptr)&button_2,video_buffer,1);
  3016.  
  3017.         } // end if kbhit
  3018.  
  3019.      // perform special effects
  3020.  
  3021.      Panel_FX();
  3022.  
  3023.      // wait a bit
  3024.  
  3025.      Time_Delay(1);
  3026.  
  3027.      } // end while
  3028.  
  3029. } // Display_Select
  3030.  
  3031. ///////////////////////////////////////////////////////////////////////////////
  3032.  
  3033. void Copy_Frames(sprite_ptr dest, sprite_ptr source)
  3034. {
  3035. // this function is used to copy the image frames from one sprite to another
  3036.  
  3037. int index; // looping variable
  3038.  
  3039. for (index=0; index<source->num_frames; index++)
  3040.     {
  3041.     // assign next frame
  3042.  
  3043.     dest->frames[index] = source->frames[index];
  3044.  
  3045.     } // end for index
  3046.  
  3047. // set up dest fields
  3048.  
  3049. dest->num_frames = source->num_frames;
  3050. dest->curr_frame = 0;
  3051.  
  3052. } // end Copy_Frames
  3053.  
  3054. /////////////////////////////////////////////////////////////////////////////
  3055.  
  3056. void Shield_Control(int ship,int on)
  3057. {
  3058. // this function is used to activate or de-activate the shields of the player
  3059. // or remote ship
  3060.  
  3061. if (ship==THE_PLAYER)
  3062.    {
  3063.  
  3064.    // which ship does player have?
  3065.  
  3066.    if (players_ship_type==GRYFON_SHIP)
  3067.       {
  3068.       // activating or de-activating shields?
  3069.  
  3070.       if (on)
  3071.          players_shield_color = primary_blue;
  3072.       else
  3073.          players_shield_color = primary_black;
  3074.  
  3075.       } // end if gryfon
  3076.    else
  3077.       {
  3078.       // activating or de-activating shields?
  3079.  
  3080.       if (on)
  3081.          players_shield_color = primary_red;
  3082.       else
  3083.          players_shield_color = primary_black;
  3084.  
  3085.        } // else raptor
  3086.  
  3087.    // set the color
  3088.  
  3089.    Write_Color_Reg(PLAYERS_SHIELD_REG,(RGB_color_ptr)&players_shield_color);
  3090.  
  3091.    // record shield change
  3092.  
  3093.    players_shields = on;
  3094.  
  3095.    } // end if players ship
  3096. else
  3097.    {
  3098.    // must be remote ship
  3099.  
  3100.    // which ship does remote have?
  3101.  
  3102.    if (remotes_ship_type==GRYFON_SHIP)
  3103.       {
  3104.       // activating or de-activating shields?
  3105.  
  3106.       if (on)
  3107.          remotes_shield_color = primary_blue;
  3108.       else
  3109.          remotes_shield_color = primary_black;
  3110.       } // end if gryfon
  3111.    else
  3112.       {
  3113.       // activating or de-activating shields?
  3114.  
  3115.       if (on)
  3116.          remotes_shield_color = primary_red;
  3117.       else
  3118.          remotes_shield_color = primary_black;
  3119.        } // else raptor
  3120.  
  3121.    // set the color
  3122.  
  3123.    Write_Color_Reg(REMOTES_SHIELD_REG,(RGB_color_ptr)&remotes_shield_color);
  3124.  
  3125.    // record shield change
  3126.  
  3127.    remotes_shields = on;
  3128.  
  3129.    } // end must be remote
  3130.  
  3131. } // end Shield_Control
  3132.  
  3133. ///////////////////////////////////////////////////////////////////////////////
  3134.  
  3135. void Erase_Missiles(void)
  3136. {
  3137. // this function erases all the missiles
  3138.  
  3139. int index; // lopping variable
  3140.  
  3141. for (index=0; index<NUM_MISSILES; index++)
  3142.     {
  3143.     // is this missile active and visible
  3144.  
  3145.     if (missiles[index].state == MISS_ACTIVE && missiles[index].visible)
  3146.        {
  3147.        Write_Pixel_DB(missiles[index].sx,missiles[index].sy,missiles[index].back_color);
  3148.        } // end if alive
  3149.  
  3150.     } // end for index
  3151.  
  3152. } // end Erase_Missiles
  3153.  
  3154. /////////////////////////////////////////////////////////////////////////////
  3155.  
  3156. void Under_Missiles(void)
  3157. {
  3158. // this function scans the background under the missiles
  3159.  
  3160. int index,       // looping varible
  3161.     px_window,   // the starting postion of the players window
  3162.     py_window,
  3163.     mx,my;       // local aliases for speed
  3164.  
  3165. // compute starting position of players window so screen mapping can be done
  3166.  
  3167. px_window = players_x - 160 + 11;
  3168. py_window = players_y - 100 + 9;
  3169.  
  3170. for (index=0; index<NUM_MISSILES; index++)
  3171.     {
  3172.     // is this missile active
  3173.  
  3174.     if (missiles[index].state == MISS_ACTIVE)
  3175.        {
  3176.        // remap to screen coordinates
  3177.  
  3178.        mx=missiles[index].sx = (missiles[index].x - px_window);
  3179.        my=missiles[index].sy = (missiles[index].y - py_window);
  3180.  
  3181.        // test if missile is visible on screen?
  3182.  
  3183.        if (mx>=320 || mx <0 || my>=200  || my<0)
  3184.           {
  3185.  
  3186.           // this missile is invisible and has been clipped
  3187.  
  3188.           missiles[index].visible = 0;
  3189.  
  3190.           // process next missile
  3191.  
  3192.           continue;
  3193.  
  3194.           } // end visibility test
  3195.  
  3196.        // scan under missile
  3197.  
  3198.        missiles[index].back_color =
  3199.                       Read_Pixel_DB(mx,my);
  3200.  
  3201.        // set visibility flag
  3202.  
  3203.        missiles[index].visible = 1;
  3204.  
  3205.        } // end if alive
  3206.  
  3207.     } // end for index
  3208.  
  3209. } // end Under_Missiles
  3210.  
  3211. /////////////////////////////////////////////////////////////////////////////
  3212.  
  3213. void Draw_Missiles(void)
  3214. {
  3215. // this function draws all the missiles
  3216. int index; // looping variable
  3217.  
  3218. for (index=0; index<NUM_MISSILES; index++)
  3219.     {
  3220.     // is this missile active and visible
  3221.  
  3222.     if (missiles[index].state == MISS_ACTIVE && missiles[index].visible)
  3223.        {
  3224.  
  3225.        Write_Pixel_DB(missiles[index].sx,missiles[index].sy,missiles[index].color);
  3226.  
  3227.        } // end if alive
  3228.  
  3229.     } // end for index
  3230.  
  3231. } // end Draw_Missiles
  3232.  
  3233. /////////////////////////////////////////////////////////////////////////////
  3234.  
  3235. void Init_Missiles(void)
  3236. {
  3237. // this function resets and intializes all missiles
  3238. int index; // looping variable
  3239.  
  3240. for (index=0; index<NUM_MISSILES; index++)
  3241.     missiles[index].state = MISS_INACTIVE;
  3242.  
  3243. } // Init_Missiles
  3244.  
  3245. ////////////////////////////////////////////////////////////////////////////
  3246.  
  3247. void Move_Missiles(void)
  3248. {
  3249. // this function move all the missiles and performs collision detection
  3250.  
  3251. int index,              // looping variables
  3252.     a_index,
  3253.     miss_x,miss_y;      // speed aliases
  3254.  
  3255. // process each missile
  3256.  
  3257. for (index=0; index<NUM_MISSILES; index++)
  3258.     {
  3259.  
  3260.     // is missile active
  3261.  
  3262.     if (missiles[index].state == MISS_ACTIVE)
  3263.        {
  3264.        // move the missile
  3265.  
  3266.        miss_x = (missiles[index].x += missiles[index].xv);
  3267.        miss_y = (missiles[index].y += missiles[index].yv);
  3268.  
  3269.        // test if a missile has hit an asteroid
  3270.  
  3271.        for (a_index=0; a_index<NUM_ASTEROIDS; a_index++)
  3272.            {
  3273.            // test if asteroid is active
  3274.  
  3275.            if (asteroids[a_index].rock.state==ASTEROID_ACTIVE)
  3276.               {
  3277.               // test for collision
  3278.  
  3279.               if (miss_x >= asteroids[a_index].x &&
  3280.                   miss_y >= asteroids[a_index].y &&
  3281.                   miss_x <= asteroids[a_index].x + asteroids[a_index].rock.width &&
  3282.                   miss_y <= asteroids[a_index].y + asteroids[a_index].rock.height)
  3283.                   {
  3284.                   // kill the asteroid and the missile
  3285.  
  3286.                   asteroids[a_index].rock.state = ASTEROID_INACTIVE;
  3287.  
  3288.                   missiles[index].state = MISS_INACTIVE;
  3289.  
  3290.                   // what kind of asteroid did we have?
  3291.  
  3292.                   switch(asteroids[a_index].type)
  3293.                         {
  3294.  
  3295.                         case ASTEROID_LARGE:
  3296.                              {
  3297.                              // start an explosion at proper place
  3298.  
  3299.                              Start_Explosion(asteroids[a_index].x,
  3300.                                              asteroids[a_index].y,2);
  3301.  
  3302.                              // start one medium and one small asteroid
  3303.                              //  (if possible)
  3304.  
  3305.                              Start_Asteroid(asteroids[a_index].x,
  3306.                                             asteroids[a_index].y,
  3307.                                             ASTEROID_MEDIUM);
  3308.  
  3309.                              Start_Asteroid(asteroids[a_index].x+ASTEROID_LARGE_WIDTH/2,
  3310.                                             asteroids[a_index].y+ASTEROID_LARGE_HEIGHT/2,
  3311.                                             ASTEROID_SMALL);
  3312.  
  3313.                              if (missiles[index].type==PLAYER_MISSILE)
  3314.                                 players_score+=100;
  3315.                              else
  3316.                                 remotes_score+=100;
  3317.  
  3318.  
  3319.                              } break;
  3320.  
  3321.                         case ASTEROID_MEDIUM:
  3322.                              {
  3323.                              // start an explosion at proper place
  3324.  
  3325.                              Start_Explosion(asteroids[a_index].x-2,
  3326.                                              asteroids[a_index].y-2,2);
  3327.  
  3328.  
  3329.                              // start two small asteroids (if possible)
  3330.  
  3331.                              Start_Asteroid(asteroids[a_index].x,
  3332.                                             asteroids[a_index].y,
  3333.                                             ASTEROID_SMALL);
  3334.  
  3335.                              Start_Asteroid(asteroids[a_index].x+ASTEROID_MEDIUM_WIDTH/2,
  3336.                                             asteroids[a_index].y+ASTEROID_MEDIUM_HEIGHT/2,
  3337.                                             ASTEROID_SMALL);
  3338.  
  3339.                              if (missiles[index].type==PLAYER_MISSILE)
  3340.                                 players_score+=50;
  3341.                              else
  3342.                                 remotes_score+=50;
  3343.  
  3344.                              } break;
  3345.  
  3346.                         case ASTEROID_SMALL:
  3347.                              {
  3348.                              // start an explosion at proper place
  3349.  
  3350.                              Start_Explosion(asteroids[a_index].x-8,
  3351.                                              asteroids[a_index].y-8,2);
  3352.  
  3353.                              // start a randomly positioned asteroid of any size
  3354.                              // at the worm hole
  3355.  
  3356.                              Start_Asteroid(WORMHOLE_X,WORMHOLE_Y,rand()%3);
  3357.  
  3358.                              if (missiles[index].type==PLAYER_MISSILE)
  3359.                                 players_score+=25;
  3360.                              else
  3361.                                 remotes_score+=25;
  3362.  
  3363.                              } break;
  3364.  
  3365.                         default:break;
  3366.  
  3367.                         } // end switch
  3368.  
  3369.                   // break inner loop
  3370.  
  3371.                   break;
  3372.  
  3373.                   } // end if collision
  3374.  
  3375.               } // end if active
  3376.  
  3377.            } // end for a_index
  3378.  
  3379.        // test if missiles hit local player
  3380.  
  3381.        if (linked && players_state==ALIVE && missiles[index].type==REMOTE_MISSILE)
  3382.        {
  3383.        if (miss_x>players_x && miss_x < players_x+SHIP_WIDTH &&
  3384.            miss_y>players_y && miss_y < players_y+SHIP_HEIGHT)
  3385.            {
  3386.  
  3387.            // de-activate missile
  3388.  
  3389.            missiles[index].state = MISS_INACTIVE;
  3390.  
  3391.            // were shields up?
  3392.  
  3393.            if (players_shields)
  3394.               {
  3395.               // start explosion
  3396.               Start_Explosion(players_x,players_y,2);
  3397.               } // end if shields up
  3398.            else
  3399.               { // say bye bye!
  3400.  
  3401.               Start_Explosion(players_x,players_y,2);
  3402.               Start_Nova(players_x+SHIP_WIDTH/2,players_y+SHIP_HEIGHT/2);
  3403.  
  3404.               // start local player death sequence
  3405.  
  3406.               Start_Players_Death();
  3407.  
  3408.               } // end if else
  3409.  
  3410.            } // end if local player hit
  3411.  
  3412.        } // end if remote fired this missile
  3413.  
  3414.        // test if missile has hit remote player
  3415.  
  3416.        if (linked && remotes_state==ALIVE && missiles[index].type==PLAYER_MISSILE)
  3417.           {
  3418.           if (miss_x>remotes_x && miss_x < remotes_x+SHIP_WIDTH &&
  3419.               miss_y>remotes_y && miss_y < remotes_y+SHIP_HEIGHT)
  3420.               {
  3421.  
  3422.               // de-activate missile
  3423.  
  3424.               missiles[index].state = MISS_INACTIVE;
  3425.  
  3426.               // were shields up?
  3427.  
  3428.               if (remotes_shields)
  3429.                  {
  3430.                  // start explosion
  3431.                  Start_Explosion(remotes_x,remotes_y,2);
  3432.                  } // end if shields up
  3433.               else
  3434.                  { // say bye bye!
  3435.  
  3436.                  Start_Explosion(remotes_x,remotes_y,2);
  3437.                  Start_Nova(remotes_x+SHIP_WIDTH/2,remotes_y+SHIP_HEIGHT/2);
  3438.  
  3439.                  // start remote death sequence
  3440.  
  3441.                  Start_Remotes_Death();
  3442.  
  3443.                  } // end if else
  3444.  
  3445.               } // end if remote player hit
  3446.  
  3447.           } // end if remote is linked
  3448.  
  3449.        // test if it's hit the edge of the screen or a wall
  3450.  
  3451.        if ( (miss_x >= UNIVERSE_WIDTH+UNIVERSE_BORDER)  ||
  3452.             (miss_x < -UNIVERSE_BORDER)                 ||
  3453.             (miss_y >  UNIVERSE_HEIGHT+UNIVERSE_BORDER) ||
  3454.             (miss_y < -UNIVERSE_BORDER)                 ||
  3455.             (--missiles[index].lifetime < 0))
  3456.           {
  3457.           // de-activate the missile
  3458.  
  3459.           missiles[index].state = MISS_INACTIVE;
  3460.  
  3461.           } // end if off edge of screen
  3462.  
  3463.        // test if this missiles has been terminated in some way, if so update
  3464.        // the active missile variable for the player or remote
  3465.  
  3466.        if (missiles[index].state == MISS_INACTIVE)
  3467.           {
  3468.           // update number of active missiles
  3469.  
  3470.           if (missiles[index].type == PLAYER_MISSILE)
  3471.              players_active_missiles--;
  3472.           else
  3473.           if (missiles[index].type == REMOTE_MISSILE)
  3474.              remotes_active_missiles--;
  3475.  
  3476.           } // end if this missiles was terminated on this cycle
  3477.  
  3478.        } // end if alive
  3479.  
  3480.     } // end for index
  3481.  
  3482. } // end Move_Missiles
  3483.  
  3484. /////////////////////////////////////////////////////////////////////////////
  3485.  
  3486. int Start_Missile(int x,int y,int xv,int yv, int color,int type)
  3487. {
  3488. // this function start a photon missile with the given position and speed
  3489.  
  3490. int index; // looping variable
  3491.  
  3492. // scan for an inactive
  3493.  
  3494. for (index=0; index<NUM_MISSILES; index++)
  3495.     {
  3496.     // is this missile free?
  3497.  
  3498.     if (missiles[index].state == MISS_INACTIVE)
  3499.        {
  3500.        // set up fields
  3501.  
  3502.        missiles[index].state       = MISS_ACTIVE;
  3503.        missiles[index].x           = x;
  3504.        missiles[index].y           = y;
  3505.        missiles[index].sx          = 0;
  3506.        missiles[index].sy          = 0;
  3507.        missiles[index].counter     = 0;
  3508.        missiles[index].threshold   = 0;
  3509.        missiles[index].xv          = xv;
  3510.        missiles[index].yv          = yv;
  3511.        missiles[index].color       = color;
  3512.        missiles[index].back_color  = 0;
  3513.        missiles[index].type        = type;
  3514.        missiles[index].visible     = 0;
  3515.        missiles[index].lifetime    = 30 + rand()%10;
  3516.  
  3517.        // make some sound
  3518.  
  3519.        Digital_FX_Play(BLZLAS_VOC,2);
  3520.  
  3521.        // return success
  3522.  
  3523.        return(1);
  3524.  
  3525.        } // end if found a good one
  3526.  
  3527.     } // end for index
  3528.  
  3529. // must not have found one
  3530.  
  3531. return(0);
  3532.  
  3533. } // end Start_Missile
  3534.  
  3535. /////////////////////////////////////////////////////////////////////////////
  3536.  
  3537. void Start_Players_Death(void)
  3538. {
  3539. // this function starts the players death sequence
  3540.  
  3541. players_xv                  = 0;
  3542. players_yv                  = 0;
  3543. players_engine              = 0;
  3544. players_flame_count         = 0;
  3545. players_gravity             = 0;
  3546. players_shields             = 0;
  3547. players_shield_time         = 0;
  3548. players_cloak               = -1;
  3549. players_state               = DYING;
  3550. players_death_count         = 48;
  3551.  
  3552.  
  3553. debounce_hud                = 0;
  3554. debounce_scan               = 0;
  3555. debounce_cloak              = 0;
  3556. debounce_thrust             = 0;
  3557. debounce_fire               = 0;
  3558. debounce_shields            = 0;
  3559.  
  3560. } // end Start_Players_Death
  3561.  
  3562. //////////////////////////////////////////////////////////////////////////////
  3563.  
  3564. void Reset_Player(void)
  3565. {
  3566. // this function resets the player to his starting position
  3567.  
  3568. players_last_x              = game_start_x[master];
  3569. players_last_y              = game_start_y[master];
  3570. players_x                   = game_start_x[master];
  3571. players_y                   = game_start_y[master];
  3572. players_state               = ALIVE;
  3573.  
  3574. } // end Reset_Player
  3575.  
  3576. //////////////////////////////////////////////////////////////////////////////
  3577.  
  3578. void Reset_Remote(void)
  3579. {
  3580. // this function resets the remote to his starting position
  3581.  
  3582. remotes_last_x              = game_start_x[slave];
  3583. remotes_last_y              = game_start_y[slave];
  3584. remotes_x                   = game_start_x[slave];
  3585. remotes_y                   = game_start_y[slave];
  3586. remotes_state               = ALIVE;
  3587.  
  3588. } // end Reset_Remote
  3589.  
  3590. //////////////////////////////////////////////////////////////////////////////
  3591.  
  3592. void Start_Remotes_Death(void)
  3593. {
  3594. // this function starts the remotes death sequence
  3595.  
  3596. remotes_xv                  = 0;
  3597. remotes_yv                  = 0;
  3598. remotes_engine              = 0;
  3599. remotes_flame_count         = 0;
  3600. remotes_gravity             = 0;
  3601. remotes_shields             = 0;
  3602. remotes_shield_time         = 0;
  3603. remotes_cloak               = -1;
  3604. remotes_state               = DYING;
  3605. remotes_death_count         = 48;
  3606.  
  3607. } // end Start_Remotes_Death
  3608.  
  3609. //////////////////////////////////////////////////////////////////////////////
  3610.  
  3611. void Reset_System(void)
  3612. {
  3613. // this function resets everything so the game can be ran again
  3614. // I hope I didn't leave anything out?
  3615.  
  3616. // player variables
  3617.  
  3618. winner = WINNER_NONE;      // the winner of the game
  3619.  
  3620. players_last_x              = game_start_x[master];
  3621. players_last_y              = game_start_y[master];
  3622. players_x                   = game_start_x[master];
  3623. players_y                   = game_start_y[master];
  3624. players_dx                  = 0;
  3625. players_dy                  = 0;
  3626. players_xv                  = 0;
  3627. players_yv                  = 0;
  3628. players_engine              = 0;
  3629. players_stability           = 8;
  3630. players_flame_count         = 0;
  3631. players_flame_time          = 1;
  3632. players_ship.curr_frame     = 0;
  3633. players_gravity             = 0;
  3634. players_shields             = 0;
  3635. players_shield_time         = 0;
  3636. players_cloak               = -1;
  3637. players_heads               = -1;
  3638. players_comm                = -1;
  3639. players_scanner             = -1;
  3640. players_num_ships           = 3;
  3641. players_shield_strength     = 22000;
  3642. players_energy              = 22000;
  3643. players_score               = 0;
  3644. players_active_missiles     = 0;
  3645. players_state               = ALIVE;
  3646. players_death_count         = 0;
  3647.  
  3648. debounce_hud                = 0;
  3649. debounce_scan               = 0;
  3650. debounce_cloak              = 0;
  3651. debounce_thrust             = 0;
  3652. debounce_fire               = 0;
  3653. debounce_shields            = 0;
  3654.  
  3655. refresh_heads = 0;
  3656.  
  3657. // remote variables
  3658.  
  3659. remotes_last_x          = game_start_x[slave];
  3660. remotes_last_y          = game_start_y[slave];
  3661. remotes_x               = game_start_x[slave];
  3662. remotes_y               = game_start_y[slave];
  3663. remotes_dx              = 0;
  3664. remotes_dy              = 0;
  3665. remotes_xv              = 0;
  3666. remotes_yv              = 0;
  3667. remotes_engine          = 0;
  3668. remotes_stability       = 8;
  3669. remotes_flame_count     = 0;
  3670. remotes_flame_time      = 1;
  3671. remotes_gravity         = 0;
  3672. remotes_shields         = 0;
  3673. remotes_shield_time     = 0;
  3674. remotes_cloak           = -1;
  3675. remotes_heads           = -1;
  3676. remotes_comm            = -1;
  3677. remotes_scanner         = -1;
  3678. remotes_num_ships       = 3;
  3679. remotes_shield_strength = 22000;
  3680. remotes_energy          = 22000;
  3681. remotes_score           = 0;
  3682. remotes_active_missiles = 0;
  3683. remotes_state           = ALIVE;
  3684. remotes_death_count    = 0;
  3685.  
  3686. } // end Reset_System
  3687.  
  3688. ///////////////////////////////////////////////////////////////////////////////
  3689.  
  3690. void Panel_FX(void)
  3691. {
  3692. // this function performs all of the special effects for the control panel
  3693.  
  3694. int index; // lopping variable
  3695.  
  3696. static int panel_counter = 0;  // used to time the color rotation of the panel
  3697.  
  3698. // is it time to update colors?
  3699.  
  3700. if (++panel_counter>2)
  3701.    {
  3702.    // reset counter
  3703.  
  3704.    panel_counter=0;
  3705.  
  3706.    // do animation to colors
  3707.  
  3708.    Read_Color_Reg(END_PANEL_REG, (RGB_color_ptr)&color_1);
  3709.  
  3710.    for (index=END_PANEL_REG; index>START_PANEL_REG; index--)
  3711.        {
  3712.        // read the (i-1)th register
  3713.  
  3714.        Read_Color_Reg(index-1, (RGB_color_ptr)&color_2);
  3715.  
  3716.        // assign it to the ith
  3717.  
  3718.        Write_Color_Reg(index, (RGB_color_ptr)&color_2);
  3719.  
  3720.        } // end rotate loop
  3721.  
  3722.     // place the value of the first color register into the last to
  3723.     // complete the rotation
  3724.  
  3725.     Write_Color_Reg(START_PANEL_REG, (RGB_color_ptr)&color_1);
  3726.  
  3727.    } // end if time
  3728.  
  3729. } // end Panel_FX
  3730.  
  3731. ////////////////////////////////////////////////////////////////////////////////
  3732.  
  3733. void Start_Explosion(int x,int y,int speed)
  3734. {
  3735. // this function stars a generic explosion
  3736.  
  3737. int index;  // looping variable
  3738.  
  3739. // scan for a useable explosion
  3740.  
  3741. for (index=0; index<NUM_EXPLOSIONS; index++)
  3742.     {
  3743.  
  3744.     if (explosions[index].state == EXPLOSION_INACTIVE)
  3745.        {
  3746.  
  3747.        // set up fields
  3748.  
  3749.        explosions[index].state       = EXPLOSION_ACTIVE;
  3750.        explosions[index].x           = 0; // screen coordinates
  3751.        explosions[index].y           = 0;
  3752.        explosions[index].counter_2   = x; // the counters will be used as universe
  3753.        explosions[index].counter_3   = y; // coordinates
  3754.  
  3755.  
  3756.        explosions[index].curr_frame  = 0;
  3757.        explosions[index].threshold_1 = speed;
  3758.        explosions[index].counter_1   = 0;
  3759.  
  3760.        // make some sound
  3761.  
  3762.        Digital_FX_Play(BLZEXP1_VOC,1);
  3763.  
  3764.        break; // exit loop
  3765.  
  3766.        } // end if found a good one
  3767.  
  3768.     } // end for index
  3769.  
  3770. } // end Start_Explosion
  3771.  
  3772. /////////////////////////////////////////////////////////////////////////////
  3773.  
  3774. void Under_Explosions(void)
  3775. {
  3776.  
  3777. // this function scans under the explosions
  3778.  
  3779.  
  3780. int index,     // looping index
  3781.     px_window, // the starting postion of the players window
  3782.     py_window;
  3783.  
  3784. // compute starting position of players window so screen mapping can be done
  3785.  
  3786. px_window = players_x - 160+11;
  3787. py_window = players_y - 100+9;
  3788.  
  3789. // scan for a running explosions
  3790.  
  3791. for (index=0; index<NUM_EXPLOSIONS; index++)
  3792.     {
  3793.  
  3794.     if (explosions[index].state == EXPLOSION_ACTIVE)
  3795.        {
  3796.  
  3797.        // postion explosion correctly on view screen, note this is very similar
  3798.        // to what we will do in 3-D when we translate all the objects in the
  3799.        // universe to the viewer position, note counter_2 and counter_3
  3800.        // in the sprite structure are used as universe or world x,y
  3801.  
  3802.        explosions[index].x = (explosions[index].counter_2-px_window);
  3803.        explosions[index].y = (explosions[index].counter_3-py_window);
  3804.  
  3805.        Sprite_Under_Clip((sprite_ptr)&explosions[index],double_buffer);
  3806.  
  3807.        } // end if found a good one
  3808.  
  3809.     } // end for index
  3810.  
  3811. } // end Under_Explosions
  3812.  
  3813. /////////////////////////////////////////////////////////////////////////////
  3814.  
  3815. void Erase_Explosions(void)
  3816. {
  3817. // this function erases all the current explosions
  3818.  
  3819. int index;
  3820.  
  3821. // scan for a useable explosion
  3822.  
  3823. for (index=0; index<NUM_EXPLOSIONS; index++)
  3824.     {
  3825.  
  3826.     if (explosions[index].state == EXPLOSION_ACTIVE)
  3827.        {
  3828.        Sprite_Erase_Clip((sprite_ptr)&explosions[index],double_buffer);
  3829.  
  3830.        } // end if found a good one
  3831.  
  3832.     } // end for index
  3833.  
  3834. } // end Erase_Explosions
  3835.  
  3836. /////////////////////////////////////////////////////////////////////////////
  3837.  
  3838. void Draw_Explosions(void)
  3839. {
  3840. // this function draws the explosion
  3841.  
  3842. int index; // looping variable
  3843.  
  3844. // scan for a useable explosion
  3845.  
  3846. for (index=0; index<NUM_EXPLOSIONS; index++)
  3847.     {
  3848.  
  3849.     // make sure this explosion is alive
  3850.  
  3851.     if (explosions[index].state == EXPLOSION_ACTIVE)
  3852.        {
  3853.  
  3854.        Sprite_Draw_Clip((sprite_ptr)&explosions[index],double_buffer,1);
  3855.  
  3856.        } // end if found a good one
  3857.  
  3858.     } // end for index
  3859.  
  3860. } // end Draw_Explosions
  3861.  
  3862. /////////////////////////////////////////////////////////////////////////////
  3863.  
  3864. void Animate_Explosions(void)
  3865. {
  3866. // this function aniamtes the explosions
  3867.  
  3868. int index;  // looping index
  3869.  
  3870. // scan for a useable explosion
  3871.  
  3872. for (index=0; index<NUM_EXPLOSIONS; index++)
  3873.     {
  3874.     // test if explosion is active
  3875.  
  3876.     if (explosions[index].state == EXPLOSION_ACTIVE)
  3877.        {
  3878.        // test if it's time to change frames
  3879.  
  3880.        if (++explosions[index].counter_1 >= explosions[index].threshold_1)
  3881.           {
  3882.           // is the explosion over?
  3883.  
  3884.           if (++explosions[index].curr_frame == NUM_EXPLOSION_FRAMES)
  3885.              explosions[index].state = EXPLOSION_INACTIVE;
  3886.  
  3887.           // reset animation clock for future
  3888.  
  3889.           explosions[index].counter_1 = 0;
  3890.  
  3891.           } // end if time to change frames
  3892.  
  3893.        } // end if found a good one
  3894.  
  3895.     } // end for index
  3896.  
  3897. } // end Animate_Explosions
  3898.  
  3899. //////////////////////////////////////////////////////////////////////////////
  3900.  
  3901. void Init_Explosions(void)
  3902. {
  3903. // clear out the states of all explosions
  3904.  
  3905. int index; // looping variable
  3906.  
  3907. for (index=0; index<NUM_EXPLOSIONS; index++)
  3908.     explosions[index].state = EXPLOSION_INACTIVE;
  3909.  
  3910. } // Init_Explosions
  3911.  
  3912. /////////////////////////////////////////////////////////////////////////////
  3913.  
  3914. void Load_Wormhole(void)
  3915. {
  3916. // this function loads in the imagery for the worm hole
  3917.  
  3918. int index; // looping variable
  3919.  
  3920. // load the imagery for the worm hole
  3921.  
  3922. PCX_Init((pcx_picture_ptr)&image_pcx);
  3923. PCX_Load("blazewrm.pcx", (pcx_picture_ptr)&image_pcx,1);
  3924.  
  3925. // initialize the wormhole sprite
  3926.  
  3927. Sprite_Init((sprite_ptr)&wormhole,0,0,26,22,0,0,0,0,0,0);
  3928.  
  3929. // extract the animation frames
  3930.  
  3931. for (index=0; index<NUM_WORMHOLE_FRAMES; index++)
  3932.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&wormhole,index,index,0);
  3933.  
  3934. PCX_Delete((pcx_picture_ptr)&image_pcx);
  3935.  
  3936. } // end Load_Wormhole
  3937.  
  3938. /////////////////////////////////////////////////////////////////////////////
  3939.  
  3940. void Init_Wormhole(void)
  3941. {
  3942. // this resets all the worm hole parameters
  3943.  
  3944.  
  3945. // set screen coordinates to 0
  3946.  
  3947. wormhole.x = 0;
  3948. wormhole.y = 0;
  3949.  
  3950. // set universe coordinates to proper position
  3951.  
  3952. wormhole.counter_2 = WORMHOLE_X; // note the counters are being used for
  3953. wormhole.counter_3 = WORMHOLE_Y; // universe positions
  3954.  
  3955. // reset the frame counter
  3956.  
  3957. wormhole.curr_frame = 0;
  3958.  
  3959. // these will be used to time animation
  3960.  
  3961. wormhole.counter_1 = 0;
  3962. wormhole.threshold_1 = 2;
  3963.  
  3964. } // end Init_Wormhole
  3965.  
  3966. /////////////////////////////////////////////////////////////////////////////
  3967.  
  3968. void Under_Wormhole(void)
  3969. {
  3970.  
  3971. // this function scans under the wormhole
  3972.  
  3973.  
  3974. int px_window, // the starting postion of the players window
  3975.     py_window;
  3976.  
  3977. // compute starting position of players window so screen mapping can be done
  3978.  
  3979. px_window = players_x - 160+11;
  3980. py_window = players_y - 100+9;
  3981.  
  3982. // translate wormhole to screen coordinates
  3983.  
  3984. wormhole.x = (wormhole.counter_2-px_window);
  3985. wormhole.y = (wormhole.counter_3-py_window);
  3986.  
  3987. Sprite_Under_Clip((sprite_ptr)&wormhole,double_buffer);
  3988.  
  3989. } // end Under_Wormhole
  3990.  
  3991. /////////////////////////////////////////////////////////////////////////////
  3992.  
  3993. void Erase_Wormhole(void)
  3994. {
  3995. // this function erase the wormhole
  3996.  
  3997. Sprite_Erase_Clip((sprite_ptr)&wormhole,double_buffer);
  3998.  
  3999. } // end Erase_Wormhole
  4000.  
  4001. /////////////////////////////////////////////////////////////////////////////
  4002.  
  4003. void Draw_Wormhole(void)
  4004. {
  4005. // this function draws the wormhole
  4006.  
  4007. Sprite_Draw_Clip((sprite_ptr)&wormhole,double_buffer,1);
  4008.  
  4009. } // end Draw_Wormhole
  4010.  
  4011. /////////////////////////////////////////////////////////////////////////////
  4012.  
  4013. void Animate_Wormhole(void)
  4014. {
  4015. // this function animates the wormhole
  4016.  
  4017. if (++wormhole.counter_1 >= wormhole.threshold_1)
  4018.    {
  4019.    // time to reset frame counter?
  4020.  
  4021.    if (++wormhole.curr_frame == NUM_WORMHOLE_FRAMES)
  4022.        wormhole.curr_frame = 0;
  4023.  
  4024.     // reset animation clock for future
  4025.  
  4026.     wormhole.counter_1 = 0;
  4027.  
  4028.     } // end if time to change frames
  4029.  
  4030. } // end Animate_Wormhole
  4031.  
  4032. /////////////////////////////////////////////////////////////////////////////
  4033.  
  4034. void Load_Fuel_Cells(void)
  4035. {
  4036. // this function loads in the imagery for the fuel cells
  4037.  
  4038. int index,  // looping variable
  4039.     frames; // looping variable
  4040.  
  4041. // load the imagery for the fuel cells
  4042.  
  4043. PCX_Init((pcx_picture_ptr)&image_pcx);
  4044. PCX_Load("blazeful.pcx", (pcx_picture_ptr)&image_pcx,1);
  4045.  
  4046. // initialize the fuel cells sprite and load bitmaps
  4047.  
  4048. for (index=0; index<NUM_FUEL_CELLS; index++)
  4049.     {
  4050.  
  4051.     Sprite_Init((sprite_ptr)&fuel_cells[index],0,0,20,18,0,0,0,0,0,0);
  4052.  
  4053.     // extract the animation frames
  4054.  
  4055.     for (frames=0; frames<NUM_FUEL_FRAMES; frames++)
  4056.         PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  4057.                        (sprite_ptr)&fuel_cells[index],frames,frames,0);
  4058.  
  4059.     } // end for index
  4060.  
  4061. PCX_Delete((pcx_picture_ptr)&image_pcx);
  4062.  
  4063. } // end Load_Fuel_Cells
  4064.  
  4065. /////////////////////////////////////////////////////////////////////////////
  4066.  
  4067. void Init_Fuel_Cells(void)
  4068. {
  4069. // this resets all the fuel cell parameters
  4070.  
  4071. int index; // looping variable
  4072.  
  4073. for (index=0; index<NUM_FUEL_CELLS; index++)
  4074.     {
  4075.  
  4076.     // set state
  4077.  
  4078.     fuel_cells[index].state = FUEL_CELL_ACTIVE;
  4079.  
  4080.     // set screen coordinates to 0
  4081.  
  4082.     fuel_cells[index].x = 0;
  4083.     fuel_cells[index].y = 0;
  4084.  
  4085.     // set universe coordinates to random position
  4086.  
  4087.     fuel_cells[index].counter_2 = 200+rand()%(UNIVERSE_WIDTH-400);
  4088.     fuel_cells[index].counter_3 = 200+rand()%(UNIVERSE_HEIGHT-400);
  4089.  
  4090.     // reset the frame counter
  4091.  
  4092.     fuel_cells[index].curr_frame = 0;
  4093.  
  4094.     // these will be used to time animation
  4095.  
  4096.     fuel_cells[index].counter_1 = 0;
  4097.     fuel_cells[index].threshold_1 = 2;
  4098.  
  4099.     } // end index
  4100.  
  4101. } // end Init_Fuel_Cells
  4102.  
  4103. /////////////////////////////////////////////////////////////////////////////
  4104.  
  4105. void Under_Fuel_Cells(void)
  4106. {
  4107. // this function scans under the Fuel cells
  4108.  
  4109.  
  4110. int px_window, // the starting postion of the players window
  4111.     py_window,
  4112.     index;     // looping variable
  4113.  
  4114. // compute starting position of players window so screen mapping can be done
  4115.  
  4116. px_window = players_x - 160+11;
  4117. py_window = players_y - 100+9;
  4118.  
  4119. // process each fuel cell
  4120.  
  4121. for (index=0; index<NUM_FUEL_CELLS; index++)
  4122.     {
  4123.     // test if fuel cell is active
  4124.  
  4125.     if (fuel_cells[index].state == FUEL_CELL_ACTIVE)
  4126.        {
  4127.        // translate Fuelcells to screen coordinates
  4128.  
  4129.        fuel_cells[index].x = (fuel_cells[index].counter_2-px_window);
  4130.        fuel_cells[index].y = (fuel_cells[index].counter_3-py_window);
  4131.  
  4132.        Sprite_Under_Clip((sprite_ptr)&fuel_cells[index],double_buffer);
  4133.  
  4134.        } // end fi active
  4135.  
  4136.     } // end for index
  4137.  
  4138. } // end Under_Fuel_Cells
  4139.  
  4140. /////////////////////////////////////////////////////////////////////////////
  4141.  
  4142. void Erase_Fuel_Cells(void)
  4143. {
  4144. // this function erase the Fuelcells
  4145.  
  4146. int index; // looping variable
  4147.  
  4148. for (index=0; index<NUM_FUEL_CELLS; index++)
  4149.     {
  4150.     // test if fuel cell is active
  4151.  
  4152.     if (fuel_cells[index].state == FUEL_CELL_ACTIVE)
  4153.        {
  4154.  
  4155.        Sprite_Erase_Clip((sprite_ptr)&fuel_cells[index],double_buffer);
  4156.  
  4157.        } // end if active
  4158.  
  4159.     } // end for index
  4160.  
  4161. } // end Erase_Fuel_Cells
  4162.  
  4163. /////////////////////////////////////////////////////////////////////////////
  4164.  
  4165. void Draw_Fuel_Cells(void)
  4166. {
  4167. // this function draws the Fuel cells
  4168.  
  4169. int index; // looping variable
  4170.  
  4171. for (index=0; index<NUM_FUEL_CELLS; index++)
  4172.     {
  4173.     // test if fuel cell is active
  4174.  
  4175.     if (fuel_cells[index].state == FUEL_CELL_ACTIVE)
  4176.        {
  4177.  
  4178.        Sprite_Draw_Clip((sprite_ptr)&fuel_cells[index],double_buffer,1);
  4179.  
  4180.        } // end if active
  4181.  
  4182.     } // end for index
  4183.  
  4184. } // end Draw_Fuel_Cells
  4185.  
  4186. /////////////////////////////////////////////////////////////////////////////
  4187.  
  4188. void Animate_Fuel_Cells(void)
  4189. {
  4190. // this function animates the fuel cells and test for collision
  4191.  
  4192. int index; // looping variable
  4193.  
  4194. for (index=0; index<NUM_FUEL_CELLS; index++)
  4195.     {
  4196.     // test if fuel cell is active
  4197.  
  4198.     if (fuel_cells[index].state == FUEL_CELL_ACTIVE)
  4199.        {
  4200.        // move cell to right
  4201.  
  4202.        if (++fuel_cells[index].counter_2 > (UNIVERSE_WIDTH+UNIVERSE_BORDER))
  4203.           fuel_cells[index].counter_2 = -UNIVERSE_BORDER;
  4204.  
  4205.        // perform animation
  4206.  
  4207.        if (++fuel_cells[index].counter_1 >= fuel_cells[index].threshold_1)
  4208.           {
  4209.           // time to reset frame counter?
  4210.  
  4211.           if (++fuel_cells[index].curr_frame == NUM_FUEL_FRAMES)
  4212.               fuel_cells[index].curr_frame = 0;
  4213.  
  4214.            // reset animation clock for future
  4215.  
  4216.            fuel_cells[index].counter_1 = 0;
  4217.  
  4218.           } // end if time to change frames
  4219.  
  4220.        } // end if active
  4221.  
  4222.     } // end for index
  4223.  
  4224. } // end Animate_Fuel_Cells
  4225.  
  4226. //////////////////////////////////////////////////////////////////////////////
  4227.  
  4228. void Load_Alien(void)
  4229. {
  4230. // this function loads in the imagery for the alien
  4231.  
  4232. int index; // looping variable
  4233.  
  4234. // load the imagery for the alien
  4235.  
  4236. PCX_Init((pcx_picture_ptr)&image_pcx);
  4237. PCX_Load("blazealn.pcx", (pcx_picture_ptr)&image_pcx,1);
  4238.  
  4239. // initialize the alien sprite
  4240.  
  4241. Sprite_Init((sprite_ptr)&alien.body,0,0,14,8,0,0,0,0,0,0);
  4242.  
  4243. // extract the animation frames
  4244.  
  4245. for (index=0; index<NUM_ALIEN_FRAMES; index++)
  4246.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,(sprite_ptr)&alien.body,index,index,0);
  4247.  
  4248.  
  4249. PCX_Delete((pcx_picture_ptr)&image_pcx);
  4250.  
  4251. } // end Load_Alien
  4252.  
  4253. /////////////////////////////////////////////////////////////////////////////
  4254.  
  4255. void Init_Alien(void)
  4256. {
  4257. // this resets all the alien parameters
  4258.  
  4259. // set screen coordinates to 0
  4260.  
  4261. alien.body.x = 0;
  4262. alien.body.y = 0;
  4263.  
  4264. // set universe coordinates to proper position
  4265.  
  4266. alien.x = 0;
  4267. alien.y = 0;
  4268.  
  4269. // reset the frame counter
  4270.  
  4271. alien.body.curr_frame = 0;
  4272.  
  4273. // these will be used to time animation
  4274.  
  4275. alien.body.counter_1 = 0;
  4276. alien.body.threshold_1 = 2;
  4277.  
  4278. // set state to active
  4279.  
  4280. alien.state = ALIEN_INACTIVE;
  4281.  
  4282. } // end Init_Alien
  4283.  
  4284. //////////////////////////////////////////////////////////////////////////////
  4285.  
  4286. void Alien_Control(void)
  4287. {
  4288. // this function will be called every cycle and decide if an alien
  4289. // will start up
  4290.  
  4291. // make sure alien is dead
  4292.  
  4293. if (alien.state==ALIEN_INACTIVE)
  4294.    {
  4295.    // throw a coin
  4296.  
  4297.    if ((rand()%ALIEN_ODDS)==1)
  4298.       {
  4299.       // position alien and set appropriate fields
  4300.  
  4301.       alien.body.x = 0; // screen coords
  4302.       alien.body.y = 0;
  4303.  
  4304.       // start alien from wormhole (universe coords)
  4305.  
  4306.       alien.x = WORMHOLE_X; // note the counters are being used for
  4307.       alien.y = WORMHOLE_Y; // universe positions
  4308.  
  4309.       // reset the frame counter
  4310.  
  4311.       alien.body.curr_frame = 0;
  4312.  
  4313.       // this will be used to time animation
  4314.  
  4315.       alien.body.counter_1   = 0;
  4316.       alien.body.threshold_1 = 2;
  4317.  
  4318.       // set state to random to start with
  4319.  
  4320.       alien.state = ALIEN_RANDOM;
  4321.  
  4322.       // select a random direction
  4323.  
  4324.       alien.xv = -4 + rand()%8;
  4325.       alien.yv = -4 + rand()%8;
  4326.  
  4327.       // counter 2 will be used to track how long to stay in a state
  4328.  
  4329.       alien.body.counter_2 = 50;
  4330.  
  4331.       } // end if start one
  4332.  
  4333.    } // end if dead
  4334.  
  4335. } // end Alien_Control
  4336.  
  4337. /////////////////////////////////////////////////////////////////////////////
  4338.  
  4339. void Under_Alien(void)
  4340. {
  4341. // this function scans under the alien
  4342.  
  4343. int px_window, // the starting postion of the players window
  4344.     py_window;
  4345.  
  4346. if (alien.state!=ALIEN_INACTIVE)
  4347.    {
  4348.    // compute starting position of players window so screen
  4349.    // mapping can be done
  4350.  
  4351.    px_window = players_x - 160+11;
  4352.    py_window = players_y - 100+9;
  4353.  
  4354.    // translate alien to screen coordinates
  4355.  
  4356.    alien.body.x = (alien.x-px_window);
  4357.    alien.body.y = (alien.y-py_window);
  4358.  
  4359.    // perform scan in screen coords
  4360.  
  4361.    Sprite_Under_Clip((sprite_ptr)&alien.body,double_buffer);
  4362.  
  4363.    } // end if alien alive
  4364.  
  4365. } // end Under_Alien
  4366.  
  4367. /////////////////////////////////////////////////////////////////////////////
  4368.  
  4369. void Erase_Alien(void)
  4370. {
  4371. // this function erases the alien
  4372.  
  4373. if (alien.state!=ALIEN_INACTIVE)
  4374.     Sprite_Erase_Clip((sprite_ptr)&alien.body,double_buffer);
  4375.  
  4376. } // end Erase_Alien
  4377.  
  4378. /////////////////////////////////////////////////////////////////////////////
  4379.  
  4380. void Draw_Alien(void)
  4381. {
  4382. // this function draws the alien
  4383.  
  4384. if (alien.state!=ALIEN_INACTIVE)
  4385.    Sprite_Draw_Clip((sprite_ptr)&alien.body,double_buffer,1);
  4386.  
  4387. } // end Draw_Alien
  4388.  
  4389. /////////////////////////////////////////////////////////////////////////////
  4390.  
  4391. void Move_Alien(void)
  4392. {
  4393. // this function moves the alien (if there is one)
  4394.  
  4395. if (alien.state!=ALIEN_INACTIVE)
  4396.    {
  4397.  
  4398.    // what state is alien in?
  4399.  
  4400.    switch(alien.state)
  4401.          {
  4402.  
  4403.          case ALIEN_RANDOM:
  4404.               {
  4405.  
  4406.               // move alien in direction
  4407.  
  4408.               alien.x+=alien.xv;
  4409.               alien.y+=alien.yv;
  4410.  
  4411.               } break;
  4412.  
  4413.          case ALIEN_CHASE_PLAYER:
  4414.               {
  4415.  
  4416.  
  4417.               } break;
  4418.  
  4419.          case ALIEN_CHASE_REMOTE:
  4420.               {
  4421.  
  4422.  
  4423.               } break;
  4424.  
  4425.           default:break;
  4426.  
  4427.          } // end switch
  4428.  
  4429.    // decrement state counter
  4430.  
  4431.    if (--alien.body.counter_2<=0)
  4432.       {
  4433.       // select a new state
  4434.  
  4435.       alien.state = ALIEN_RANDOM;   // change this line later
  4436.  
  4437.       // set up new state
  4438.  
  4439.       switch(alien.state)
  4440.             {
  4441.             case ALIEN_RANDOM:
  4442.                  {
  4443.                  // select new random direction and state time
  4444.  
  4445.                  alien.xv = -4 + rand()%8;
  4446.                  alien.yv = -4 + rand()%8;
  4447.  
  4448.                  // counter 2 will be used to track how long to stay in a state
  4449.  
  4450.                  alien.body.counter_2 = 25+rand()%75;
  4451.  
  4452.                  } break;
  4453.  
  4454.             case ALIEN_CHASE_PLAYER:
  4455.                  {
  4456.                  // this bud's for you!
  4457.                  } break;
  4458.  
  4459.             case ALIEN_CHASE_REMOTE:
  4460.                  {
  4461.                  // this is an exercise
  4462.                  } break;
  4463.  
  4464.             default:break;
  4465.  
  4466.             } // end switch
  4467.  
  4468.       } // end if time to select a new state
  4469.  
  4470.    // animate alien
  4471.  
  4472.    if (++alien.body.counter_1 >=alien.body.threshold_1)
  4473.       {
  4474.       // change animation frames
  4475.  
  4476.       if (++alien.body.curr_frame==NUM_ALIEN_FRAMES)
  4477.          alien.body.curr_frame = 0;
  4478.  
  4479.       // reset animation counter
  4480.  
  4481.       alien.body.counter_1 = 0;
  4482.  
  4483.       } // end if time to animate
  4484.  
  4485.    // do collision detection
  4486.  
  4487.    if ((alien.x>UNIVERSE_WIDTH+UNIVERSE_BORDER)  ||
  4488.        (alien.x<-UNIVERSE_BORDER)                ||
  4489.        (alien.y>UNIVERSE_HEIGHT+UNIVERSE_BORDER) ||
  4490.        (alien.y<-UNIVERSE_BORDER))
  4491.       {
  4492.       // kill alien
  4493.  
  4494.       alien.state = ALIEN_INACTIVE;
  4495.  
  4496.       } // end if alien has warped off universe edge
  4497.  
  4498.    } // end if alien alive
  4499.  
  4500. } // end Move_Alien
  4501.  
  4502. ///////////////////////////////////////////////////////////////////////////////
  4503.  
  4504. void Load_Heads(void)
  4505. {
  4506. // this function loads various icons for the heads up display
  4507.  
  4508. int index; // looping variable
  4509.  
  4510. // load the imagery for the icons for display
  4511.  
  4512. PCX_Init((pcx_picture_ptr)&image_pcx);
  4513. PCX_Load("blazehu1.pcx", (pcx_picture_ptr)&image_pcx,1);
  4514.  
  4515. // intialize the button sprite
  4516.  
  4517. Sprite_Init((sprite_ptr)&heads_text,0,0,34,6,0,0,0,0,0,0);
  4518.  
  4519. // extract the bitmaps for heads up text
  4520.  
  4521. for (index=0; index<7; index++)
  4522.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  4523.                    (sprite_ptr)&heads_text,index,index,0);
  4524.  
  4525. // delete pcx file
  4526.  
  4527. PCX_Delete((pcx_picture_ptr)&image_pcx);
  4528.  
  4529. // load the imagery for the icons for display
  4530.  
  4531. PCX_Init((pcx_picture_ptr)&image_pcx);
  4532. PCX_Load("blazehu2.pcx", (pcx_picture_ptr)&image_pcx,1);
  4533.  
  4534. // intialize the button sprite
  4535.  
  4536. Sprite_Init((sprite_ptr)&heads_numbers,0,0,8,6,0,0,0,0,0,0);
  4537.  
  4538. // extract the bitmaps for heads up text
  4539.  
  4540. for (index=0; index<7; index++)
  4541.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  4542.                    (sprite_ptr)&heads_numbers,index,index,0);
  4543.  
  4544. // delete pcx file
  4545.  
  4546. PCX_Delete((pcx_picture_ptr)&image_pcx);
  4547.  
  4548. // load the imagery for the icons for display
  4549.  
  4550. PCX_Init((pcx_picture_ptr)&image_pcx);
  4551. PCX_Load("blazehu1.pcx", (pcx_picture_ptr)&image_pcx,1);
  4552.  
  4553. // intialize the button sprite
  4554.  
  4555. Sprite_Init((sprite_ptr)&heads_gauge,0,0,34,6,0,0,0,0,0,0);
  4556.  
  4557. // extract the bitmaps for heads up gauges
  4558.  
  4559. for (index=0; index<23; index++)
  4560.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  4561.                    (sprite_ptr)&heads_gauge,index,index%9,2+index/9);
  4562.  
  4563. // delete pcx file
  4564.  
  4565. PCX_Delete((pcx_picture_ptr)&image_pcx);
  4566.  
  4567. } // end Load_Heads
  4568.  
  4569. ////////////////////////////////////////////////////////////////////////////
  4570.  
  4571. void Init_Heads(void)
  4572. {
  4573. // do nothing for now
  4574.  
  4575.  
  4576. } // end Init_Heads
  4577.  
  4578. ////////////////////////////////////////////////////////////////////////////
  4579.  
  4580. void Draw_Heads(void)
  4581. {
  4582. // this function draws the heads up display during the tmie when
  4583. // the game background can be modified
  4584.  
  4585. int index; // looping variable
  4586.  
  4587. heads_text.x = LEFT_HEADS_TEXT_X;
  4588. heads_text.y = LEFT_HEADS_TEXT_Y;
  4589.  
  4590. // draw the left most messages first
  4591.  
  4592. heads_text.curr_frame = HEADS_CLOAK;
  4593.  
  4594. for (index=0; index<4; index++)
  4595.     {
  4596.     Sprite_Draw((sprite_ptr)&heads_text,double_buffer,0);
  4597.  
  4598.     // move down a row
  4599.  
  4600.     heads_text.y+=8;
  4601.  
  4602.     // select next message
  4603.  
  4604.     heads_text.curr_frame++;
  4605.  
  4606.     } //  end for index
  4607.  
  4608. // now draw buttons and numbers
  4609.  
  4610. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4611. heads_numbers.y = LEFT_HEADS_TEXT_Y;
  4612.  
  4613. // draw cloaked button
  4614.  
  4615. if (players_cloak==1)
  4616.    {
  4617.    heads_numbers.curr_frame=2;
  4618.    Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4619.    }
  4620. else
  4621.    {
  4622.    heads_numbers.curr_frame=1;
  4623.    Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4624.    } // end else
  4625.  
  4626. // draw scanner enable
  4627.  
  4628. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4629. heads_numbers.y = LEFT_HEADS_TEXT_Y+8;
  4630.  
  4631. if (players_scanner==1)
  4632.    {
  4633.    heads_numbers.curr_frame=2;
  4634.    Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4635.    }
  4636. else
  4637.    {
  4638.    heads_numbers.curr_frame=1;
  4639.    Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4640.    } // end else
  4641.  
  4642. // draw communications
  4643.  
  4644. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4645. heads_numbers.y = LEFT_HEADS_TEXT_Y+16;
  4646.  
  4647. if (linked)
  4648.    {
  4649.    heads_numbers.curr_frame=2;
  4650.    Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4651.    }
  4652. else
  4653.    {
  4654.    heads_numbers.curr_frame=1;
  4655.    Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4656.    } // end else
  4657.  
  4658. // draw number of ships
  4659.  
  4660. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4661. heads_numbers.y = LEFT_HEADS_TEXT_Y+24;
  4662.  
  4663. heads_numbers.curr_frame=3+players_num_ships;
  4664. Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4665.  
  4666. // now draw right most messages
  4667.  
  4668. heads_text.x = RIGHT_HEADS_TEXT_X;
  4669. heads_text.y = RIGHT_HEADS_TEXT_Y;
  4670.  
  4671. heads_text.curr_frame = HEADS_ENERGY;
  4672.  
  4673. for (index=0; index<2; index++)
  4674.     {
  4675.     Sprite_Draw((sprite_ptr)&heads_text,double_buffer,0);
  4676.  
  4677.     // move down a row
  4678.  
  4679.     heads_text.y+=8;
  4680.  
  4681.     // select next message
  4682.  
  4683.     heads_text.curr_frame++;
  4684.  
  4685.     } //  end for index
  4686.  
  4687. // draw gauges
  4688.  
  4689. heads_gauge.x = RIGHT_HEADS_TEXT_X+40;
  4690. heads_gauge.y = RIGHT_HEADS_TEXT_Y;
  4691.  
  4692. // compute proper frame
  4693.  
  4694. heads_gauge.curr_frame = 22 - (players_energy/1000);
  4695.  
  4696. // draw the energy level
  4697.  
  4698. Sprite_Draw((sprite_ptr)&heads_gauge,double_buffer,0);
  4699.  
  4700. heads_gauge.x = RIGHT_HEADS_TEXT_X+40;
  4701. heads_gauge.y = RIGHT_HEADS_TEXT_Y+8;
  4702.  
  4703. // compute proper frame
  4704.  
  4705. heads_gauge.curr_frame = 22 - (players_shield_strength/1000);
  4706.  
  4707. // draw the shield strength
  4708.  
  4709. Sprite_Draw((sprite_ptr)&heads_gauge,double_buffer,0);
  4710.  
  4711. } // end Draw_Heads
  4712.  
  4713. ////////////////////////////////////////////////////////////////////////////
  4714.  
  4715. void Erase_Heads(void)
  4716. {
  4717.  
  4718. // this function erases the heads up display during the time when
  4719. // the game background can be modified
  4720.  
  4721. int index; // looping variable
  4722.  
  4723. heads_text.x = LEFT_HEADS_TEXT_X;
  4724. heads_text.y = LEFT_HEADS_TEXT_Y;
  4725.  
  4726. // draw the left most messages first
  4727.  
  4728. heads_text.curr_frame = 0;
  4729.  
  4730. for (index=0; index<4; index++)
  4731.     {
  4732.     Sprite_Draw((sprite_ptr)&heads_text,double_buffer,0);
  4733.  
  4734.     // move down a row
  4735.  
  4736.     heads_text.y+=8;
  4737.  
  4738.     } //  end for index
  4739.  
  4740.  
  4741. // now erase buttons and numbers
  4742.  
  4743. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4744. heads_numbers.y = LEFT_HEADS_TEXT_Y;
  4745.  
  4746. // erase cloaked button
  4747.  
  4748. heads_numbers.curr_frame=0;
  4749. Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4750.  
  4751. // erase scanner
  4752.  
  4753. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4754. heads_numbers.y = LEFT_HEADS_TEXT_Y+8;
  4755.  
  4756. Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4757.  
  4758. // erase communications
  4759.  
  4760. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4761. heads_numbers.y = LEFT_HEADS_TEXT_Y+16;
  4762.  
  4763. Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4764.  
  4765. // erase ships number
  4766.  
  4767. heads_numbers.x = LEFT_HEADS_TEXT_X+40;
  4768. heads_numbers.y = LEFT_HEADS_TEXT_Y+24;
  4769.  
  4770. Sprite_Draw((sprite_ptr)&heads_numbers,double_buffer,0);
  4771.  
  4772. // now draw right most messages
  4773.  
  4774. heads_text.x = RIGHT_HEADS_TEXT_X;
  4775. heads_text.y = RIGHT_HEADS_TEXT_Y;
  4776.  
  4777. // draw the left most messages first
  4778.  
  4779. for (index=0; index<2; index++)
  4780.     {
  4781.     Sprite_Draw((sprite_ptr)&heads_text,double_buffer,0);
  4782.  
  4783.     // move down a row
  4784.  
  4785.     heads_text.y+=8;
  4786.  
  4787.     } //  end for index
  4788.  
  4789. // erase gauges
  4790.  
  4791. heads_gauge.x = RIGHT_HEADS_TEXT_X+40;
  4792. heads_gauge.y = RIGHT_HEADS_TEXT_Y;
  4793.  
  4794. // compute proper frame
  4795.  
  4796. heads_gauge.curr_frame = 22;
  4797.  
  4798. // draw the energy level
  4799.  
  4800. Sprite_Draw((sprite_ptr)&heads_gauge,double_buffer,0);
  4801.  
  4802. // draw gauges
  4803.  
  4804. heads_gauge.x = RIGHT_HEADS_TEXT_X+40;
  4805. heads_gauge.y = RIGHT_HEADS_TEXT_Y+8;
  4806.  
  4807. // erase the shield strength
  4808.  
  4809. Sprite_Draw((sprite_ptr)&heads_gauge,double_buffer,0);
  4810.  
  4811. } // end Erase_Heads
  4812.  
  4813. /////////////////////////////////////////////////////////////////////////////
  4814.  
  4815. void Init_Scanner(void)
  4816. {
  4817. // this function initializes the scanner
  4818.  
  4819. // not much to do at this point!
  4820.  
  4821. } // end Init_Scanner
  4822.  
  4823. /////////////////////////////////////////////////////////////////////////////
  4824.  
  4825. void Erase_Scanner(void)
  4826. {
  4827. // this function erases the scanner and the blips
  4828.  
  4829. // first erase scanner grid
  4830.  
  4831. Line_H_2(SCANNER_X,SCANNER_X+64,SCANNER_Y,   0,double_buffer);
  4832. Line_H_2(SCANNER_X,SCANNER_X+64,SCANNER_Y+16,0,double_buffer);
  4833. Line_H_2(SCANNER_X,SCANNER_X+64,SCANNER_Y+32,0,double_buffer);
  4834.  
  4835. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X,   0,double_buffer);
  4836. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+16,0,double_buffer);
  4837. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+32,0,double_buffer);
  4838. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+48,0,double_buffer);
  4839. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+64,0,double_buffer);
  4840.  
  4841. } // end Erase_Scanner
  4842.  
  4843. ////////////////////////////////////////////////////////////////////////////
  4844.  
  4845. void Draw_Scanner(void)
  4846. {
  4847. // this function draws the scanner and the blips
  4848.  
  4849. // first draw scanner grid
  4850.  
  4851. Line_H_2(SCANNER_X,SCANNER_X+64,SCANNER_Y,   10,double_buffer);
  4852. Line_H_2(SCANNER_X,SCANNER_X+64,SCANNER_Y+16,10,double_buffer);
  4853. Line_H_2(SCANNER_X,SCANNER_X+64,SCANNER_Y+32,10,double_buffer);
  4854.  
  4855. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X,   10,double_buffer);
  4856. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+16,10,double_buffer);
  4857. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+32,10,double_buffer);
  4858. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+48,10,double_buffer);
  4859. Line_V_2(SCANNER_Y,SCANNER_Y+32,SCANNER_X+64,10,double_buffer);
  4860.  
  4861. } // end Draw_Scanner
  4862.  
  4863. /////////////////////////////////////////////////////////////////////////////
  4864.  
  4865. void Under_Blips(void)
  4866. {
  4867. // this function is used to draw all the scanner blips
  4868.  
  4869. // draw blips, notice that the position of the remote and player is
  4870. // scaled to fit into the scanner window
  4871.  
  4872. under_players_blip = Read_Pixel_DB(SCANNER_X+players_x/40,SCANNER_Y+players_y/80);
  4873. under_remotes_blip = Read_Pixel_DB(SCANNER_X+remotes_x/40,SCANNER_Y+remotes_y/80);
  4874.  
  4875. } // end Under_Blips
  4876.  
  4877. /////////////////////////////////////////////////////////////////////////////
  4878.  
  4879. void Draw_Blips(void)
  4880. {
  4881. // this function is used to draw all the scanner blips
  4882.  
  4883. // draw blips, notice that the position of the remote and player is
  4884. // scaled to fit into the scanner window
  4885.  
  4886. if (players_cloak==-1)
  4887.    Write_Pixel_DB(SCANNER_X+players_x/40,SCANNER_Y+players_y/80,9);
  4888.  
  4889. if (remotes_cloak==-1)
  4890.    Write_Pixel_DB(SCANNER_X+remotes_x/40,SCANNER_Y+remotes_y/80,12);
  4891.  
  4892. } // end Draw_Blips
  4893.  
  4894. /////////////////////////////////////////////////////////////////////////////
  4895.  
  4896. void Erase_Blips(void)
  4897. {
  4898. // this function is used to erase all the scanner blips
  4899.  
  4900. // erase blips, notice that the position of the remote and player is
  4901. // scaled to fit into the scanner window
  4902.  
  4903. Write_Pixel_DB(SCANNER_X+players_x/40,SCANNER_Y+players_y/80,under_players_blip);
  4904. Write_Pixel_DB(SCANNER_X+remotes_x/40,SCANNER_Y+remotes_y/80,under_remotes_blip);
  4905.  
  4906. } // end Erase_Blips
  4907.  
  4908. ////////////////////////////////////////////////////////////////////////////
  4909.  
  4910. void Music_Init(void)
  4911. {
  4912. // this function loads the music and resets all the indexes
  4913.  
  4914. static int loaded=0;
  4915.  
  4916. // has the music already been loaded
  4917.  
  4918. if (!music_enabled)
  4919.    return;
  4920.  
  4921. if (!loaded)
  4922.    {
  4923.    Music_Load("blazemus.xmi",(music_ptr)&song);
  4924.    loaded=1;
  4925.    } // end if not loaded
  4926.  
  4927. // reset sequence counters
  4928.  
  4929. game_seq_index=0;
  4930. intro_seq_index=0;
  4931.  
  4932. } // end Music_Init
  4933.  
  4934. /////////////////////////////////////////////////////////////////////////////
  4935.  
  4936. void Music_Close(void)
  4937. {
  4938. // this function unloads the music files
  4939.  
  4940. if (!music_enabled)
  4941.    return;
  4942.  
  4943. // turn off music and unload song
  4944.  
  4945. Music_Stop();
  4946. Music_Unload((music_ptr)&song);
  4947.  
  4948. } // end Music_Close
  4949.  
  4950. //////////////////////////////////////////////////////////////////////////////
  4951.  
  4952. void Digital_FX_Init(void)
  4953. {
  4954. // this function initializes the digital sound fx system
  4955.  
  4956. static int loaded=0;
  4957.  
  4958. if (!digital_enabled)
  4959.    return;
  4960.  
  4961. // have the sound fx been loaded?
  4962.  
  4963. if (!loaded)
  4964.    {
  4965.    // load int sounds
  4966.  
  4967.    Sound_Load("BLZCLK.VOC"  ,(sound_ptr)&digital_FX[BLZCLK_VOC  ],1);
  4968.    Sound_Load("BLZEXP1.VOC" ,(sound_ptr)&digital_FX[BLZEXP1_VOC ],1);
  4969.    Sound_Load("BLZEXP2.VOC" ,(sound_ptr)&digital_FX[BLZEXP2_VOC ],1);
  4970.    Sound_Load("BLZLAS.VOC"  ,(sound_ptr)&digital_FX[BLZLAS_VOC  ],1);
  4971.    Sound_Load("BLZNRG.VOC"  ,(sound_ptr)&digital_FX[BLZNRG_VOC  ],1);
  4972.    Sound_Load("BLZSHLD.VOC" ,(sound_ptr)&digital_FX[BLZSHLD_VOC ],1);
  4973.    Sound_Load("BLZTAC.VOC"  ,(sound_ptr)&digital_FX[BLZTAC_VOC  ],1);
  4974.    Sound_Load("BLZSCN.VOC"  ,(sound_ptr)&digital_FX[BLZSCN_VOC  ],1);
  4975.    Sound_Load("BLZMISS.VOC" ,(sound_ptr)&digital_FX[BLZMISS_VOC ],1);
  4976.  
  4977.    Sound_Load("BLZBIOS.VOC" ,(sound_ptr)&digital_FX[BLZBIOS_VOC ],1);
  4978.    Sound_Load("BLZENTR.VOC" ,(sound_ptr)&digital_FX[BLZENTR_VOC ],1);
  4979.    Sound_Load("BLZABRT.VOC" ,(sound_ptr)&digital_FX[BLZABRT_VOC ],1);
  4980.    Sound_Load("BLZSEL.VOC"  ,(sound_ptr)&digital_FX[BLZSEL_VOC  ],1);
  4981.    Sound_Load("BLZKEY.VOC"  ,(sound_ptr)&digital_FX[BLZKEY_VOC  ],1);
  4982.    Sound_Load("BLZDIAL.VOC"  ,(sound_ptr)&digital_FX[BLZDIAL_VOC  ],1);
  4983.  
  4984.    Sound_Load("BLZLOS.VOC"  ,(sound_ptr)&digital_FX[BLZLOS_VOC  ],1);
  4985.    Sound_Load("BLZWIN.VOC"  ,(sound_ptr)&digital_FX[BLZWIN_VOC  ],1);
  4986.  
  4987.    // set loaded flag
  4988.  
  4989.    loaded=1;
  4990.  
  4991.    } // end if sound effects aren't loaded
  4992.  
  4993. } // end Digital_FX_Init
  4994.  
  4995. ///////////////////////////////////////////////////////////////////////////////
  4996.  
  4997. void Digital_FX_Close(void)
  4998. {
  4999. // this function unloads all the digital FX
  5000.  
  5001. if (!digital_enabled)
  5002.    return;
  5003.  
  5004. // unload all the sound fx from memory
  5005.  
  5006. Sound_Unload((sound_ptr)&digital_FX[BLZCLK_VOC  ]);
  5007. Sound_Unload((sound_ptr)&digital_FX[BLZEXP1_VOC ]);
  5008. Sound_Unload((sound_ptr)&digital_FX[BLZEXP2_VOC ]);
  5009. Sound_Unload((sound_ptr)&digital_FX[BLZLAS_VOC  ]);
  5010. Sound_Unload((sound_ptr)&digital_FX[BLZNRG_VOC  ]);
  5011. Sound_Unload((sound_ptr)&digital_FX[BLZSHLD_VOC ]);
  5012. Sound_Unload((sound_ptr)&digital_FX[BLZTAC_VOC  ]);
  5013. Sound_Unload((sound_ptr)&digital_FX[BLZSCN_VOC  ]);
  5014. Sound_Unload((sound_ptr)&digital_FX[BLZMISS_VOC ]);
  5015.  
  5016. Sound_Unload((sound_ptr)&digital_FX[BLZENTR_VOC ]);
  5017. Sound_Unload((sound_ptr)&digital_FX[BLZABRT_VOC ]);
  5018. Sound_Unload((sound_ptr)&digital_FX[BLZSEL_VOC  ]);
  5019. Sound_Unload((sound_ptr)&digital_FX[BLZKEY_VOC  ]);
  5020. Sound_Unload((sound_ptr)&digital_FX[BLZDIAL_VOC ]);
  5021.  
  5022. Sound_Unload((sound_ptr)&digital_FX[BLZLOS_VOC  ]);
  5023. Sound_Unload((sound_ptr)&digital_FX[BLZWIN_VOC ]);
  5024.  
  5025.  
  5026. } // end Digital_FX_Close
  5027.  
  5028. /////////////////////////////////////////////////////////////////////////////
  5029.  
  5030. int Digital_FX_Play(int the_effect, int priority)
  5031. {
  5032. // this function is used to play a digital effect using a pre-emptive priority
  5033. // scheme. The algorithm works like this: if a sound is playing then its
  5034. // priority is compared to the sound that is being requested to be played
  5035. // if the new sound has higher priority (a smaller number) then the currenlty
  5036. // playing sound is pre-empted for the new sound and the global FX priority
  5037. // is set to the new sound. If there is no sound playing then the new sound
  5038. // is simple played and the global priority is set
  5039.  
  5040. // is the digital fx system on-line?
  5041.  
  5042. if (!digital_enabled)
  5043.    return(0);
  5044.  
  5045. // is there a sound playing?
  5046.  
  5047. if (!Sound_Status() || (priority <= digital_FX_priority))
  5048.    {
  5049.    // start new sound
  5050.  
  5051.    Sound_Stop();
  5052.  
  5053.    Sound_Play((sound_ptr)&digital_FX[the_effect]);
  5054.  
  5055.    // set the priority
  5056.  
  5057.    digital_FX_priority = priority;
  5058.  
  5059.    return(1);
  5060.  
  5061.    } // end if
  5062. else // the current sound is of higher priority
  5063.    return(0);
  5064.  
  5065. } // end Digital_FX_Play
  5066.  
  5067. /////////////////////////////////////////////////////////////////////////////
  5068.  
  5069. int Parse_Commands(int argc, char **argv)
  5070. {
  5071. // this function is used to parse the commands line parameters that are to be
  5072. // used as switched to enable different modes of operation
  5073.  
  5074. int index;  // looping variable
  5075.  
  5076. for (index=1; index<argc; index++)
  5077.     {
  5078.     // get the first character from the string
  5079.  
  5080.     switch(argv[index][0])
  5081.           {
  5082.  
  5083.           case 's': // enable sound effects
  5084.           case 'S':
  5085.                {
  5086.                digital_enabled=1;
  5087.                } break;
  5088.  
  5089.           case 'm': // enable nusic
  5090.           case 'M':
  5091.                {
  5092.                music_enabled=1;
  5093.                } break;
  5094.  
  5095.           // more commands would go here...
  5096.  
  5097.           default:break;
  5098.  
  5099.           } // end switch
  5100.  
  5101.     } // end for index
  5102.  
  5103. } // end Parse_Commands
  5104.  
  5105. /////////////////////////////////////////////////////////////////////////////
  5106.  
  5107. int Get_Modem_String(char *buffer)
  5108. {
  5109. // this function open up the modem intialization file named
  5110. // blaze.mod, if the file exists then
  5111.  
  5112. FILE *fp;
  5113.  
  5114. // try and open the file
  5115.  
  5116. if ((fp=fopen("blaze.mod","r"))==NULL)
  5117.    {
  5118.    strcpy(buffer,"");
  5119.    return(0);
  5120.    }
  5121.  
  5122. // else load in modem initialization string
  5123.  
  5124. fscanf(fp,"%s",buffer);
  5125.  
  5126. // close the file
  5127.  
  5128. fclose(fp);
  5129.  
  5130. return(1);
  5131.  
  5132. } // end Get_Modem_String
  5133.  
  5134. // M A I N //////////////////////////////////////////////////////////////////
  5135.  
  5136. void main(int argc, char **argv)
  5137. {
  5138.  
  5139. // the main controls most of the platyer and remote logic, normally we would
  5140. // probably move most of the code into functions, but for instructional purposes
  5141. // this is easier to follow, believe me there are already enough function calls
  5142. // to make your head spin!
  5143.  
  5144. int index,             // looping variable
  5145.     sel,               // used for input
  5146.     px_window,         // starting upper left hand corner of players view port
  5147.     py_window,
  5148.     result,            // result from comm system
  5149.     response,          // result from comm system
  5150.     players_key_state, // state of players input
  5151.     remotes_key_state, // state pf remotes input
  5152.  
  5153.     sent_right =0,     // diagnostic counters to track number of
  5154.     sent_left  =0,     // of input instructions both sent and received
  5155.     sent_up    =0,
  5156.     rec_right  =0,
  5157.     rec_left   =0,
  5158.     rec_up     =0;
  5159.  
  5160. unsigned char seed;    // a random number seed
  5161.  
  5162. char buffer[64],            // general buffer
  5163.      modem_ini_string[64],  // used for extra modem intialization string
  5164.      number[32],            // used to print strings
  5165.      ch;                    // used for keyboard input
  5166.  
  5167. // the game begins by loading in all the imagery, sounds and so forth.
  5168.  
  5169. // parse the command line and set up configuration
  5170.  
  5171. Parse_Commands(argc,argv);
  5172.  
  5173. // get the modem initialization string
  5174.  
  5175. Get_Modem_String(modem_ini_string);
  5176.  
  5177. printf("\nExtra modem initialization string = %s",modem_ini_string);
  5178.  
  5179. Time_Delay(25);
  5180.  
  5181. // set the graphics mode to mode 13h
  5182.  
  5183. Set_Graphics_Mode(GRAPHICS_MODE13);
  5184.  
  5185. // start up music system
  5186.  
  5187. if (music_enabled)
  5188.    {
  5189.    Music_Init();
  5190.    Music_Play((music_ptr)&song,0);
  5191.    } // end if music enabled
  5192.  
  5193. // start up digital FX system
  5194.  
  5195. if (digital_enabled)
  5196.    {
  5197.    Digital_FX_Init();
  5198.    } // end if digital sound enabled
  5199.  
  5200. // put up Waite header
  5201.  
  5202. Intro_Waite();
  5203.  
  5204. // seed the random number generator with time
  5205.  
  5206. srand((unsigned int)Timer_Query());
  5207.  
  5208. // initialize font engine
  5209.  
  5210. Font_Engine_1(0,0,0,0,NULL,NULL);
  5211. Tech_Print(START_MESS_X,START_MESS_Y,"STARBLAZER 1.0 STARTING UP...",video_buffer);
  5212.  
  5213. Time_Delay(5);
  5214.  
  5215. // create the double buffer
  5216.  
  5217. Create_Double_Buffer(200);
  5218. Tech_Print(START_MESS_X,START_MESS_Y+16,"DOUBLE BUFFER CREATED",video_buffer);
  5219. Tech_Print(START_MESS_X,START_MESS_Y+24,"LANGUAGE TRANSLATION ENGAGED",video_buffer);
  5220.  
  5221. // install the keyboard driver
  5222.  
  5223. Keyboard_Install_Driver();
  5224. Tech_Print(START_MESS_X,START_MESS_Y+32,"NEURAL INTERFACE ACTIVATED",video_buffer);
  5225.  
  5226. // load in all gadget icons
  5227.  
  5228. Load_Icons();
  5229. Tech_Print(START_MESS_X,START_MESS_Y+40,"VISUAL ICONS LOADED",video_buffer);
  5230.  
  5231. // load in the ships
  5232.  
  5233. Load_Ships();
  5234. Tech_Print(START_MESS_X,START_MESS_Y+48,"SHIPS LOADED",video_buffer);
  5235.  
  5236. // assign ships to player and remote
  5237.  
  5238. Copy_Frames((sprite_ptr)&players_ship,(sprite_ptr)&gryfon_l);
  5239. Copy_Frames((sprite_ptr)&remotes_ship,(sprite_ptr)&raptor_r);
  5240.  
  5241. // start the asteroids up
  5242.  
  5243. Init_Asteroids(16,6,4);
  5244. Tech_Print(START_MESS_X,START_MESS_Y+56,"ASTEROID TRAJECTORIES COMPUTED",video_buffer);
  5245.  
  5246. // start the stars
  5247.  
  5248. Init_Stars();
  5249. Tech_Print(START_MESS_X,START_MESS_Y+64,"STARFIELD GENERATED",video_buffer);
  5250.  
  5251. // start the missiles
  5252.  
  5253. Init_Missiles();
  5254. Tech_Print(START_MESS_X,START_MESS_Y+72,"WEAPONS DAEMONS ONLINE",video_buffer);
  5255.  
  5256. // start the explosions
  5257.  
  5258. Init_Explosions();
  5259. Load_Explosions();
  5260. Init_Novas();
  5261. Tech_Print(START_MESS_X,START_MESS_Y+80,"EXPLOSION ANIMATION SYSTEM LOADED",video_buffer);
  5262.  
  5263. // initialize font engine
  5264.  
  5265. Font_Engine_1(0,0,0,0,NULL,NULL);
  5266. Tech_Print(START_MESS_X,START_MESS_Y+88,"FONT ENGINE ENGAGED",video_buffer);
  5267.  
  5268. // load the wormhole imagery
  5269.  
  5270. Load_Wormhole();
  5271. Init_Wormhole();
  5272. Tech_Print(START_MESS_X,START_MESS_Y+96,"WORM HOLE CREATED",video_buffer);
  5273.  
  5274. // load the aliens
  5275.  
  5276. Load_Alien();
  5277. Init_Alien();
  5278. Tech_Print(START_MESS_X,START_MESS_Y+104,"ENEMY AI GENERATED",video_buffer);
  5279.  
  5280. // the the fuel cells
  5281.  
  5282. Load_Fuel_Cells();
  5283. Init_Fuel_Cells();
  5284. Tech_Print(START_MESS_X,START_MESS_Y+112,"FUEL CELLS PLACED",video_buffer);
  5285.  
  5286. // load the heads up display
  5287.  
  5288. Load_Heads();
  5289. Init_Heads();
  5290. Tech_Print(START_MESS_X,START_MESS_Y+120,"HEADS UP DISPLAY ACTIVE",video_buffer);
  5291.  
  5292. // blink ok
  5293.  
  5294. Tech_Print(START_MESS_X,START_MESS_Y+136,"SYSTEM BIOS O.K.",video_buffer);
  5295.  
  5296. Digital_FX_Play(BLZBIOS_VOC,1);
  5297.  
  5298. for (index=0; index<3; index++)
  5299.     {
  5300.     // draw the message and the erase the message
  5301.     Font_Engine_1(START_MESS_X,START_MESS_Y+136,0,0,"SYSTEM BIOS O.K.",video_buffer);
  5302.     Time_Delay(8);
  5303.  
  5304.     Font_Engine_1(START_MESS_X,START_MESS_Y+136,0,0,"                ",video_buffer);
  5305.     Time_Delay(8);
  5306.  
  5307.     } // end for
  5308.  
  5309. // get rid off this sound to save a little memory (we are running low!)
  5310.  
  5311. Sound_Unload((sound_ptr)&digital_FX[BLZBIOS_VOC]);
  5312.  
  5313. // do intro piece
  5314.  
  5315. Intro_Title();
  5316.  
  5317. // save the system pallete here because we are going to really thrash it!!!
  5318.  
  5319. Read_Palette(0,255,(RGB_palette_ptr)&game_palette);
  5320.  
  5321. // main event loop ///////////////////////////////////////////////////////////
  5322.  
  5323. while(game_state!=GAME_OVER)
  5324.      {
  5325.      // test the overall game state
  5326.  
  5327.      if (game_state==GAME_SETUP)
  5328.         {
  5329.         // if machines were linked then break connection
  5330.  
  5331.         if (linked)
  5332.            {
  5333.            // close down serial connection
  5334.  
  5335.            Hang_Up();
  5336.            Serial_Flush();
  5337.            Serial_Close();
  5338.  
  5339.            // reset linked flag
  5340.  
  5341.            linked = 0;
  5342.  
  5343.            } // end if
  5344.  
  5345.         // user in in the setup state
  5346.  
  5347.         Intro_Controls();
  5348.  
  5349.         // restore pallete
  5350.  
  5351.         Write_Palette(0,255,(RGB_palette_ptr)&game_palette);
  5352.  
  5353.         // enter setup event loop
  5354.  
  5355.         while(game_state==GAME_SETUP)
  5356.              {
  5357.              // this event loop is for the setup phase
  5358.  
  5359.              if (keys_active>0)
  5360.                 {
  5361.  
  5362.                 // what is user trying to do
  5363.  
  5364.                     if (keyboard_state[MAKE_UP])
  5365.                            {
  5366.                            // erase the button and move it up
  5367.                            Sprite_Erase((sprite_ptr)&button_1,video_buffer);
  5368.  
  5369.                            button_1.y-=12;
  5370.  
  5371.                            // test if we need to wrap around bottom
  5372.  
  5373.                            if (--button_1.counter_1 < 0)
  5374.                               {
  5375.                               button_1.counter_1 = 6;
  5376.                               button_1.y         = 63+6*12;
  5377.                               } // end if wrap around
  5378.  
  5379.                            // scan and draw button
  5380.                            Sprite_Under((sprite_ptr)&button_1,video_buffer);
  5381.                            Sprite_Draw((sprite_ptr)&button_1,video_buffer,1);
  5382.  
  5383.                            Digital_FX_Play(BLZKEY_VOC,2);
  5384.  
  5385.                            Time_Delay(1);
  5386.  
  5387.                            } // end if up
  5388.  
  5389.                     else
  5390.                     if (keyboard_state[MAKE_DOWN])
  5391.                            {
  5392.                            // erase the button and move it down
  5393.                            Sprite_Erase((sprite_ptr)&button_1,video_buffer);
  5394.  
  5395.                            button_1.y+=12;
  5396.  
  5397.                            // test if we need to wrap around top
  5398.  
  5399.                            if (++button_1.counter_1 > 6)
  5400.                               {
  5401.                               button_1.counter_1 = 0;
  5402.                               button_1.y         = 63;
  5403.                               } // end if wrap around
  5404.  
  5405.                            // scan and draw button
  5406.                            Sprite_Under((sprite_ptr)&button_1,video_buffer);
  5407.                            Sprite_Draw((sprite_ptr)&button_1,video_buffer,1);
  5408.  
  5409.                            Digital_FX_Play(BLZKEY_VOC,2);
  5410.  
  5411.                            Time_Delay(1);
  5412.  
  5413.                            } // end if down
  5414.                      else
  5415.                      if (keyboard_state[MAKE_ENTER] )
  5416.                            {
  5417.  
  5418.                            // illuminate button for a second
  5419.  
  5420.                            // draw button down
  5421.  
  5422.                            button_1.curr_frame = 1;
  5423.                            Sprite_Draw((sprite_ptr)&button_1,video_buffer,1);
  5424.  
  5425.                            Digital_FX_Play(BLZKEY_VOC,2);
  5426.  
  5427.                            Time_Delay(5);
  5428.  
  5429.                            // now draw button up
  5430.  
  5431.                            button_1.curr_frame = 0;
  5432.                            Sprite_Draw((sprite_ptr)&button_1,video_buffer,1);
  5433.  
  5434.                            // test which item is being selected
  5435.  
  5436.                            switch(button_1.counter_1)
  5437.                                  {
  5438.                                  case SETUP_PLAY_SOLO:
  5439.                                       {
  5440.  
  5441.                                       Clear_Display(0);
  5442.  
  5443.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5444.                                                     "ENTERING ARENA",
  5445.                                                     video_buffer);
  5446.  
  5447.                                       // move to running state
  5448.  
  5449.                                       game_state = GAME_RUNNING;
  5450.  
  5451.                                       Time_Delay(5);
  5452.  
  5453.                                       } break;
  5454.  
  5455.                                  case SETUP_MAKE_CONNECTION:
  5456.                                       {
  5457.  
  5458.                                       Clear_Display(0);
  5459.  
  5460.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5461.                                                     "ENTER NUMBER",
  5462.                                                     video_buffer);
  5463.  
  5464.  
  5465.  
  5466.  
  5467.                                       // remove the keyboard handler,
  5468.                                       // makes user input easier for strings
  5469.  
  5470.                                       Keyboard_Remove_Driver();
  5471.  
  5472.                                       result = Get_Line(number);
  5473.  
  5474.                                       // replace our handler
  5475.  
  5476.                                       Keyboard_Install_Driver();
  5477.  
  5478.                                       // get the number
  5479.  
  5480.                                       if (!result)
  5481.                                          {
  5482.  
  5483.                                          Clear_Display(0);
  5484.  
  5485.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5486.                                                        "ABORTED...",
  5487.                                                        video_buffer);
  5488.  
  5489.                                          Digital_FX_Play(BLZABRT_VOC,1);
  5490.  
  5491.                                          Time_Delay(5);
  5492.  
  5493.                                          Clear_Display(0);
  5494.  
  5495.                                          break;
  5496.  
  5497.                                          } // end if aborted input
  5498.  
  5499.                                       // make a connection
  5500.  
  5501.                                       // open com port
  5502.  
  5503.                                       Modem_Control(MODEM_DTR_ON);
  5504.  
  5505.                                       Serial_Open(comm_port_to_address[comm_port] ,SERIAL_BAUD_2400,SERIAL_PARITY_NONE |
  5506.                                                   SERIAL_BITS_8 | SERIAL_STOP_1);
  5507.  
  5508.                                       Serial_Flush();
  5509.  
  5510.                                       // initialize modem with standard initialization
  5511.                                       // plus any added init string in blaze.mod
  5512.  
  5513.                                       Initialize_Modem(modem_ini_string);
  5514.  
  5515.                                       // let user know whats going on
  5516.  
  5517.                                       Clear_Display(0);
  5518.  
  5519.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5520.                                                     "DIALING:",
  5521.                                                     video_buffer);
  5522.  
  5523.  
  5524.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2+8,0,0,
  5525.                                                     number,
  5526.                                                     video_buffer);
  5527.  
  5528.                                       Digital_FX_Play(BLZDIAL_VOC,1);
  5529.  
  5530.                                       result = Make_Connection(number);
  5531.  
  5532.                                       if (result==MODEM_CONNECT_1200 ||
  5533.                                           result==MODEM_CONNECT_2400 ||
  5534.                                           result==MODEM_CONNECT      ||
  5535.                                           result==MODEM_CARRIER_2400)
  5536.                                          {
  5537.                                          // set game to linked and local to
  5538.                                          // master
  5539.  
  5540.                                          linked=1;
  5541.                                          master=1;
  5542.                                          slave=0;
  5543.  
  5544.                                          game_state = GAME_LINKING;
  5545.  
  5546.                                          Clear_Display(0);
  5547.  
  5548.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5549.                                                        "CONNECTED!",
  5550.                                                        video_buffer);
  5551.  
  5552.                                          Time_Delay(5);
  5553.  
  5554.                                          Clear_Display(0);
  5555.  
  5556.                                          } //end if connection made
  5557.                                       else
  5558.                                       if (result==MODEM_USER_ABORT)
  5559.                                          {
  5560.                                          // close down serial connection
  5561.  
  5562.                                          Hang_Up();
  5563.                                          Serial_Flush();
  5564.                                          Serial_Close();
  5565.  
  5566.                                          // print that selection was aborted
  5567.  
  5568.                                          Clear_Display(0);
  5569.  
  5570.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5571.                                                        "ABORTED...",
  5572.                                                        video_buffer);
  5573.  
  5574.                                          Digital_FX_Play(BLZABRT_VOC,1);
  5575.  
  5576.                                          Time_Delay(5);
  5577.  
  5578.                                          Clear_Display(0);
  5579.  
  5580.                                          } // end if user aborted
  5581.                                       else
  5582.                                          {
  5583.                                          // close down serial connection
  5584.  
  5585.                                          Hang_Up();
  5586.                                          Serial_Flush();
  5587.                                          Serial_Close();
  5588.  
  5589.                                          // print that selection was aborted
  5590.  
  5591.                                          Clear_Display(0);
  5592.  
  5593.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5594.                                                        "COMM PROBLEM",
  5595.                                                        video_buffer);
  5596.  
  5597.                                          Time_Delay(5);
  5598.  
  5599.                                          Clear_Display(0);
  5600.  
  5601.                                          } // end if user aborted
  5602.                                       } break;
  5603.  
  5604.                                  case SETUP_WAIT_FOR_CONNECTION:
  5605.                                       {
  5606.  
  5607.                                       Clear_Display(0);
  5608.  
  5609.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5610.                                                     "ANSWER MODE",
  5611.                                                     video_buffer);
  5612.  
  5613.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2+8,0,0,
  5614.                                                     "ENABLED...",
  5615.                                                     video_buffer);
  5616.  
  5617.                                       // open com port
  5618.  
  5619.                                       Modem_Control(MODEM_DTR_ON);
  5620.  
  5621.                                       Serial_Open(comm_port_to_address[comm_port] ,SERIAL_BAUD_2400,SERIAL_PARITY_NONE |
  5622.                                                   SERIAL_BITS_8 | SERIAL_STOP_1);
  5623.  
  5624.                                       Serial_Flush();
  5625.  
  5626.                                       // wait for a call
  5627.  
  5628.  
  5629.                                       // initialize modem with standard initialization
  5630.                                       // plus any added init string in blaze.mod
  5631.  
  5632.                                       Initialize_Modem(modem_ini_string);
  5633.  
  5634.                                       result = Wait_For_Connection();
  5635.  
  5636.                                       // is the connection message 2400?
  5637.  
  5638.                                       if (result==MODEM_CONNECT_1200 ||
  5639.                                           result==MODEM_CONNECT_2400 ||
  5640.                                           result==MODEM_CONNECT      ||
  5641.                                           result==MODEM_CARRIER_2400)
  5642.                                          {
  5643.                                          // set game state to linked and local
  5644.                                          // to slave
  5645.  
  5646.                                          linked=1;
  5647.                                          master = 0;
  5648.                                          slave = 1;
  5649.  
  5650.                                          game_state = GAME_LINKING;
  5651.  
  5652.                                          Clear_Display(0);
  5653.  
  5654.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5655.                                                        "CONNECTED!",
  5656.                                                        video_buffer);
  5657.  
  5658.                                          Time_Delay(5);
  5659.  
  5660.                                          Clear_Display(0);
  5661.  
  5662.                                          } // end if connection made
  5663.                                       else
  5664.                                       if (result==MODEM_USER_ABORT)
  5665.                                          {
  5666.                                          // user bailed so close down serial
  5667.  
  5668.                                          Hang_Up();
  5669.                                          Serial_Flush();
  5670.                                          Serial_Close();
  5671.  
  5672.                                          Clear_Display(0);
  5673.  
  5674.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5675.                                                        "ABORTED...",
  5676.                                                        video_buffer);
  5677.  
  5678.                                          // play sound fx
  5679.  
  5680.                                          Digital_FX_Play(BLZABRT_VOC,1);
  5681.  
  5682.                                          Time_Delay(5);
  5683.  
  5684.                                          Clear_Display(0);
  5685.  
  5686.                                          } // end if user aborted
  5687.                                       else
  5688.                                          {
  5689.                                          // close down serial connection
  5690.  
  5691.                                          Hang_Up();
  5692.                                          Serial_Flush();
  5693.                                          Serial_Close();
  5694.  
  5695.                                          // print that selection was aborted
  5696.  
  5697.                                          Clear_Display(0);
  5698.  
  5699.                                          Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5700.                                                        "COMM PROBLEM",
  5701.                                                        video_buffer);
  5702.  
  5703.                                          Time_Delay(5);
  5704.  
  5705.                                          Clear_Display(0);
  5706.  
  5707.                                          } // end if user aborted
  5708.  
  5709.                                       } break;
  5710.  
  5711.                                  case SETUP_SELECT_SHIP:
  5712.                                       {
  5713.  
  5714.                                       Clear_Display(0);
  5715.  
  5716.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5717.                                                     "GRYFON  RAPTOR",
  5718.                                                     video_buffer);
  5719.  
  5720.                                       // draw ships
  5721.  
  5722.                                       displays.curr_frame = DISPLAY_IMG_SHIPS;
  5723.  
  5724.                                       Sprite_Draw((sprite_ptr)&displays,video_buffer,1);
  5725.  
  5726.                                       // let user select one
  5727.  
  5728.                                       sel = Display_Select(players_ship_type);
  5729.  
  5730.                                       // test if user changed ship
  5731.  
  5732.                                       if (sel!=-1)
  5733.                                          {
  5734.                                          players_ship_type = sel;
  5735.  
  5736.                                          // set up sprite
  5737.  
  5738.                                          if (players_ship_type==GRYFON_SHIP)
  5739.                                              {
  5740.                                              Copy_Frames((sprite_ptr)&players_ship,(sprite_ptr)&gryfon_l);
  5741.                                              }
  5742.                                          else
  5743.                                              {
  5744.                                              Copy_Frames((sprite_ptr)&players_ship,(sprite_ptr)&raptor_l);
  5745.  
  5746.                                              }
  5747.                                          } // end if
  5748.  
  5749.                                       } break;
  5750.  
  5751.                                  case SETUP_SET_COMM_PORT:
  5752.                                       {
  5753.  
  5754.                                       Clear_Display(0);
  5755.  
  5756.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5757.                                                     "COMM 1  COMM 2",
  5758.                                                     video_buffer);
  5759.  
  5760.                                       // draw comm ports
  5761.  
  5762.                                       displays.curr_frame = DISPLAY_IMG_PORTS;
  5763.  
  5764.                                       Sprite_Draw((sprite_ptr)&displays,video_buffer,1);
  5765.  
  5766.                                       // let user select one
  5767.  
  5768.                                       sel = Display_Select(comm_port);
  5769.  
  5770.                                       // test if user changed selection
  5771.  
  5772.                                       if (sel!=-1)
  5773.                                          {
  5774.                                          // change comm port
  5775.  
  5776.                                          comm_port=sel;
  5777.  
  5778.                                          } // end if
  5779.  
  5780.  
  5781.                                       } break;
  5782.  
  5783.                                  case SETUP_BRIEFING:
  5784.                                       {
  5785.                                       // show user instructions
  5786.  
  5787.                                       Digital_FX_Play(BLZMISS_VOC ,1);
  5788.  
  5789.                                       Intro_Briefing();
  5790.  
  5791.                                       // redisplay intro controls
  5792.  
  5793.                                       Intro_Controls();
  5794.  
  5795.                                       } break;
  5796.  
  5797.                                  case SETUP_EXIT:
  5798.                                       {
  5799.                                       // set state to game over
  5800.  
  5801.                                       game_state=GAME_OVER;
  5802.  
  5803.                                       Clear_Display(0);
  5804.  
  5805.                                       Font_Engine_1(DISPLAY_X+2,DISPLAY_Y+2,0,0,
  5806.                                                     "EXITING SYSTEM",
  5807.                                                     video_buffer);
  5808.  
  5809.                                       } break;
  5810.  
  5811.                                  default:break;
  5812.  
  5813.                                  } // end switch
  5814.  
  5815.                            } // end if enter
  5816.  
  5817.                 } // end if keyboard hit
  5818.  
  5819.              // perform special effects to control panel
  5820.  
  5821.              Panel_FX();
  5822.  
  5823.              // slow things down a bit
  5824.  
  5825.              Time_Delay(1);
  5826.  
  5827.              // check on music
  5828.  
  5829.              if (music_enabled)
  5830.                 {
  5831.                 // test if piece is complete or has been stopped
  5832.  
  5833.                 if (Music_Status()==2 || Music_Status()==0)
  5834.                    {
  5835.                    // advance to next sequence
  5836.  
  5837.                    if (++intro_seq_index==11)
  5838.                       intro_seq_index=0;
  5839.  
  5840.                    Music_Play((music_ptr)&song,intro_sequence[intro_seq_index]);
  5841.  
  5842.                    } // end if
  5843.  
  5844.                 } // end if music enabled
  5845.  
  5846.              } // end setup event loop
  5847.  
  5848.         } // end if in control state
  5849.  
  5850. ///////////////////////////////////////////////////////////////////////////////
  5851.      else
  5852.      if (game_state==GAME_LINKING)
  5853.         {
  5854.  
  5855.         // wait a second to machine sure otehr machine is linked
  5856.  
  5857.         Time_Delay(DELAY_2_SECOND);
  5858.  
  5859.         // test if this machine is master or slave and negotiate
  5860.         // connection
  5861.  
  5862.         if (master)
  5863.            {
  5864.  
  5865.            // send master signal
  5866.  
  5867.            Serial_Write('M');
  5868.  
  5869.            // send ship type
  5870.  
  5871.            Serial_Write('0'+players_ship_type);
  5872.  
  5873.            // this is a crucial function call, both machines must use the same
  5874.            // random sequence, this is accomplised by the master sending a seed
  5875.            // to the remote to be used as the seed for the random number
  5876.            // generator
  5877.  
  5878.            // send random seed
  5879.  
  5880.            seed = (unsigned char)Timer_Query();
  5881.  
  5882.            Serial_Write(seed);
  5883.  
  5884.            // seed local random number generator
  5885.  
  5886.            srand(seed);
  5887.  
  5888.  
  5889.            // wait for acknowledge
  5890.  
  5891.            response = Serial_Read_Wait();
  5892.  
  5893.            if (response=='S')
  5894.               {
  5895.  
  5896.               // get remotes ship type
  5897.  
  5898.               response = Serial_Read_Wait();
  5899.  
  5900.               remotes_ship_type = response - '0';
  5901.  
  5902.               // move game state into running mode
  5903.  
  5904.               game_state=GAME_RUNNING;
  5905.  
  5906.               } // end if linked
  5907.  
  5908.            } // end if master
  5909.         else
  5910.         if (slave)
  5911.            {
  5912.            // send master signal
  5913.  
  5914.            Serial_Write('S');
  5915.  
  5916.            // send ship type
  5917.  
  5918.            Serial_Write('0'+players_ship_type);
  5919.  
  5920.            // wait for a master signal
  5921.  
  5922.            // wait for acknowledge
  5923.  
  5924.            response = Serial_Read_Wait();
  5925.  
  5926.            if (response=='M')
  5927.               {
  5928.               // get remotes ship type
  5929.  
  5930.               response = Serial_Read_Wait();
  5931.  
  5932.               remotes_ship_type = response - '0';
  5933.  
  5934.               // the next byte is the random number generator seed
  5935.  
  5936.               seed = (unsigned char)Serial_Read_Wait();
  5937.  
  5938.               srand(seed);
  5939.  
  5940.  
  5941.               // move game state into running mode
  5942.  
  5943.               game_state=GAME_RUNNING;
  5944.  
  5945.               } // end if linked
  5946.  
  5947.            } // end if slave
  5948.  
  5949.         } // end if game linking
  5950.  
  5951. ////////////////////////////////////////////////////////////////////////////////
  5952.  
  5953.      else
  5954.      if (game_state==GAME_RUNNING)
  5955.         {
  5956.  
  5957.         // restore pallete
  5958.  
  5959.         Write_Palette(0,255,(RGB_palette_ptr)&game_palette);
  5960.  
  5961.         // turn shields off
  5962.  
  5963.         Shield_Control(THE_PLAYER,0);
  5964.         Shield_Control(THE_REMOTE,0);
  5965.  
  5966.         // reset system variables
  5967.  
  5968.         Reset_System();
  5969.  
  5970.         // select engine colors
  5971.  
  5972.         if (players_ship_type==GRYFON_SHIP)
  5973.            players_engine_color = primary_white;
  5974.         else
  5975.            players_engine_color = primary_green;
  5976.  
  5977.         if (remotes_ship_type==GRYFON_SHIP)
  5978.            remotes_engine_color = primary_white;
  5979.         else
  5980.            remotes_engine_color = primary_green;
  5981.  
  5982.         // set up remote ships ship type
  5983.  
  5984.         if (remotes_ship_type==GRYFON_SHIP)
  5985.             Copy_Frames((sprite_ptr)&remotes_ship,(sprite_ptr)&gryfon_r);
  5986.         else
  5987.             Copy_Frames((sprite_ptr)&remotes_ship,(sprite_ptr)&raptor_r);
  5988.  
  5989.         // restart everything
  5990.  
  5991.         Init_Wormhole();
  5992.         Init_Stars();
  5993.         Init_Missiles();
  5994.         Init_Asteroids(16,6,4);
  5995.         Init_Explosions();
  5996.         Init_Novas();
  5997.         Init_Alien();
  5998.         Init_Heads();
  5999.         Init_Fuel_Cells();
  6000.  
  6001.         // start music
  6002.  
  6003.         if (music_enabled)
  6004.            {
  6005.            Music_Stop();
  6006.  
  6007.            game_seq_index=0;
  6008.  
  6009.            Music_Play((music_ptr)&song,game_sequence[game_seq_index]);
  6010.  
  6011.            } // end if music enabled
  6012.  
  6013.         Digital_FX_Play(BLZENTR_VOC,1);
  6014.  
  6015.         // clear double buffer
  6016.  
  6017.         Fill_Double_Buffer(0);
  6018.  
  6019.         // scan under all objects
  6020.  
  6021.         Under_Wormhole();
  6022.         Under_Asteroids();
  6023.         Under_Stars();
  6024.         Under_Fuel_Cells();
  6025.  
  6026. // BEGIN PLAYER ///////////////////////////////////////////////////////////////
  6027.  
  6028.         Sprite_Under((sprite_ptr)&players_ship,double_buffer);
  6029.  
  6030. // END PLAYER ///////////////////////////////////////////////////////////////
  6031.  
  6032. // BEGIN REMOTE ///////////////////////////////////////////////////////////////
  6033.  
  6034.         px_window = players_x - 160+11;
  6035.         py_window = players_y - 100+9;
  6036.  
  6037.         remotes_ship.x = remotes_x - px_window;
  6038.         remotes_ship.y = remotes_y - py_window;
  6039.  
  6040.         Sprite_Under_Clip((sprite_ptr)&remotes_ship,double_buffer);
  6041.  
  6042. // END REMOTE ///////////////////////////////////////////////////////////////
  6043.  
  6044.         // enter into the main game loop
  6045.  
  6046.         while(game_state==GAME_RUNNING)
  6047.              {
  6048.  
  6049.              // compute starting time of this frame
  6050.  
  6051.              starting_time = Timer_Query();
  6052.  
  6053.              // reset all vars
  6054.  
  6055.              refresh_heads=0;
  6056.  
  6057.              // flag engines off
  6058.  
  6059.              players_engine = 0;
  6060.              remotes_engine = 0;
  6061.  
  6062.              // erase all objects
  6063.  
  6064.              Erase_Fuel_Cells();
  6065.              Erase_Alien();
  6066.              Erase_Wormhole();
  6067.              Erase_Stars();
  6068.              Erase_Asteroids();
  6069.              Erase_Missiles();
  6070.              Erase_Explosions();
  6071.              Erase_Novas();
  6072.  
  6073.              // erase scanner data
  6074.  
  6075.              if (players_scanner==1)
  6076.                 Erase_Blips();
  6077.  
  6078. // BEGIN PLAYER//////////////////////////////////////////////////////////////////
  6079.  
  6080.  
  6081.              Sprite_Erase((sprite_ptr)&players_ship,double_buffer);
  6082.  
  6083.  
  6084. // END PLAYER///////////////////////////////////////////////////////////////////
  6085.  
  6086. // BEGIN REMOTE//////////////////////////////////////////////////////////////////
  6087.  
  6088.  
  6089.              Sprite_Erase_Clip((sprite_ptr)&remotes_ship,double_buffer);
  6090.  
  6091.  
  6092. // END REMOTE///////////////////////////////////////////////////////////////////
  6093.  
  6094.  
  6095. // BEGIN PLAYER//////////////////////////////////////////////////////////////////
  6096.  
  6097.              // move player
  6098.  
  6099.              players_last_x = players_x;
  6100.              players_last_y = players_y;
  6101.  
  6102.              // test if a key is depressed
  6103.  
  6104.              players_key_state = 0;
  6105.  
  6106.              if (players_state==ALIVE)
  6107.              {
  6108.              if (keys_active > 0)
  6109.                 {
  6110.                 // which key ?
  6111.  
  6112.                 if (keyboard_state[MAKE_LEFT] )
  6113.                      {
  6114.                      // rotate left
  6115.  
  6116.                      if (--players_ship.curr_frame < 0)
  6117.                         players_ship.curr_frame = 15;
  6118.  
  6119.                      // add this action to key state
  6120.  
  6121.                      players_key_state += REMOTE_LEFT;
  6122.  
  6123. #if DEBUG
  6124.                      sent_left++;
  6125. #endif
  6126.  
  6127.                      } // end if left
  6128.                 else
  6129.                 if (keyboard_state[MAKE_RIGHT])
  6130.                      {
  6131.                      // rotate right
  6132.  
  6133.                      if (++players_ship.curr_frame > 15)
  6134.                         players_ship.curr_frame = 0;
  6135.  
  6136.                      // add this action to key state
  6137.  
  6138.                      players_key_state += REMOTE_RIGHT;
  6139.  
  6140. #if DEBUG
  6141.                      sent_right++;
  6142. #endif
  6143.  
  6144.  
  6145.                      } // end if right
  6146.  
  6147.                 if (keyboard_state[MAKE_UP] && players_energy>0)
  6148.                      {
  6149.                      // thrust foward
  6150.  
  6151.                      players_xv+=motion_dx[players_ship.curr_frame];
  6152.                      players_yv+=motion_dy[players_ship.curr_frame];
  6153.  
  6154.                      // bound maximum velocity
  6155.  
  6156.                      if (players_xv > 8)
  6157.                         players_xv=8;
  6158.                      else
  6159.                      if (players_xv <-8)
  6160.                         players_xv=-8;
  6161.  
  6162.                      if (players_yv > 8)
  6163.                         players_yv=8;
  6164.                      else
  6165.                      if (players_yv <-8)
  6166.                         players_yv=-8;
  6167.  
  6168.                      // flag engines on
  6169.  
  6170.                      players_engine = 1;
  6171.  
  6172.                      players_energy--;
  6173.  
  6174.                      // add this action to key state
  6175.  
  6176.                      players_key_state += REMOTE_THRUST;
  6177.  
  6178. #if DEBUG
  6179.                      sent_up++;
  6180. #endif
  6181.  
  6182.                      } // end if up
  6183.  
  6184.                 if (keyboard_state[MAKE_SPACE] && !debounce_fire &&
  6185.                     players_active_missiles < 5 && players_energy>0)
  6186.                      {
  6187.                      // fire weapons
  6188.  
  6189.                      Start_Missile(players_x+SHIP_WIDTH/2,players_y+SHIP_HEIGHT/2,
  6190.                                    players_xv+2*motion_dx[players_ship.curr_frame],
  6191.                                    players_yv+2*motion_dy[players_ship.curr_frame],
  6192.                                    10,PLAYER_MISSILE);
  6193.  
  6194.                      // update energy
  6195.  
  6196.                      players_energy-=5;
  6197.  
  6198.                      // now there is one more active missile
  6199.  
  6200.                      players_active_missiles++;
  6201.  
  6202.                      // add this action to key state
  6203.  
  6204.                      players_key_state += REMOTE_FIRE;
  6205.  
  6206.                      // set fire button debounce
  6207.  
  6208.                      debounce_fire = 1;
  6209.  
  6210.                      } // end if weapons
  6211.  
  6212.                  // instrumentation
  6213.  
  6214.                  if (keyboard_state[MAKE_ALT] && !debounce_shields &&
  6215.                      players_cloak==-1 && players_shield_strength>0)
  6216.                      {
  6217.                      // turn the shields on
  6218.  
  6219.                      Shield_Control(THE_PLAYER,1);
  6220.  
  6221.                      Digital_FX_Play(BLZSHLD_VOC,1);
  6222.  
  6223.                      // start timer
  6224.  
  6225.                      players_shield_time = 100;
  6226.  
  6227.                      // add this action to key state
  6228.  
  6229.                      players_key_state += REMOTE_SHIELDS;
  6230.  
  6231.                      // request debounce
  6232.  
  6233.                      debounce_shields = 1;
  6234.  
  6235.                      } // end if shields
  6236.                  else
  6237.                  if (keyboard_state[MAKE_C] && !debounce_cloak && players_energy>0)
  6238.                       {
  6239.                       // toggle the cloaking device
  6240.  
  6241.                       players_cloak = -players_cloak;
  6242.  
  6243.                       Digital_FX_Play(BLZCLK_VOC ,1);
  6244.  
  6245.                       // refresh heads up if it's on
  6246.  
  6247.                       refresh_heads=1;
  6248.  
  6249.                       // request debounce
  6250.  
  6251.                       debounce_cloak = 1;
  6252.  
  6253.                       // add this action to key state
  6254.  
  6255.                       players_key_state += REMOTE_CLOAK;
  6256.  
  6257.                       } // emd if cloak
  6258.                 else
  6259.                 if (keyboard_state[MAKE_H] && !debounce_hud)
  6260.                      {
  6261.                      // toggle the display status
  6262.  
  6263.                      players_heads=-players_heads;
  6264.  
  6265.                      // test if it's on or off
  6266.  
  6267.                      if (players_heads==1)
  6268.                         {
  6269.                         Draw_Heads();
  6270.                         Digital_FX_Play(BLZTAC_VOC ,1);
  6271.                         }
  6272.                      else
  6273.                         Erase_Heads();
  6274.  
  6275.  
  6276.                      // request debounce
  6277.  
  6278.                      debounce_hud = 1;
  6279.  
  6280.                      } // end if heads
  6281.                 else
  6282.                 if (keyboard_state[MAKE_S] && !debounce_scan)
  6283.                      {
  6284.                      // toggle the scanner
  6285.  
  6286.                      players_scanner=-players_scanner;
  6287.  
  6288.                      // test if it's on or off
  6289.  
  6290.                      if (players_scanner==1)
  6291.                         {
  6292.                         Draw_Scanner();
  6293.                         Digital_FX_Play(BLZSCN_VOC ,1);
  6294.                         }
  6295.                      else
  6296.                         Erase_Scanner();
  6297.  
  6298.                      // refresh heads up if it's on
  6299.  
  6300.                      refresh_heads=1;
  6301.  
  6302.                      // request debounce
  6303.  
  6304.                      debounce_scan = 1;
  6305.  
  6306.                      } // end if scanner
  6307.                 else
  6308.                 if (keyboard_state[MAKE_ESC])
  6309.                      {
  6310.                      game_state = GAME_SETUP;
  6311.  
  6312.                      // add this action to key state
  6313.  
  6314.                      players_key_state += REMOTE_ESC;
  6315.  
  6316.                      } // end if escape
  6317.  
  6318.                 } // end if kbhit
  6319.  
  6320.              } // end if player alive
  6321.  
  6322.                // debounce section
  6323.  
  6324.                if (!keyboard_state[MAKE_C])
  6325.                    debounce_cloak=0;
  6326.  
  6327.                if (!keyboard_state[MAKE_H])
  6328.                   debounce_hud=0;
  6329.  
  6330.                if (!keyboard_state[MAKE_S])
  6331.                   debounce_scan=0;
  6332.  
  6333.                if (!keyboard_state[MAKE_SPACE])
  6334.                   debounce_fire=0;
  6335.  
  6336.                if (!keyboard_state[MAKE_ALT])
  6337.                   debounce_shields=0;
  6338.  
  6339.              // send local players data to remote machine
  6340.  
  6341.              if (linked)
  6342.                 {
  6343.  
  6344.                 Serial_Write(players_key_state);
  6345.  
  6346.                 } // end if linked
  6347.  
  6348.              // update energy loss due to normal operation
  6349.  
  6350.              if (players_cloak==1)
  6351.                 players_energy--;
  6352.  
  6353.              if (players_energy>0)
  6354.                 {
  6355.                 players_energy--;
  6356.  
  6357.                 // enable refresh
  6358.  
  6359.                 refresh_heads = 1;
  6360.  
  6361.                 } // end energy update
  6362.              else
  6363.                 players_energy=0;
  6364.  
  6365.  
  6366.              // test if shields are on
  6367.  
  6368.              if (players_shields==1)
  6369.                 {
  6370.                 players_shield_strength-=8;
  6371.  
  6372.                 if (players_shield_strength<0)
  6373.                     players_shield_strength = 0;
  6374.  
  6375.                 // enable refresh
  6376.  
  6377.                 refresh_heads = 1;
  6378.  
  6379.                 } // end if shields are on
  6380.  
  6381.              // test if hud needs refreshing
  6382.  
  6383.              if (players_heads==1 && refresh_heads)
  6384.                 {
  6385.  
  6386.                 Draw_Heads();
  6387.  
  6388.                 // reset refresh flag
  6389.                 refresh_heads = 0;
  6390.  
  6391.                 } // end if hud needs a refresh
  6392.  
  6393.              // translate player and apply friction if engines aren't on
  6394.  
  6395.              players_x+=players_xv;
  6396.              players_y+=players_yv;
  6397.  
  6398.  
  6399.              // test for gravity
  6400.  
  6401.              if (!players_engine)
  6402.                 {
  6403.                 if (++players_gravity >=players_stability)
  6404.                    {
  6405.                    // reset gravity count
  6406.  
  6407.                    players_gravity = 0;
  6408.  
  6409.                    // apply friction (in space!!!). hey it's just a game
  6410.  
  6411.                    if (players_xv>0)
  6412.                       players_xv--;
  6413.                    else
  6414.                    if (players_xv<0)
  6415.                       players_xv++;
  6416.  
  6417.                    if (players_yv>0)
  6418.                       players_yv--;
  6419.                    else
  6420.                    if (players_yv<0)
  6421.                       players_yv++;
  6422.  
  6423.                    } // end if time to apply friction
  6424.  
  6425.                 } // end if engines are off
  6426.  
  6427.  
  6428.              // show engines flicker
  6429.  
  6430.              if (players_engine)
  6431.                 {
  6432.                 if (++players_flame_count > players_flame_time)
  6433.                    {
  6434.                    // turn engines on
  6435.  
  6436.                    Write_Color_Reg(PLAYERS_ENGINE_REG,
  6437.                                    (RGB_color_ptr)&players_engine_color);
  6438.  
  6439.                    // reset counter
  6440.  
  6441.                    players_flame_count = 0;
  6442.  
  6443.                    } // end if time to toggle engines
  6444.                 else
  6445.                    {
  6446.                    // turn engines off
  6447.  
  6448.                    Write_Color_Reg(PLAYERS_ENGINE_REG,
  6449.                                    (RGB_color_ptr)&primary_black);
  6450.  
  6451.                    } // end else
  6452.  
  6453.                 } // end if engines are on
  6454.  
  6455.  
  6456.              // test if shields should turn off
  6457.  
  6458.              if (players_shield_time>0)
  6459.                 {
  6460.                 // try and turn off shields
  6461.  
  6462.                 if (--players_shield_time<=0)
  6463.                    Shield_Control(THE_PLAYER,0);
  6464.                 else
  6465.                    {
  6466.                    // which shield colors?
  6467.  
  6468.                    if (players_ship_type==GRYFON_SHIP)
  6469.                       {
  6470.                       if ((players_shield_color.blue+=8) >=64)
  6471.                          players_shield_color.blue = 24;
  6472.  
  6473.                       Write_Color_Reg(PLAYERS_SHIELD_REG,(RGB_color_ptr)&players_shield_color);
  6474.                       }
  6475.                    else
  6476.                       {
  6477.                       // must be a raptor
  6478.  
  6479.                       if ((players_shield_color.red+=8) >=64)
  6480.                          players_shield_color.red = 24;
  6481.  
  6482.                       Write_Color_Reg(PLAYERS_SHIELD_REG,(RGB_color_ptr)&players_shield_color);
  6483.  
  6484.                       } // end else
  6485.  
  6486.                    } // end else modulate shields
  6487.  
  6488.                 } // end if
  6489.  
  6490.  
  6491.  
  6492.  
  6493.  
  6494.              // compute players delta
  6495.  
  6496.              players_dx = players_last_x - players_x;
  6497.              players_dy = players_last_y - players_y;
  6498.  
  6499.              // do player boundary detection
  6500.              // we are going to wrap universe around, but maybe placing
  6501.              // a barrier at edges would be better?
  6502.  
  6503.              if (players_x > UNIVERSE_WIDTH)
  6504.                 players_x = players_x - UNIVERSE_WIDTH;
  6505.              else
  6506.              if (players_x < 0)
  6507.                 players_x = players_x + UNIVERSE_WIDTH;
  6508.  
  6509.              if (players_y > UNIVERSE_HEIGHT)
  6510.                 players_y = players_y - UNIVERSE_HEIGHT;
  6511.              else
  6512.              if (players_y < 0)
  6513.                 players_y = players_y + UNIVERSE_HEIGHT;
  6514.  
  6515.  
  6516. //END PLAYER///////////////////////////////////////////////////////////////////
  6517.  
  6518.  
  6519.  
  6520.  
  6521. // BEGIN REMOTE//////////////////////////////////////////////////////////////////
  6522.  
  6523.  
  6524.              // only process remote if machines are linked
  6525.  
  6526.              if (linked)
  6527.              {
  6528.  
  6529.              // move remote
  6530.  
  6531.              remotes_last_x = remotes_x;
  6532.              remotes_last_y = remotes_y;
  6533.  
  6534.              // reset remotes input
  6535.  
  6536.              remotes_key_state = 0;
  6537.  
  6538.              // get input from remote machine
  6539.  
  6540.              remotes_key_state = Serial_Read_Wait();
  6541.  
  6542.              // test if a key is depressed
  6543.  
  6544.  
  6545.              if (remotes_state==ALIVE)
  6546.              {
  6547.  
  6548.              if (remotes_key_state > 0)
  6549.                 {
  6550.                 // which key ?
  6551.  
  6552.                 if ((remotes_key_state & REMOTE_LEFT))
  6553.                      {
  6554.                      // rotate left
  6555.  
  6556.                      if (--remotes_ship.curr_frame < 0)
  6557.                         remotes_ship.curr_frame = 15;
  6558. #if DEBUG
  6559.  
  6560.                      rec_left++;
  6561. #endif
  6562.  
  6563.                      } // end if left
  6564.                 else
  6565.                 if ((remotes_key_state & REMOTE_RIGHT))
  6566.                      {
  6567.                      // rotate right
  6568.  
  6569.                      if (++remotes_ship.curr_frame > 15)
  6570.                         remotes_ship.curr_frame = 0;
  6571.  
  6572. #if DEBUG
  6573.                      rec_right++;
  6574. #endif
  6575.  
  6576.                      } // end if right
  6577.  
  6578.                 if ((remotes_key_state & REMOTE_THRUST) && remotes_energy>0)
  6579.                      {
  6580.                      // thrust foward
  6581.  
  6582.                      remotes_xv+=motion_dx[remotes_ship.curr_frame];
  6583.                      remotes_yv+=motion_dy[remotes_ship.curr_frame];
  6584.  
  6585.                      // bound maximum velocity
  6586.  
  6587.                      if (remotes_xv > 8)
  6588.                         remotes_xv=8;
  6589.                      else
  6590.                      if (remotes_xv <-8)
  6591.                         remotes_xv=-8;
  6592.  
  6593.                      if (remotes_yv > 8)
  6594.                         remotes_yv=8;
  6595.                      else
  6596.                      if (remotes_yv <-8)
  6597.                         remotes_yv=-8;
  6598.  
  6599.                      // flag engines on
  6600.  
  6601.                      remotes_engine = 1;
  6602.                      remotes_energy--;
  6603.  
  6604. #if DEBUG
  6605.                      rec_up++;
  6606. #endif
  6607.  
  6608.  
  6609.                      } // end if up
  6610.  
  6611.                 if ((remotes_key_state & REMOTE_FIRE) && remotes_active_missiles < 5 &&
  6612.                     remotes_energy>0)
  6613.                      {
  6614.                      // fire weapons
  6615.  
  6616.                      Start_Missile(remotes_x+SHIP_WIDTH/2,remotes_y+SHIP_HEIGHT/2,
  6617.                                    remotes_xv+2*motion_dx[remotes_ship.curr_frame],
  6618.                                    remotes_yv+2*motion_dy[remotes_ship.curr_frame],
  6619.                                    10,REMOTE_MISSILE);
  6620.  
  6621.                      // decrease energy
  6622.  
  6623.                      remotes_energy-=5;
  6624.  
  6625.                      // now there is one more active missile
  6626.  
  6627.                      remotes_active_missiles++;
  6628.  
  6629.                      } // end if weapons
  6630.  
  6631.                  // instrumentation
  6632.  
  6633.                  if ((remotes_key_state & REMOTE_SHIELDS) &&
  6634.                     remotes_cloak==-1 && remotes_shield_strength>0)
  6635.                      {
  6636.                      // turn the shields on
  6637.  
  6638.                      Shield_Control(THE_REMOTE,1);
  6639.  
  6640.                      // start timer
  6641.  
  6642.                      remotes_shield_time = 100;
  6643.  
  6644.                      } // end if shields
  6645.                  else
  6646.                  if ((remotes_key_state & REMOTE_CLOAK) && remotes_energy>0)
  6647.                       {
  6648.                       // toggle the cloaking device
  6649.  
  6650.                       remotes_cloak = -remotes_cloak;
  6651.  
  6652.                       } // emd if cloak
  6653.                 else
  6654.                 if ((remotes_key_state & REMOTE_ESC))
  6655.                      {
  6656.  
  6657.                      game_state = GAME_SETUP;
  6658.  
  6659.                      } // end if escape
  6660.  
  6661.                 } // end if kbhit
  6662.  
  6663.              // update energy loss due to normal operation
  6664.  
  6665.              if (remotes_cloak==1)
  6666.                 remotes_energy--;
  6667.  
  6668.              if (remotes_energy>0)
  6669.                 {
  6670.                 remotes_energy--;
  6671.  
  6672.                 } // end energy update
  6673.              else
  6674.                 remotes_energy=0;
  6675.  
  6676.              // test if shields are on
  6677.  
  6678.              if (remotes_shields==1)
  6679.                 {
  6680.                 remotes_shield_strength-=8;
  6681.  
  6682.                 if (remotes_shield_strength<0)
  6683.                     remotes_shield_strength = 0;
  6684.  
  6685.                 } // end if shields are on
  6686.  
  6687.              } // end if remote alive
  6688.  
  6689.              // translate remote and apply friction if engines aren't on
  6690.  
  6691.              remotes_x+=remotes_xv;
  6692.              remotes_y+=remotes_yv;
  6693.  
  6694.              // test for gravity
  6695.  
  6696.              if (!remotes_engine)
  6697.                 {
  6698.                 if (++remotes_gravity >=remotes_stability)
  6699.                    {
  6700.                    // reset gravity count
  6701.  
  6702.                    remotes_gravity = 0;
  6703.  
  6704.                    // apply friction (in space!!!). hey it's just a game
  6705.  
  6706.                    if (remotes_xv>0)
  6707.                       remotes_xv--;
  6708.                    else
  6709.                    if (remotes_xv<0)
  6710.                       remotes_xv++;
  6711.  
  6712.                    if (remotes_yv>0)
  6713.                       remotes_yv--;
  6714.                    else
  6715.                    if (remotes_yv<0)
  6716.                       remotes_yv++;
  6717.  
  6718.                    } // end if time to apply friction
  6719.  
  6720.                 } // end if engines are off
  6721.  
  6722.              // show engines flicker
  6723.  
  6724.              if (remotes_engine)
  6725.                 {
  6726.                 if (++remotes_flame_count > remotes_flame_time)
  6727.                    {
  6728.                    // turn engines on
  6729.  
  6730.                    Write_Color_Reg(REMOTES_ENGINE_REG,
  6731.                                    (RGB_color_ptr)&remotes_engine_color);
  6732.  
  6733.                    // reset counter
  6734.  
  6735.                    remotes_flame_count = 0;
  6736.  
  6737.                    } // end if time to toggle engines
  6738.                 else
  6739.                    {
  6740.                    // turn engines off
  6741.  
  6742.                    Write_Color_Reg(REMOTES_ENGINE_REG,
  6743.                                    (RGB_color_ptr)&primary_black);
  6744.  
  6745.                    } // end else
  6746.  
  6747.                 } // end if engines are on
  6748.  
  6749.  
  6750.              // test if shields should turn off
  6751.  
  6752.              if (remotes_shield_time>0)
  6753.                 {
  6754.                 // try and turn off shields
  6755.  
  6756.                 if (--remotes_shield_time<=0)
  6757.                    Shield_Control(THE_REMOTE,0);
  6758.                 else
  6759.                    {
  6760.                    // which shield colors?
  6761.  
  6762.                    if (remotes_ship_type==GRYFON_SHIP)
  6763.                       {
  6764.                       if ((remotes_shield_color.blue+=8) >=64)
  6765.                          remotes_shield_color.blue = 24;
  6766.  
  6767.                       Write_Color_Reg(REMOTES_SHIELD_REG,(RGB_color_ptr)&remotes_shield_color);
  6768.                       }
  6769.                    else
  6770.                       {
  6771.                       // must be a raptor
  6772.  
  6773.                       if ((remotes_shield_color.red+=8) >=64)
  6774.                          remotes_shield_color.red = 24;
  6775.  
  6776.                       Write_Color_Reg(REMOTES_SHIELD_REG,(RGB_color_ptr)&remotes_shield_color);
  6777.  
  6778.                       } // end else
  6779.  
  6780.                    } // end else modulate shields
  6781.  
  6782.                 } // end if
  6783.  
  6784.              // compute remotes delta
  6785.  
  6786.              remotes_dx = remotes_last_x - remotes_x;
  6787.              remotes_dy = remotes_last_y - remotes_y;
  6788.  
  6789.              // do remotes boundary detection
  6790.              // we are going to wrap universe around, but maybe placing
  6791.              // a barrier at edges would be better?
  6792.  
  6793.              if (remotes_x > UNIVERSE_WIDTH)
  6794.                 remotes_x = remotes_x - UNIVERSE_WIDTH;
  6795.              else
  6796.              if (remotes_x < 0)
  6797.                 remotes_x = remotes_x + UNIVERSE_WIDTH;
  6798.  
  6799.              if (remotes_y > UNIVERSE_HEIGHT)
  6800.                 remotes_y = remotes_y - UNIVERSE_HEIGHT;
  6801.              else
  6802.              if (remotes_y < 0)
  6803.                 remotes_y = remotes_y + UNIVERSE_HEIGHT;
  6804.  
  6805.              } // end if linked
  6806.  
  6807. //END REMOTE///////////////////////////////////////////////////////////////////
  6808.  
  6809.              // call AI logic for alien
  6810.  
  6811.              Alien_Control();
  6812.  
  6813.              // move all objects
  6814.  
  6815.              Move_Stars();
  6816.              Move_Alien();
  6817.              Move_Asteroids();
  6818.              Move_Missiles();
  6819.              Animate_Explosions();
  6820.              Move_Novas();
  6821.              Animate_Wormhole();
  6822.              Animate_Fuel_Cells();
  6823.  
  6824.              // perform death sequence logic for player
  6825.  
  6826.              if (players_state==DYING)
  6827.                 {
  6828.  
  6829.                 // decrement death counter
  6830.  
  6831.                 if (--players_death_count<=0)
  6832.                    {
  6833.                    // reset player to starting position
  6834.  
  6835.                    Reset_Player();
  6836.  
  6837.                    // test if this is it...
  6838.  
  6839.                    if (--players_num_ships==0)
  6840.                       {
  6841.                       // return to setup
  6842.  
  6843.                       game_state = GAME_SETUP;
  6844.                       winner = WINNER_REMOTE;
  6845.  
  6846.                       } // end if it's all over
  6847.  
  6848.                       // refresh hud in any case
  6849.  
  6850.                       if (players_heads==1)
  6851.                          Draw_Heads();
  6852.  
  6853.                    } // end if death done
  6854.  
  6855.                 } // end if player dying
  6856.  
  6857.  
  6858.              // perform death sequence logic for remote
  6859.  
  6860.              if (linked && remotes_state==DYING)
  6861.                 {
  6862.  
  6863.                 // decrement death counter
  6864.  
  6865.                 if (--remotes_death_count<=0)
  6866.                    {
  6867.                    // reset remote to starting position
  6868.  
  6869.                    Reset_Remote();
  6870.  
  6871.                    // test if this is it...
  6872.  
  6873.                    if (--remotes_num_ships==0)
  6874.                       {
  6875.  
  6876.                       game_state = GAME_SETUP;
  6877.                       winner = WINNER_PLAYER;
  6878.  
  6879.                       } // end if it's all over
  6880.  
  6881.                    } // end if death done
  6882.  
  6883.                 } // end if remote dying
  6884.  
  6885.              // scan under all objects
  6886.  
  6887.              Under_Fuel_Cells();
  6888.              Under_Stars();
  6889.              Under_Asteroids();
  6890.  
  6891.              Under_Missiles();
  6892.              Under_Explosions();
  6893.              Under_Novas();
  6894.              Under_Wormhole();
  6895.              Under_Alien();
  6896.  
  6897.              // render scanner with new data
  6898.  
  6899.              if (players_scanner==1)
  6900.                 Under_Blips();
  6901.  
  6902. // BEGIN PLAYER ////////////////////////////////////////////////////////////////
  6903.  
  6904.              Sprite_Under((sprite_ptr)&players_ship,double_buffer);
  6905.  
  6906. // END PLAYER //////////////////////////////////////////////////////////////////
  6907.  
  6908.  
  6909. // BEGIN REMOTE ////////////////////////////////////////////////////////////////
  6910.  
  6911.              // translate remote to player
  6912.  
  6913.              px_window = players_x - 160+11;
  6914.              py_window = players_y - 100+9;
  6915.  
  6916.              remotes_ship.x = remotes_x - px_window;
  6917.              remotes_ship.y = remotes_y - py_window;
  6918.  
  6919.              Sprite_Under_Clip((sprite_ptr)&remotes_ship,double_buffer);
  6920.  
  6921. // END REMOTE //////////////////////////////////////////////////////////////////
  6922.  
  6923.              // draw all objects
  6924.  
  6925.              Draw_Wormhole();
  6926.              Draw_Fuel_Cells();
  6927.              Draw_Stars();
  6928.              Draw_Asteroids();
  6929.  
  6930. //BEGIN PLAYER//////////////////////////////////////////////////////////////////
  6931.  
  6932.              // display proper image of ship depending on state of engines
  6933.              // and cloak
  6934.  
  6935.  
  6936.              // but first is there a ship?
  6937.  
  6938.              if (players_state==ALIVE)
  6939.              {
  6940.              // test if ship is totally cloaked
  6941.              if (players_cloak==-1)
  6942.                 {
  6943.                 // ship isn't cloaked
  6944.  
  6945.                 if (players_engine)
  6946.                    {
  6947.                    // index into frames with thrust
  6948.  
  6949.                    players_ship.curr_frame+=16;
  6950.  
  6951.                    // draw the ship with thrust showing
  6952.  
  6953.                    Sprite_Draw((sprite_ptr)&players_ship,double_buffer,1);
  6954.  
  6955.                    // restore the original frame
  6956.  
  6957.                    players_ship.curr_frame-=16;
  6958.  
  6959.                    } // end if engines are on
  6960.                 else
  6961.                    {
  6962.                    // no engines
  6963.  
  6964.                    Sprite_Draw((sprite_ptr)&players_ship,double_buffer,1);
  6965.  
  6966.                    } // end else no engine flicker
  6967.  
  6968.                 } // end if not cloaked
  6969.              else
  6970.                 {
  6971.                 // player is cloaked
  6972.  
  6973.                 // test if player is trying to engage shields
  6974.  
  6975.                 if (players_shields)
  6976.                    {
  6977.                    // force shields off
  6978.  
  6979.                    Shield_Control(THE_PLAYER,0);
  6980.                    players_shield_time=0;
  6981.  
  6982.                    } // end if trying to engage sheilds
  6983.  
  6984.                 } // end else ship cloaked
  6985.  
  6986.              } // end if player alive
  6987.  
  6988. //END PLAYER//////////////////////////////////////////////////////////////////
  6989.  
  6990.  
  6991. //BEGIN REMOTE//////////////////////////////////////////////////////////////////
  6992.  
  6993.              // display proper image of ship depending on state of engines
  6994.              // and cloak
  6995.  
  6996.              // but first is there is a ship?
  6997.  
  6998.              if (remotes_state==ALIVE)
  6999.              {
  7000.              // test if ship is totally cloaked
  7001.              if (remotes_cloak==-1)
  7002.                 {
  7003.                 // ship isn't cloaked
  7004.  
  7005.                 if (remotes_engine)
  7006.                    {
  7007.                    // index into frames with thrust
  7008.  
  7009.                    remotes_ship.curr_frame+=16;
  7010.  
  7011.                    // draw the ship with thrust showing
  7012.  
  7013.                    Sprite_Draw_Clip((sprite_ptr)&remotes_ship,double_buffer,1);
  7014.  
  7015.                    // restore the original frame
  7016.  
  7017.                    remotes_ship.curr_frame-=16;
  7018.  
  7019.                    } // end if engines are on
  7020.                 else
  7021.                    {
  7022.                    // no engines
  7023.  
  7024.                    Sprite_Draw_Clip((sprite_ptr)&remotes_ship,double_buffer,1);
  7025.  
  7026.                    } // end else no engine flicker
  7027.  
  7028.                 } // end if not cloaked
  7029.              else
  7030.                 {
  7031.                 // player is cloaked
  7032.  
  7033.                 // test if player is trying to engage shields
  7034.  
  7035.                 if (remotes_shields)
  7036.                    {
  7037.                    // force shields off
  7038.  
  7039.                    Shield_Control(THE_REMOTE,0);
  7040.                    remotes_shield_time=0;
  7041.  
  7042.                    } // end if trying to engage sheilds
  7043.  
  7044.                 } // end else ship cloaked
  7045.  
  7046.              } // end if remote is alive
  7047.  
  7048.  
  7049. //END REMOTE//////////////////////////////////////////////////////////////////
  7050.  
  7051.              // draw remaining priority objects
  7052.  
  7053.              Draw_Missiles();
  7054.              Draw_Alien();
  7055.              Draw_Explosions();
  7056.              Draw_Novas();
  7057.  
  7058.              // render scanner with new data
  7059.  
  7060.              if (players_scanner==1)
  7061.                 Draw_Blips();
  7062.  
  7063.              // display coordinates and score
  7064.  
  7065.              sprintf(buffer,"COORDINATES:[%d,%d]    ",players_x,players_y);
  7066.              Font_Engine_1(0,0,0,0,buffer,double_buffer);
  7067.  
  7068.              sprintf(buffer,"SCORE: %d",players_score);
  7069.              Font_Engine_1(250,0,0,0,buffer,double_buffer);
  7070.  
  7071. #if DEBUG
  7072.              // diagnostic stuff
  7073.  
  7074.              sprintf(buffer,"REMOTE:[%d,%d]    ",remotes_x,remotes_y);
  7075.              Font_Engine_1(0,10,0,0,buffer,double_buffer);
  7076.  
  7077.              sprintf(buffer,"SENT: R=%d L=%d U=%d ",sent_right,sent_left,sent_up);
  7078.              Font_Engine_1(0,20,0,0,buffer,double_buffer);
  7079.  
  7080.              sprintf(buffer,"REC: R=%d L=%d U=%d ",rec_right,rec_left,rec_up);
  7081.              Font_Engine_1(0,30,0,0,buffer,double_buffer);
  7082.  
  7083.              // end diagnostic stuff
  7084.  
  7085. #endif
  7086.  
  7087.              // display double buffer
  7088.  
  7089.              Display_Double_Buffer(double_buffer,0);
  7090.  
  7091.              // lock onto 18 frames per second max
  7092.  
  7093.              while((Timer_Query()-starting_time)<1);
  7094.  
  7095.              // check on music
  7096.  
  7097.              if (music_enabled)
  7098.              {
  7099.              if (Music_Status()==2 || Music_Status()==0)
  7100.                 {
  7101.  
  7102.                 // advance to next sequence
  7103.  
  7104.                 if (++game_seq_index==18)
  7105.                    game_seq_index=0;
  7106.  
  7107.                 Music_Play((music_ptr)&song,game_sequence[game_seq_index]);
  7108.  
  7109.                 } // end if
  7110.  
  7111.              } // end if music enabled
  7112.  
  7113.              } // end game loop
  7114.  
  7115.         // test if there is a winner or user just decided to exit
  7116.  
  7117.         if (winner==WINNER_REMOTE)
  7118.            {
  7119.            // tell player remote is winner
  7120.  
  7121.            Tech_Print(128,80,"CEASE COMBAT!",video_buffer);
  7122.  
  7123.            if (music_enabled)
  7124.               {
  7125.               Music_Stop();
  7126.               Music_Play((music_ptr)&song,11);
  7127.               }
  7128.            Time_Delay(25);
  7129.            Digital_FX_Play(BLZLOS_VOC,2);
  7130.            Tech_Print(120,100,"YOU ARE DEFEATED",video_buffer);
  7131.            Time_Delay(50);
  7132.  
  7133.            } // end if remote won
  7134.         else
  7135.         if (winner==WINNER_PLAYER)
  7136.            {
  7137.            // tell player he is winner
  7138.  
  7139.            Tech_Print(128,80,"CEASE COMBAT!",video_buffer);
  7140.            if (music_enabled)
  7141.               {
  7142.               Music_Stop();
  7143.               Music_Play((music_ptr)&song,11);
  7144.               }
  7145.            Time_Delay(25);
  7146.            Digital_FX_Play(BLZWIN_VOC,2);
  7147.            Tech_Print(115,100,"YOU ARE VICTORIOUS",video_buffer);
  7148.            Time_Delay(50);
  7149.  
  7150.            } // end if player won
  7151.  
  7152.         // do all exit clean up here to move back to the setup state
  7153.  
  7154.         Screen_Transition(SCREEN_DARKNESS);
  7155.  
  7156.         // restart intro music
  7157.  
  7158.         if (music_enabled)
  7159.            {
  7160.            // stop game music, start intro music again
  7161.  
  7162.            intro_seq_index=0;
  7163.            Music_Stop();
  7164.            Music_Play((music_ptr)&song,intro_sequence[intro_seq_index]);
  7165.  
  7166.            } // end if music enabled
  7167.  
  7168.         } // end if running
  7169.  
  7170.      } // end main system event loop
  7171.  
  7172. ///////////////////////////////////////////////////////////////////////////////
  7173.  
  7174. // exit in a very cool way
  7175.  
  7176. Screen_Transition(SCREEN_DARKNESS);
  7177.  
  7178. // free up all resources
  7179.  
  7180. Delete_Double_Buffer();
  7181.  
  7182. // remove the keyboard handler
  7183.  
  7184. Keyboard_Remove_Driver();
  7185.  
  7186. // close down FX
  7187.  
  7188. Digital_FX_Close();
  7189.  
  7190. // show the credits
  7191.  
  7192. Closing_Screen();
  7193.  
  7194. // close down music
  7195.  
  7196. Music_Close();
  7197.  
  7198. Set_Graphics_Mode(TEXT_MODE);
  7199.  
  7200. // see ya!
  7201.  
  7202. printf("\nSTARBLAZER Shutdown Normal.\n");
  7203.  
  7204. } // end main
  7205.  
  7206.