/*
  Jalaxa

  A space shoot-up for Java

  by Eduardo Fernandez
  based on GalaXa by Bill Kendrick
  kendrick@zippy.sonoma.edu
  http://zippy.sonoma.edu/kendrick/
  
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;

public class Jalaxa extends Applet implements Runnable {


    boolean paused=false;
    boolean stopped=false;
    static int FRAMERATE = 20; /* 50 fps - Original value */
    static long sync_then = new Date().getTime();
    static long sync_now;
    static long sync_timepad = 0;

    public void syncRate() {
	
	sync_now = new Date().getTime();
	
	sync_timepad += (FRAMERATE - (sync_now - sync_then));
	sync_then = sync_now;
	
	if (sync_timepad > 0) {
	    try {
		Thread.sleep(sync_timepad);
		}
	    catch (Exception e) {
	    }
	    sync_then += sync_timepad;
	    sync_timepad = 0;
	    ga.enableDrawing();
	    }
	else {
	    /*	    try {
		Thread.sleep(FRAMERATE/4);
	    }
	    catch (Exception e) {
	    }
	    sync_timepad -= FRAMERATE/4;*/
	    ga.disableDrawing();
	}

	if (stopped) {
	    synchronized (this) {
		while (stopped) {
		    try {
			wait();
		    }
		    catch (InterruptedException e) {
		    }
		}
	    }
	    ga.enableDrawing();
	}
    }
    
    
    static final int EVENTLOOP = 100;
	
    static final int KEY_LEFT = 0;
    static final int KEY_RIGHT = 1;
	
    static final int MAX_SHOTS_AT_A_TIME = 3;

    static final int DIR_UP = 0;
    static final int DIR_UPRIGHT = 1;
    static final int DIR_RIGHT = 2;
    static final int DIR_DOWNRIGHT = 3;
    static final int DIR_DOWN = 4;
    static final int DIR_DOWNLEFT = 5;
    static final int DIR_LEFT = 6;
    static final int DIR_UPLEFT = 7;

    static final int MAX_ALIENS = 22;
    static final int MAX_BULLETS = 16;
    static final int MAX_EXPLOSIONBITS = 32;
    static final int MAX_EXPLOSIONS = 1;
    static final int MAX_STARS = 10;

    static final int BULLET_SIZE = 8;

    static final int MODE_ENTER = 0;
    static final int MODE_WAIT = 1;
    static final int MODE_ATTACK = 2;
    static final int MODE_RETREAT = 3;
    static final int MODE_SUCK = 4;

    static final int GAMEMODE_WARP = 0;
    static final int GAMEMODE_ENTER = 1;
    static final int GAMEMODE_NORMAL = 2;
    static final int GAMEMODE_SUCK = 3;

    static final int TYPE_MASTER_1 = 0;
    static final int TYPE_GUARD = 1;
    static final int TYPE_GUARDA = 2;
    static final int TYPE_PAWNA = 3;
    static final int TYPE_PAWN = 4;
    static final int TYPE_MASTER_0 = 5;

    static final int OWNER_PLAYER = 0;
    static final int OWNER_ALIEN = 1;

    static final int 	SUCK_HEIGHT = (GameArea.HEIGHT - 96);

    static final int HELPSHAPE_LEFT = 0;
    static final int HELPSHAPE_CENTER = 1;
    static final int HELPSHAPE_RIGHT = 2;

    static final int TITLEMODE_TITLE = 0;
    static final int TITLEMODE_HELP_1 = 1;
    static final int TITLEMODE_HELP_2 = 2;
    static final int TITLEMODE_HELP_3 = 3;
    static final int TITLEMODE_HIGHS = 4;
    static final int NUM_TITLEMODES = 5;

    static final int MAX_FIREWORKS = 5;
    static final int MAX_FIREWORKSBITS = 20;

    static final int MAX_ASTEROIDS = 6;

    int[] scores = {250, 100, 100, 50, 50, 250};

/* Typedefs: */

    public class player_type {
	boolean alive;
	int x, y;
	int size;
	int shots_out;
    };

    public class alien_type {
      boolean alive;
      boolean hasship;
      boolean isship;
	int type, mode, goaway;
	int x, y;
	int homex, homey;
	int gotox, gotoy;
	int dir;
	int sucktime;
	int hitpoints;
    };

    public class bullet_type {
      boolean alive;
	int owner;
	int x, y;
	int xm, ym;
    };

    public class explosionbit_type {
      boolean alive;
	int time;
	int x, y;
	int xm, ym;
    };
    
    public class explosion_type {
      boolean alive;
	int frame;
	int x, y;
    };

    public class planet_type {
	boolean alive;
	int x, y;
	int shape;
    };

    public class star_type {
	int x, y;
	int speed;
    };

    public class scoretable_type {
	int score = 0;
	String name = "No1";
    };

    public class fireworksbit_type {
	float x, y;
	float xm, ym;
    };

    public class fireworks_type {
	boolean alive;
	int time;
	float x, y;
	float xm, ym;
	fireworksbit_type[] bit = new fireworksbit_type[MAX_FIREWORKSBITS];
	public fireworks_type() {
	    for (int x=0;x<MAX_FIREWORKSBITS;x++) {
		bit[x] = new fireworksbit_type();
	    }
	}
    };
    
    public class asteroid_type {
	boolean alive;
      int size;
	int x, y;
	int xm, ym;
	int anim, animm, animspeed;
    };
    

    /* Globals: */
    
    player_type player = new player_type();
    player_type extraship = new player_type();
    planet_type planet = new planet_type();
    
    alien_type[] aliens = new alien_type[MAX_ALIENS];
    star_type[] stars = new star_type[MAX_STARS];
    asteroid_type[] asteroids = new asteroid_type[MAX_ASTEROIDS];
    bullet_type[] bullets = new bullet_type[MAX_BULLETS];
    explosionbit_type[] explosionbits = new explosionbit_type[MAX_EXPLOSIONBITS];
    scoretable_type[] highscores = new scoretable_type[10];
    scoretable_type[] highlevels = new scoretable_type[10];
    explosion_type[] explosions = new explosion_type[MAX_EXPLOSIONS];
    
    float highhitratio = 0f;
    String highhitrationame = "No1";
    int[] arrow_key = new int[2];
    int starspeed, starspeedm, starspeedtime, wantstarspeed, faststarspeed,
	changestarspeed, alien_responsible;
    int gamemode, level, alien_speed, flashscreen, maxlevel, score,
	lives, gameover;
  boolean giant_bugs  =false;
    float num_shots, num_hits;
    int highscoreslot, highlevelslot, highhitratioslot;

    public static void main(String[] s) {
	new AppletShell("Jalaxa v0.1",GameArea.WIDTH,GameArea.HEIGHT
			,false,true,new Jalaxa(),s);
    }
    
    public void init() {
	System.out.println("Initializing...");
	for (int x=0; x<aliens.length;x++) {
	    aliens[x] = new alien_type();
	}
	for (int x=0; x<stars.length;x++) {
	    stars[x] = new star_type();
	}

	for (int x=0; x<asteroids.length;x++) {
	    asteroids[x] = new asteroid_type();
	}

	for (int x=0; x<bullets.length;x++) {
	    bullets[x] = new bullet_type();
	}

	for (int x=0; x<explosionbits.length;x++) {
	    explosionbits[x] = new explosionbit_type();
	}

	for (int x=0; x<highscores.length;x++) {
	    highscores[x] = new scoretable_type();
	}

	for (int x=0; x<highlevels.length;x++) {
	    highlevels[x] = new scoretable_type();
	}

	for (int x=0; x<explosions.length;x++) {
	    explosions[x] = new explosion_type();
	}


	ga = new GameArea(this);
	setLayout(new BorderLayout());
	add(ga,BorderLayout.CENTER);
	setVisible(true);
	km=new KeyMonitor();
	km.addGenerator(ga);
	km.addGenerator(this);
    }
    Thread thread;
    GameArea ga;
    KeyMonitor km;

    public void start() {
	if (thread == null) {
	    thread= new Thread(this);
	    thread.start();
	}
	else {
	    stopped = false;
	    synchronized (this) {
		notify();
	    }
	}
    }
    public void stop() {
	paused = true;
	stopped = true;	
    }
    
    /* -- MAIN THREAD -- */
    
    public void run() {
	int titlemode;	
  
	/* Setup: */
	
	maxlevel = 20;
	System.out.println("GameArea Init");
	ga.init();	
	System.out.println("GameArea Init Done");
	loadhighscores();
  
	titlemode = TITLEMODE_TITLE;
	
	highscoreslot = -1;
	highlevelslot = -1;
	highhitratioslot = -1;
	level = 1;
  
	do {
	    title(titlemode);
	    
	    highscoreslot = -1;
	    highlevelslot = -1;
	    highhitratioslot = -1;
	    
	    titlemode = game();
	}
	while (true);
  
	//	savehighscores();
	//	shutdown();
    }


    /* Title mode: */

    void title(int titlemode)
    {
	int key;
	int i, j, titlex, titley, levelx, levely, creditsx, creditsy,
	    titlemode_section, nextmode, spin, title_size,
	    checkmode, flashscreen, titlemode_section_fast;
	int counter = 0;
	boolean done = false;
	
	//	silence(sound_fs); /* Sound Support is not in this version */
	
	
	/* Quick refs. for positions: */
	
	titlex = (GameArea.WIDTH - ga.object_width[ga.OBJ_TITLE]) / 2;
	titley = (GameArea.WIDTH - ga.object_height[ga.OBJ_TITLE] - ga.object_height[ga.OBJ_CREDITS]) / 2;
	creditsx = (GameArea.WIDTH - ga.object_width[ga.OBJ_CREDITS]) / 2;
	creditsy = titley + ga.object_height[ga.OBJ_TITLE] + 8;
	levelx = (GameArea.WIDTH - 48) / 2;
	levely = creditsy + ga.object_height[ga.OBJ_CREDITS] + 16;
	
	
	/* Reset everything: */
	
	initstars();
	
	titlemode_section = 0;
	titlemode_section_fast = 0;
	title_size = 1000;
	flashscreen = 0;
	ga.clearbackbuffer();
	
	/* I do this to put the clipmask in the right place: */
	
	ga.drawshape(titlex, titley, ga.OBJ_TITLE);
	
	
	/* Title screen main loop: */
	
	do {
	    /* Handle counters/mode switchers/etc.: */
	    
	    counter++;
	    
	    if (counter % 50 == 0)
		titlemode_section++;
	    
	    if (counter % 15 == 0)
		titlemode_section_fast++;
	    
	    
	    spin = (counter / 6) % 8;
	    	    	    
	    /* Handle keyboard input: */
	    
	    nextmode = 0;
	    checkmode = 0;
	    
	    if (km.wasPressed(KeyEvent.VK_SPACE)) {
		done = true;
	    }
	    if (km.wasPressed(KeyEvent.VK_1)) {
		nextmode = 1;
	    }
	    if (km.wasPressed(KeyEvent.VK_2)) {
		nextmode = 1;
		titlemode = TITLEMODE_HIGHS - 1;
	    }
	    if (km.wasPressed(KeyEvent.VK_L)) {
		level++;
		if (level > maxlevel)
		    level = 1;
		checkmode = 1;
		
		//		playsound(SND_SHOT);
	    }
	    if (km.wasPressed(KeyEvent.VK_K)) {
		level--;
		if (level < 1)
		    level = maxlevel;
		checkmode = 1;
		
		//		playsound(SND_SHOT);
	    }
	    
	    km.reset();
	
	    if (checkmode == 1 && titlemode != TITLEMODE_TITLE) {		
		titlemode = TITLEMODE_TITLE - 1;
		nextmode = 1;
	    }
	    
	    
	    /* Redraw screen: */
	    
	    if (flashscreen != 0 && (counter % 2) == 1) {
		flashscreen--;
		ga.clearbackbufferinvert();
	    }
	    else
		ga.clearbackbuffer();
	    
		
	    
	    /* Draw and move stars: */
	    
	    for (i = 0; i < MAX_STARS; i++) {
		ga.g_backbuffer.setColor(Color.gray);
		ga.g_backbuffer.drawLine(stars[i].x, stars[i].y,stars[i].x, stars[i].y);
		
		
		stars[i].y = stars[i].y + (stars[i].speed + 3);
	    
		if (stars[i].y > ga.HEIGHT) {
		stars[i].x = Randnum.getInt(ga.WIDTH);
		stars[i].y = -Randnum.getInt(20);
		stars[i].speed = Randnum.getInt(5);
	      }
	    }
      
      
	    if (titlemode == TITLEMODE_TITLE) {
	      /* Draw title: */
	      
		ga.drawshape(titlex, titley, ga.OBJ_TITLE);
	  
		ga.drawshape(creditsx, creditsy, ga.OBJ_CREDITS);
		
		    ga.setColor(Color.white);
		    ga.drawcenteredtext(0, ga.WIDTH , levely,
					"LEVEL:");
		    ga.drawshape(levelx, levely, level / 10);
		    ga.drawshape(levelx + 24, levely, level % 10);
		    ga.drawcenteredtext(0, ga.WIDTH, levely + 40 + ga.fh,
					"Use [L] and [K] to select");
		    ga.drawcenteredtext(0, ga.WIDTH, levely + 40 + ga.fh * 2,
					"Press [Space] to begin");
		if (titlemode_section >= 20)
		    nextmode = 1;
	    }
	    else if (titlemode == TITLEMODE_HELP_1) {
	      /* Draw help, page 1: */
	      
		    helpshape(HELPSHAPE_LEFT, 16,
			      ga.OBJ_ALIEN_0 + TYPE_PAWN * 9 + spin);
		    helpshape(HELPSHAPE_RIGHT, 16,
			      ga.OBJ_ALIEN_0 + TYPE_PAWNA * 9 + 7 - spin);
		    helptext(16, "Drones - 50 pts");
		    
		    if (titlemode_section >= 2) {
			helpshape(HELPSHAPE_LEFT, 96,
				  ga.OBJ_ALIEN_0 + TYPE_GUARD * 9 + 7 - spin);
			helpshape(HELPSHAPE_RIGHT, 96,
				  ga.OBJ_ALIEN_1 + TYPE_GUARD * 9 + spin);
			helptext(96, "Guards - 100 pts");
		    }
	      
		    if (titlemode_section >= 3) {
			helpshape(HELPSHAPE_LEFT, 172,
				  ga.OBJ_ALIEN_0 + TYPE_MASTER_0 * 9 +
				  8 * ((counter / 8) % 2));
			helpshape(HELPSHAPE_RIGHT, 172,
				  ga.OBJ_ALIEN_0 + TYPE_MASTER_1 * 9 +
				  8 * ((counter / 8) % 2));
			helptext(172, "Masters - 250 pts");
			helptext(172 + ga.fh, "(Requires two shots)");
		    }
	      
		    if (titlemode_section >= 5) {
			helpshape(HELPSHAPE_CENTER, 248, ga.OBJ_SHIP_0);
			helptext(248, "Your Fighter");
		    }
		
		if (titlemode_section >= 10)
		    nextmode = 1;
	    }
	    else if (titlemode == TITLEMODE_HELP_2) {
	      /* Draw help page 2: */
	      
		    helpshape(HELPSHAPE_CENTER, 32, ga.OBJ_ALIEN_0 +
			      TYPE_MASTER_0 * 9 + DIR_DOWN);
		    helpshape(HELPSHAPE_CENTER, 64, ga.OBJ_TRACTORBEAM);
		    
		    helptext(112, "Masters fire a beam to capture your fighter");
		    
		    if (titlemode_section >= 2) {
			helpshape(HELPSHAPE_CENTER, 192, ga.OBJ_SHIP_1 + spin);
			helpshape(HELPSHAPE_CENTER, 224, ga.OBJ_ALIEN_0 +
				  TYPE_MASTER_0 * 9 + spin);
			helptext(224, "Shoot the Master to free your ship");
			helptext(224 + ga.fh, "(Do this only while it's diving!)");
		    }
		    
		    if (titlemode_section >= 4) {
			ga.drawshape(ga.WIDTH / 2 - 32, 300, ga.OBJ_SHIP_0);
			ga.drawshape(ga.WIDTH / 2, 300, ga.OBJ_SHIP_0);
			helptext(300, "Dock with the freed ship for double shots!");
		    }
		if (titlemode_section >= 10)
		    nextmode = 1;
	    }
	    else if (titlemode == TITLEMODE_HELP_3) {
	      /* Draw help page 3: */
	  
		    helpshape(HELPSHAPE_CENTER, 32, ga.OBJ_GIANT_0 +
			      (counter % 2));
		    
		    helptext(32 + ga.object_height[ga.OBJ_GIANT_0] - ga.fh,
			     "Every 10th level has Super-Masters!");
		    helptext(32 + ga.object_height[ga.OBJ_GIANT_0],
			     "??? pts");
		    helptext(32 + ga.object_height[ga.OBJ_GIANT_0] + ga.fh,
			     "(Requires many shots)");
	  
	  
		    helptext(300, "Watch for other mysteries!");
		if (titlemode_section >= 10)
		    nextmode = 1;
	    }
	    else if (titlemode == TITLEMODE_HIGHS) {
	      /* Draw high scores: */
		    ga.setColor(ga.explosioncolors[counter % ga.NUM_EXPLOSION_COLORS]);
		    ga.drawcenteredtext(0, ga.WIDTH, 80 - ga.fh * 3, "HIGH SCORES");
		    ga.setColor(Color.white);
	  
		    ga.drawtext(20, 80 - ga.fh, "High Scores:");
		    
		    ga.drawtext(ga.WIDTH / 2 + 20, 80 - ga.fh, "High Levels:");
	  
		    for (j = 0; j < titlemode_section_fast && j < 10; j++) {
			int i2 = 9-j;
			if (i2!=highscoreslot)
			    ga.setColor(Color.white);
			else
			    ga.setColor(ga.explosioncolors[(counter / 10) % ga.NUM_EXPLOSION_COLORS]);
			ga.drawtext(20,
				    ga.fh*i2+80+ga.fh,
				    rightAlign((i2+1)+"",2)+" "+
			      rightAlign(highscores[i2].score+"",6)+" "+
				    rightAlign(highscores[i2].name,5));
			if (i2!=highlevelslot)
			    ga.setColor(Color.white);
			else
			    ga.setColor(ga.explosioncolors[(counter / 10) % ga.NUM_EXPLOSION_COLORS]);
			ga.drawtext(ga.WIDTH/2 +20,
				    ga.fh*i2+80+ga.fh,
				    rightAlign(""+(i2+1),2)+" "+
				    rightAlign(highlevels[i2].score+"",3)+" "+
				    rightAlign(highlevels[i2].name,5));
		    }
	      
		    if (titlemode_section_fast >= 11) {
			ga.setColor(Color.white);
			ga.drawcenteredtext(0, ga.WIDTH, 80 + ga.fh * 12, "Highest Hit Ratio:");
		
			String temp = highhitratio+"%   "+highhitrationame;
		       
			if (highhitratioslot != 0)
			    ga.setColor(Color.white);
			else 
			    ga.setColor(ga.explosioncolors[(counter / 10) % ga.NUM_EXPLOSION_COLORS]);
			ga.drawcenteredtext(0, ga.WIDTH, 80 + ga.fh * 14, temp);
			ga.setColor(Color.white);
			
		    }
		if (titlemode_section >= 10)
		    nextmode = 1;
	    }
	    

	/* Switch mode: */
	    
	    if (nextmode == 1) {
	      titlemode++;
	      if (titlemode >= NUM_TITLEMODES)
		titlemode = 0;
	      
	      titlemode_section = 0;
	      titlemode_section_fast = 0;
	    }
	
	    
	    /* Refresh: */
	    ga.frame();
	    
	    /* Pause: */
	    
	    syncRate();

	}  while (!done);

    }



/* Game mode: */

  int game() {
    int i, j, x, y, counter, z, eventloop, w, h;
    //  char string[128], key[128], temp[128], text[128];
    String text="";
    boolean wantleft, wantright, wantup, wantdown;
    int all_in_place, num_aliens,
      wingflap, wave_position, wave_position_m, num_bullets,
      someone_hasship, show_text;
    ga.start_time=0;
  
    /* Init stuff: */
    
    initgame();
    initlevel();
  
    //  playsound(sound_fs, SND_INTRO);
  
    counter = 0;
    wingflap = 0;
    wave_position = 0;
    wave_position_m = 1;
    show_text = 0;
  
    boolean done = false;
  
    flashscreen = 0;

  
    /* MAIN LOOP: */
  
    do {
      
      /* Handle loopers, counters, togglers, etc. */
      
      counter++;
      
      if (counter % 10 == 0)
	wingflap = 1 - wingflap;
      
      if (counter % 3 == 0) {
	wave_position = wave_position + wave_position_m;
	  
	if (wave_position <= -5)
	  wave_position_m = 1;
	else if (wave_position >= 5)
	  wave_position_m = -1;
      }
      
      
      /* Handle keyboard: */
      
      if (player.alive && !paused) {
	/* Arrow keys move: */
	  
	if (km.isDown(KeyEvent.VK_LEFT) && player.x > 0)
	  player.x = player.x - 6;
	else if (km.isDown(KeyEvent.VK_RIGHT) &&
		 player.x < ga.WIDTH - (32 * player.size) - 1)
	    player.x = player.x + 6;	
	else if (km.isDown(KeyEvent.VK_K) && player.x > 0)
	    player.x = player.x - 6;
	else if (km.isDown(KeyEvent.VK_L) &&
		 player.x < ga.WIDTH - (32 * player.size) - 1)
	    player.x = player.x + 6;
	  
	  
	if (km.wasPressed(KeyEvent.VK_SPACE)) {
	  /* Space fires */
	  
	  /*	  if (player.shots_out < MAX_SHOTS_AT_A_TIME * player.size)
		  playsound(sound_fs, SND_SHOT);*/
	  
	  for (i = 0; i < player.size; i++) {
	    if (player.shots_out < MAX_SHOTS_AT_A_TIME * player.size) {
	      addbullet(player.x + 16 - BULLET_SIZE / 2 + (i * 32),
			ga.HEIGHT - 32 - BULLET_SIZE / 2,
			0, -10, OWNER_PLAYER);
		      
	      num_shots++;
		      
	      player.shots_out++;
	    }
	  }
	}
      }


      if (km.wasPressed(KeyEvent.VK_P))
	{
	  /* P (un)pauses: */
	  
	  paused = !paused;
	}

      km.reset();
      
      /* Count aliens: */
      
      num_aliens = 0;
      someone_hasship = 0;
      
      for (i = 0; i < MAX_ALIENS; i++) {
	if (aliens[i].alive) {
	  num_aliens++;
	  
	  if (aliens[i].hasship)
	    someone_hasship = 1;
	}
      }
      
      
      /* Advance if there are no more aliens: */
      
      if (num_aliens == 0)
	{
	  level++;
	  
	  if (level > 99)
	    level = 0;
	  
	  if (level > maxlevel)
	    maxlevel = level;
	  
	  //playsound(sound_fs, SND_NEXTLEVEL);
	  initlevel();
	}
      
      
      /* Handle aliens: */
      
      for (i = 0; i < MAX_ALIENS; i++)
	{
	  if (aliens[i].alive && gamemode != GAMEMODE_WARP &&
	      !paused)
	    {
	      /* if (player.alive == 0)
		aliens[i].mode = MODE_ENTER; */
	      
	      
	      /* Rotate: */
	      
	      if (aliens[i].dir < 0)
		aliens[i].dir = aliens[i].dir + 8;
	      else if (aliens[i].dir > 7)
		aliens[i].dir = aliens[i].dir - 8;
	      
	      
	      /* Move: */
	      
	      if (aliens[i].mode != MODE_WAIT &&
		  aliens[i].mode != MODE_SUCK)
		{
		  /* Move them forward: */
		  
		  aliens[i].x = aliens[i].x + (ga.xms[aliens[i].dir] *
					       alien_speed);
		  aliens[i].y = aliens[i].y + (ga.yms[aliens[i].dir] *
					       alien_speed);
		  
		  
		  /* Make them spin: */
		  
		  if (counter % 4 == 0)
		    {
		      /* Find out which way they want to go: */
		      
		      wantleft = false;
		      wantright = false;
		      wantup = false;
		      wantdown = false;
		      
		      if (aliens[i].x < aliens[i].gotox)
			wantright = true;
		      else if (aliens[i].x > aliens[i].gotox)
			wantleft = true;
		      
		      if (aliens[i].y < aliens[i].gotoy)
			wantdown = true;
		      else if (aliens[i].y > aliens[i].gotoy)
			wantup = true;
		      
		      
		      /* Make them spin to face that way: */
		      
		      if (wantleft)
			{
			  if (wantup)
			    {
			      aliens[i].dir = dirtowards(DIR_UPLEFT,
							 aliens[i].dir);
			    }
			  else if (wantdown)
			    {
			      aliens[i].dir = dirtowards(DIR_DOWNLEFT,
							 aliens[i].dir);
			    }
			  else
			    {
			      aliens[i].dir = dirtowards(DIR_LEFT,
							 aliens[i].dir);
			    }
			}
		      else if (wantright)
			{
			  if (wantup)
			    {
			      aliens[i].dir = dirtowards(DIR_UPRIGHT,
							 aliens[i].dir);
			    }
			  else if (wantdown)
			    {
			      aliens[i].dir = dirtowards(DIR_DOWNRIGHT,
							 aliens[i].dir);
			    }
			  else
			    {
			      aliens[i].dir = dirtowards(DIR_RIGHT,
							 aliens[i].dir);
			    }
			}
		      else
			{
			  if (wantup)
			    aliens[i].dir = dirtowards(DIR_UP,
						       aliens[i].dir);
			  else
			    aliens[i].dir = dirtowards(DIR_DOWN,
						       aliens[i].dir);
			}
		    }
		  
		  
		  /* If they're attacking, take care of making them
		     wrap around the screen: */
		  
		  if (aliens[i].mode == MODE_ATTACK)
		    {
		      /* Some aliens go off the bottom: */
		      
		      /* if (aliens[i].y < -32)
			{
			  aliens[i].y = aliens[i].y + ga.HEIGHT + 32;
			  aliens[i].x = Randnum.getInt(ga.WIDTH - 32);
			} */
		      
		      if (aliens[i].y > ga.HEIGHT)
			{
			  aliens[i].y = aliens[i].y - ga.HEIGHT - 32;
			  aliens[i].x = Randnum.getInt(ga.WIDTH - 32);
			  
			  aliens[i].gotox = player.x;
			}
		      
		      
		      /* Masters switch into "suck" mode: */
		      
		      if (someone_hasship == 0 &&
			  player.alive && player.size == 1 &&
			  !aliens[i].hasship &&
			  aliens[i].mode == MODE_ATTACK &&
			  aliens[i].y >= SUCK_HEIGHT &&
			  (aliens[i].type == TYPE_MASTER_0 ||
			   aliens[i].type == TYPE_MASTER_1))
			{
			  aliens[i].mode = MODE_SUCK;
			  aliens[i].sucktime = 50;
			}
		    }
		}
	      else if (aliens[i].mode == MODE_WAIT)
		{
		  /* WAIT mode: */
		  
		  if (aliens[i].dir != DIR_UP)
		    {
		      /* Rotate up if not facing up: */
		      
		      if (counter % 4 == 0)
			aliens[i].dir = dirtowards(DIR_UP, aliens[i].dir);
		    }
		  else
		    {
		      /* Float back and forth */
		      
		      if (level % 3 == 0)
			{
			  if (i % 2 == 0)
			    aliens[i].x = aliens[i].homex + wave_position;
			  else
			    aliens[i].x = aliens[i].homex - wave_position;
			}
		      else if (level % 3 == 1)
			{
			  aliens[i].x = aliens[i].homex + wave_position;
			}
		      else if (level % 3 == 2)
			{
			  j = aliens[i].homex - ga.WIDTH / 2;
			  j = j / 32;
			  
			  aliens[i].x = aliens[i].homex + wave_position * j;
			  aliens[i].y = aliens[i].homey + wave_position;
			}
		    }
		}
	      else if (aliens[i].mode == MODE_SUCK) 
		{
		  /* "suck" mode: */
		  
		  /* Unswitch from "suck" mode: */
		  
		  aliens[i].sucktime--;
		  
		  if (aliens[i].sucktime <= 0)
		    aliens[i].mode = MODE_ENTER;
		  
		  if (aliens[i].dir != DIR_DOWN)
		    {
		      /* Rotate down if not facing down: */
		      
		      if (counter % 4 == 0)
			aliens[i].dir = dirtowards(DIR_DOWN, aliens[i].dir);
		    }
		}
	      
	      
	      /* Handle mode: */
	      
	      if (aliens[i].mode == MODE_ENTER)
		{
		  /* We want to go back home: */
		  
		  aliens[i].gotox = aliens[i].homex;
		  aliens[i].gotoy = aliens[i].homey;
		  
		  
		  /* If we are home, snap into position and switch to
		     wait mode: */
		  
		  if ((aliens[i].x >= aliens[i].homex - 8 &&
		       aliens[i].x <= aliens[i].homex + 8 &&
		       aliens[i].y >= aliens[i].homey - 32 &&
		       aliens[i].y <= aliens[i].homey + 32) ||
		      (aliens[i].x >= aliens[i].homex - 32 &&
		       aliens[i].x <= aliens[i].homex + 32 &&
		       aliens[i].y >= aliens[i].homey - 8 &&
		       aliens[i].y <= aliens[i].homey + 8))
		    {
		      aliens[i].x = aliens[i].homex;
		      aliens[i].y = aliens[i].homey;
		      
		      aliens[i].mode = MODE_WAIT;
		    }
		  
		  
		  /* If we're a "go away" bug, then head for the bottom: */
		  
		  if (aliens[i].x >= 0 && aliens[i].x <= ga.WIDTH - 32 &&
		      aliens[i].goaway == 1)
		    {
		      aliens[i].mode = MODE_ATTACK;
		      aliens[i].gotoy = ga.HEIGHT + 32;
		    }
		  
		}
	      else if (aliens[i].mode == MODE_ATTACK)
		{
		  /* Randomly shoot: */
		  
		  if (Randnum.getInt(500) <= level / 2 &&
		      player.alive)
		    addbullet(aliens[i].x + 16 - BULLET_SIZE / 2,
			      aliens[i].y + 32,
			      ga.xms[aliens[i].dir], 3, OWNER_ALIEN);
		  
		  
		  /* Switch back to "go home" mode: */
		  
		  if ((((aliens[i].type == TYPE_PAWN ||
			 aliens[i].type == TYPE_PAWNA) &&
			aliens[i].y > ga.HEIGHT - 64) ||
		       ((aliens[i].type == TYPE_GUARD ||
			 aliens[i].type == TYPE_GUARDA) &&
			aliens[i].y < 0)) && aliens[i].goaway == 0)
		    {
		      aliens[i].mode = MODE_ENTER;
		    }
		  
		  
		  /* Face down: */
		  
		  if (counter % 8 == 0)
		    aliens[i].dir = dirtowards(DIR_DOWN, aliens[i].dir);
		  
		  
		  /* If we're a go-away and we've reached the bottom,
		     then go away! */
		  
		  if (aliens[i].y >= ga.HEIGHT - 16 && aliens[i].goaway == 1)
		    {
		      aliens[i].alive = false;
		    }
		}
	      
	      
	      /* Randomly switch to attack mode: 
		 (or do it if there are few bugs around) */
	      
	      if (player.alive &&
		  aliens[i].mode == MODE_WAIT && 
		  (Randnum.getInt(1000) < level || num_aliens < 5) &&
		  gamemode == GAMEMODE_NORMAL &&
		  (aliens[i].hasship || Randnum.getInt(10) < 1))
		{
		  aliens[i].mode = MODE_ATTACK;
		  aliens[i].gotox = player.x + 16 * player.size;
		  aliens[i].gotoy = ga.HEIGHT;
		  
		  /* See if we make a convoy: */
		  
		  if (aliens[i].type == TYPE_MASTER_0 ||
		      aliens[i].type == TYPE_MASTER_1)
		    {
		      for (j = 0; j < MAX_ALIENS; j++)
			{
			  if (aliens[j].alive &&
			      aliens[j].mode == MODE_WAIT &&
			      aliens[j].homex == aliens[i].homex &&
			      aliens[j].homey < aliens[i].homey + 64)
			    {
			      aliens[j].mode = MODE_ATTACK;
			      aliens[j].gotox = aliens[i].gotox;
			      aliens[j].gotoy = aliens[i].gotoy + 32;
			    }
			}
		    }
		}
	      
	      
	      /* Detect collisions with bullets: */
	      
	      for (j = 0; j < MAX_BULLETS; j++)
		{
		  if (bullets[j].alive &&
		      bullets[j].owner == OWNER_PLAYER &&
		      bullets[j].x >= aliens[i].x - BULLET_SIZE &&
		      bullets[j].x <= aliens[i].x + 32 &&
		      bullets[j].y >= (aliens[i].y - BULLET_SIZE -
				       (32 * (aliens[i].hasship?1:0))) &&
		      bullets[j].y <= aliens[i].y + 32) {
		    killbullet(j);
		    num_hits++;
		      
		      
		    /* Masters take damage, all else die: */
		      
		    if (aliens[i].type == TYPE_MASTER_0) {
		      if (!giant_bugs || aliens[i].hitpoints == 0) {
			aliens[i].type = TYPE_MASTER_1;
			      
			//playsound(sound_fs, SND_HURT);
		      }
		      else {
			aliens[i].hitpoints--;
			addexplosion(bullets[j].x, bullets[j].y,
				     0, -2);
		      }
		    }
		    else {
			  if (aliens[i].type == TYPE_MASTER_1 &&
			      giant_bugs)
			    {
			      flashscreen = 1;
			      score = score + level * 100;
			      
			      addanimatedexplosion(aliens[i].x, aliens[i].y);
			    }
			  else
			    {
			      score = score + scores[aliens[i].type];
			    }
			  
			  aliens[i].alive = false;
			  
			  //			  playsound(sound_fs, SND_KILL);

			  
			  if (aliens[i].isship)
			    {
			      text = "FIGHTER DESTROYED!";
			      show_text = 100;
			      flashscreen = 3;
			    }
			  
			  
			  /* Release the ship: */
			  
			  if (aliens[i].hasship) {
			    /* Make aliens go home: */
			    
			    if (bullets[j].y + 16 >= aliens[i].y) {
			      /* If they shot the bug: */
				  
			      if (aliens[i].mode != MODE_WAIT) {
				/* If it was attacking or something: */
				      
				gamemode = GAMEMODE_ENTER;
				      
				for (int k = 0; k < MAX_ALIENS; k++)
				  aliens[k].mode = MODE_ENTER;
				      
				extraship.alive = true;
				extraship.x = aliens[i].x;
				extraship.y = aliens[i].y - 32;
				      
				text = "FIGHTER FREED!";
				show_text = 75;
			      }
			      else {
				/* Oops, they shot the bug and now
				   the ship is stuck! */
				      
				aliens[i].alive = true;
				aliens[i].hasship = false;
				aliens[i].isship = true;
			      }
				}
			      else
				{
				  /* If they shot the ship: */
				  
				  flashscreen = 3;
				  aliens[i].hasship = false;
				  aliens[i].alive = true;
				  
				  text = "FIGHTER DESTROYED!";
				  show_text = 100;
				}
			    }
			}
		      
		      
		      /* Add explosion: */
		      
		      addexplosion(bullets[j].x, bullets[j].y, 0, 0);
		    }
		}
	      
	      
	      /* Detect collisions with player: */
	      
	      if (aliens[i].x + 32 >= player.x &&
		  aliens[i].x <= player.x + (32 * player.size) &&
		  aliens[i].y + 32 >= ga.HEIGHT - 32 &&
		  player.alive)
		{
		  if (aliens[i].type != TYPE_MASTER_0 &&
		      aliens[i].type != TYPE_MASTER_1 &&
		      !giant_bugs)
		    {
		      aliens[i].alive = false;
		      score = score + scores[aliens[i].type];
		    }
		  
		  killplayer(aliens[i].x);
		}
	      
	      
	      /* Detect alien zap: */
	      
	      if (player.alive &&
		  aliens[i].mode == MODE_SUCK &&
		  aliens[i].x + 32 >= player.x &&
		  aliens[i].x <= (player.x + 32 * player.size))
		{
		  player.alive = false;
		  gamemode = GAMEMODE_SUCK;
		  player.y = ga.HEIGHT - 32;
		  alien_responsible = i;
		  aliens[i].sucktime = 1000;
		}
	    }
	}
      
      
      /* Find out if they are all at home yet or not: */
      
      all_in_place = 1;
      
      for (i = 0; i < MAX_ALIENS; i++)
	{
	  if (aliens[i].alive && aliens[i].mode != MODE_WAIT)
	    /* aliens[i].x != aliens[i].homex &&
	      aliens[i].y != aliens[i].homey) */
	    all_in_place = 0;
	}
      
      
      /* Count number of bullets: */
      
      num_bullets = 0;
      for (i = 0; i < MAX_BULLETS; i++)
	{
	  if (bullets[i].alive)
	    num_bullets++;
	}
      
      
      /* Switch to normal game mode if they are all in place */

      if (all_in_place == 1 && gamemode == GAMEMODE_ENTER)
	{
	  gamemode = GAMEMODE_NORMAL;
	}
      
      
      /* If you're gone, make you come back: */
      
      if (!player.alive && gamemode != GAMEMODE_SUCK)
	{
	  if (num_bullets == 0 && all_in_place == 1 &&
	      gameover == 0)
	    player.alive = true;
	}


      /* Handle extra ship: */
      
      if (extraship.alive && !paused)
	{
	  if (extraship.x > player.x)
	    extraship.x--;
	  else if (extraship.x < player.x)
	    extraship.x++;
	  
	  if (extraship.y < ga.HEIGHT - 32)
	    {
	      extraship.y = extraship.y + 4;
	    }
	  
	  if (extraship.y >= ga.HEIGHT - 32 - 32 &&
	      extraship.x + 32 >= player.x &&
	      extraship.x <= player.x + 32)
	    {
	      extraship.alive = false;
	      
	      if (player.alive)
		{
		  if (extraship.x < player.x)
		    player.x = player.x - 32;
		  
		  player.size = 2;
		}
	      else
		{
		  player.size = 1;
		  player.alive = true;
		}
	    }
	}
      
      
      /* Handle bullets: */
      
      for (i = 0; i < MAX_BULLETS; i++)
	{
	  if (bullets[i].alive && !paused)
	    {
	      /* Move bullet: */
	      
	      bullets[i].x = bullets[i].x + bullets[i].xm;
	      bullets[i].y = bullets[i].y + bullets[i].ym;
	      
	      
	      /* Kill it if it goes offscreen: */
	      
	      if (bullets[i].x < -BULLET_SIZE || bullets[i].x >= ga.WIDTH ||
		  bullets[i].y < -BULLET_SIZE || bullets[i].y >= ga.HEIGHT)
		{
		  killbullet(i);
		}
	      
	      
	      /* Detect collision with player: */
	      
	      if (bullets[i].x + BULLET_SIZE >= player.x &&
		  bullets[i].x <= player.x + 32 * player.size &&
		  bullets[i].y - BULLET_SIZE >= ga.HEIGHT - 32 &&
		  bullets[i].owner != OWNER_PLAYER &&
		  player.alive)
		{
		  killbullet(i);
		  
		  killplayer(bullets[i].x);
		}
	    }
	}
      
      
      /* Move explosion bits: */
      
      for (i = 0; i < MAX_EXPLOSIONBITS; i++)
	{
	  if (explosionbits[i].alive)
	    {
	      explosionbits[i].x = explosionbits[i].x + explosionbits[i].xm;
	      explosionbits[i].y = explosionbits[i].y + explosionbits[i].ym;
	      
	      explosionbits[i].time--;
	      if (explosionbits[i].time <= 0)
		explosionbits[i].alive = false;
	    }
	}
      
      
      /* Move explosions: */
      
      for (i = 0; i < MAX_EXPLOSIONS; i++)
	{
	  if (explosions[i].alive)
	    {
	      if (counter % 4 == 0)
		{
		  explosions[i].frame++;
		  if (explosions[i].frame >= ga.NUM_EXPLODE_SHAPES)
		    explosions[i].alive = false;
		}
	    }
	}
      
      
      /* Handle asteroids: */
      
      for (i = 0; i < MAX_ASTEROIDS; i++)
	{
	  if (asteroids[i].alive)
	    {
	      asteroids[i].x = asteroids[i].x + asteroids[i].xm;
	      asteroids[i].y = asteroids[i].y + asteroids[i].ym;
	      
	      if (counter % asteroids[i].animspeed == 0)
		{
		  asteroids[i].anim = (asteroids[i].anim + asteroids[i].animm);
		  if (asteroids[i].anim < 0)
		    asteroids[i].anim = 4;
		  else if (asteroids[i].anim > 4)
		    asteroids[i].anim = 0;
		}
	      
	      if (asteroids[i].x < -100 || asteroids[i].x > ga.WIDTH ||
		  asteroids[i].y < -100 || asteroids[i].y > ga.HEIGHT)
		asteroids[i].alive = false;
	      
	      if (asteroids[i].size == 1)
		{
		  w = ga.object_width[ga.OBJ_ASTEROID_A];
		  h = ga.object_width[ga.OBJ_ASTEROID_A];
		}
	      else
		{
		  w = ga.object_width[ga.OBJ_ASTEROID_B];
		  h = ga.object_width[ga.OBJ_ASTEROID_B];
		}
	      
	      for (j = 0; j < MAX_BULLETS; j++)
		{
		  if (bullets[j].alive)
		    {
		      if (bullets[j].x + BULLET_SIZE > asteroids[i].x && 
			  bullets[j].x < asteroids[i].x + w &&
			  bullets[j].y + BULLET_SIZE > asteroids[i].y &&
			  bullets[j].y < asteroids[i].y + h)
			{
			  killbullet(j);
			  addexplosion(bullets[j].x, bullets[j].y,
				       asteroids[i].xm, asteroids[i].ym);
			  
			  score = score + 150 - (50 * asteroids[i].size);
			  
			  asteroids[i].size--;
			  
			  if (asteroids[i].size == 0)
			    asteroids[i].alive = false;
			  else
			    {
			      asteroids[i].xm = Randnum.getInt(11) - 5;
			      asteroids[i].ym = Randnum.getInt(11) - 5;
			      asteroids[i].animm = Randnum.getInt(3) - 1;
			      asteroids[i].animspeed = Randnum.getInt(5) + 1;
			      
			      if (Randnum.getInt(10) < 5)
				addasteroid(asteroids[i].x,
					    asteroids[i].y,
					    (Randnum.getInt(11) - 5),
					    (Randnum.getInt(11) - 5), 1);
			    }
			}
		    }
		}
	      
	      if (player.x + 32 * player.size > asteroids[i].x &&
		  player.x < asteroids[i].x + w &&
		  asteroids[i].y + h > ga.HEIGHT - 32 && player.alive)
		{
		  killplayer(asteroids[i].x);
		}
	    }
	  else
	    {
	      if (Randnum.getInt(10000) < level && level > 20)
		{
		  addasteroid(-1, -1, 0, 0, Randnum.getInt(2) + 1);
		}
	    }
	}
      
      
      /* Move stars: */
      
      for (i = 0; i < MAX_STARS; i++)
	{
	  if (gamemode != GAMEMODE_SUCK)
	    {
	      stars[i].y = stars[i].y + (starspeed + stars[i].speed);
	      
	      if (stars[i].y > ga.HEIGHT)
		{
		  stars[i].x = Randnum.getInt(ga.WIDTH);
		  stars[i].speed = Randnum.getInt(5)+1;
		  stars[i].y = -Randnum.getInt(20);
		}
	    }
	  else
	    {
	      stars[i].y = stars[i].y - starspeed - stars[i].speed;
	      
	      if (stars[i].y < 0)
		{
		  stars[i].x = Randnum.getInt(ga.WIDTH);
		  stars[i].speed = Randnum.getInt(5)+1;
		  stars[i].y = ga.HEIGHT + Randnum.getInt(20);
		}
	    }
	}
      
      
      /* Move planet: */
      
      if (planet.alive)
	{
	  if (gamemode != GAMEMODE_SUCK)
	    {
	      planet.y = planet.y + (starspeed + 5);
	      
	      if (planet.y > ga.HEIGHT)
		planet.alive = false;
	    }
	  else
	    {
	      planet.y = planet.y - (starspeed + 5);
	    }
	}
      else
	{
	  if (Randnum.getInt(1000) < 1)
	    {
	      planet.alive = true;
	      planet.x = Randnum.getInt(ga.WIDTH + 100) - 100;
	      planet.y = -100;
	      planet.shape = Randnum.getInt(ga.NUM_PLANET_SHAPES);
	    }
	}
      
      
      /* Handle star speed: */
      
      if (counter % 5 == 0)
	starspeed = starspeed + starspeedm;
      
      if (starspeed > faststarspeed)
	{
	  starspeed = faststarspeed;
	  starspeedm = 0;
	  starspeedtime = 50;
	}
      
      if (starspeedtime > 0)
	{
	  starspeedtime = starspeedtime - 1;
	  
	  if (starspeedtime <= 0)
	    {
	      if (starspeed == faststarspeed)
		starspeedm = -changestarspeed;
	      else
		starspeedm = changestarspeed;
	    }
	}
      
      if (starspeed <= wantstarspeed && starspeedm < 0)
	{
	  starspeed = wantstarspeed;
	  starspeedm = 0;
	  gamemode = GAMEMODE_ENTER;
	}
      

      /* Erase backbuffer */
      
      if (flashscreen <= 0)
	  ga.clearbackbuffer();      
      else
	  {
	      ga.clearbackbufferinvert();
	      flashscreen--;
	  }
      
      
      /* Draw stars: */
      ga.setColor(Color.gray);
      for (i = 0; i < MAX_STARS; i++) {
	  if (starspeed < 4)
	      ga.g_backbuffer.drawLine(stars[i].x, stars[i].y,stars[i].x, stars[i].y);
	  else
	      ga.g_backbuffer.drawLine(stars[i].x, stars[i].y,stars[i].x, stars[i].y-starspeed);
      }
      
      
      /* Draw plent: */
      
      if (planet.alive) {
	  ga.drawshape(planet.x, planet.y, ga.OBJ_PLANET_0 + planet.shape);
      }
      
      
      /* Draw bullets: */
      
      for (i = 0; i < MAX_BULLETS; i++) {
	  if (bullets[i].alive) {
	      if (bullets[i].owner == OWNER_PLAYER)
		  ga.drawshape(bullets[i].x, bullets[i].y, ga.OBJ_BULLET);
	      else
		  ga.drawshape(bullets[i].x, bullets[i].y, ga.OBJ_ALIENBULLET);
	  }
      }
      
      
      /* Draw explosionbits: */
      
      for (i = 0; i < MAX_EXPLOSIONBITS; i++) {
	  if (explosionbits[i].alive) {
	      ga.setColor(ga.explosioncolors[Randnum.getInt(ga.NUM_EXPLOSION_COLORS)]);
	      ga.g_backbuffer.drawLine(explosionbits[i].x, explosionbits[i].y,
				       explosionbits[i].x + explosionbits[i].xm,
				       explosionbits[i].y + explosionbits[i].ym);
	  }
      }
      
      
      /* Draw explosions: */
      
      for (i = 0; i < MAX_EXPLOSIONS; i++) {
	  if (explosions[i].alive) {
	      j = ga.OBJ_EXPLODE + explosions[i].frame;
	      
	      ga.drawshape(explosions[i].x - ga.object_width[j] / 2,
			   explosions[i].y - ga.object_height[j] / 2,
			   j);
	  }
      }
      
      
      /* Draw "Level": */
      
      if (gamemode == GAMEMODE_WARP) {
	  ga.drawshape(ga.WIDTH / 2 - 12, ga.HEIGHT / 2, level / 10);
	  ga.drawshape(ga.WIDTH / 2 + 12, ga.HEIGHT / 2, level % 10);
      }
      
      
      /* Draw aliens: */
      
      for (i = 0; i < MAX_ALIENS; i++) {
	  if (aliens[i].alive && gamemode != GAMEMODE_WARP) {
	      if (!aliens[i].isship) {
		      if (giant_bugs &&
			  (aliens[i].type == TYPE_MASTER_0 ||
			   aliens[i].type == TYPE_MASTER_1)) {
			  ga.drawshape(aliens[i].x - 29, aliens[i].y - 62,
				       ga.OBJ_GIANT_0 + (counter % 2));
		      }
		      else {
			  if (aliens[i].mode == MODE_WAIT && wingflap == 0)
			      ga.drawshape(aliens[i].x, aliens[i].y,
					   ga.OBJ_ALIEN_0 + aliens[i].type * 9 + 8);
			  else
			      ga.drawshape(aliens[i].x, aliens[i].y,
					   (ga.OBJ_ALIEN_0 + aliens[i].type * 9 +
					    aliens[i].dir));
		      }
		  }
		  else {
		      ga.drawshape(aliens[i].x, aliens[i].y,
				   ga.OBJ_SHIP_1 + aliens[i].dir);
		  }
	      
	      
		  /* Draw ship next to alien: */
	      
		  if (aliens[i].hasship)
		      ga.drawshape(aliens[i].x, aliens[i].y - 32,
				   ga.OBJ_SHIP_1 + (aliens[i].dir * (1 - (giant_bugs?1:0))));
	      
	      
		  /* Draw tractor beam: */
	      
		  if (aliens[i].mode == MODE_SUCK) {
		      ga.drawshape(aliens[i].x - 16, aliens[i].y +32,
				   ga.OBJ_TRACTORBEAM);
		  
		  /*		  if (counter % 10 == 0 && gamemode != GAMEMODE_SUCK)
				  playsound(sound_fs, SND_TRACTORBEAM);*/
		  }
	      
	      //#ifdef ATTACH_SELF
	      /*	      ga.setColor(Color.white);
	      if (aliens[i].mode == MODE_ATTACK)
		ga.g_backbuffer.drawLine(aliens[i].x + 16, aliens[i].y + 16,
			    player.x + 16, ga.HEIGHT - 16);
	      else if (aliens[i].mode == MODE_ENTER)
		ga.g_backbuffer.drawLine(aliens[i].x + 16, aliens[i].y + 16,
		aliens[i].homex + 16, aliens[i].homey + 16);*/
	      //#endif /* ATTACH_SELF */
	      }
	  }
	  
	  
	  /* Draw asteroids: */
      
	  for (i = 0; i < MAX_ASTEROIDS; i++) {
	      if (asteroids[i].alive) {
		  ga.drawshape(asteroids[i].x, asteroids[i].y,
			       ga.OBJ_ASTEROID_A + asteroids[i].anim +
			       (asteroids[i].size * 5) - 5);
	      }
	  }
      
      
	  /* Draw ship: */
	  
	  if (player.alive) {
	      for (i = 0; i < player.size; i++)
		  ga.drawshape(player.x + i * 32, ga.HEIGHT - 32, ga.OBJ_SHIP_0);
	  }
      
      
      /* Draw score and level: */
	  ga.setColor(Color.white);
      
	  ga.drawtext(0, ga.fh, "Score: "+score);
	  ga.drawcenteredtext(0, ga.WIDTH,ga.fh, "Level: "+level);
	  ga.drawrighttext(ga.WIDTH, ga.fh, "Lives: "+lives);
      
	  if (show_text > 0) {
	      ga.drawcenteredtext(0, ga.WIDTH,(ga.HEIGHT - ga.fh) / 2, text);	  
	      show_text--;
	  }
      
      
	  /* Draw game over: */
      
	  if (paused && (counter % 10) < 5) {
	      ga.drawcenteredtext(0, ga.WIDTH, ga.HEIGHT / 2,"PAUSED");
	  }
      
	  if (gameover > 0) {
	      ga.drawcenteredtext(0,ga.WIDTH, ga.HEIGHT / 2,"GAME OVER");
	  
	      if (num_shots != 0) {
		  ga.drawcenteredtext(0,ga.WIDTH, ga.HEIGHT / 2 + ga.fh,"Hit Ratio = "+
				      (num_hits*100/num_shots)+"%");
	      }
	      gameover++;
	      if (gameover == 100) {
		  done=true;
	      }
	  }
      

      /* Draw extra ship: */
      
	  if (extraship.alive) {
	      ga.drawshape(extraship.x, extraship.y,
			   ga.OBJ_SHIP_0 + (counter / 4) % 8);
	  }
      
      
	  /* Draw ship getting sucked up */
      
	  if (gamemode == GAMEMODE_SUCK) {
	      if (player.y > SUCK_HEIGHT + 32)
		  ga.drawshape(player.x, player.y, ga.OBJ_SHIP_0 + ((counter / 4) % 8));
	      else
		  ga.drawshape(player.x, player.y, ga.OBJ_SHIP_1 + ((counter / 4) % 8));
	  
	      if (counter % 2 == 0) {
		  if (aliens[alien_responsible].alive) {
		      player.y = player.y - 4;
		  
		  /*		  if (counter % 6 == 0)
				  playsound(sound_fs, SND_CAPTURE);*/
		  }
		  else
		      player.y = player.y + 2;
	      }
	  
	  if (player.y <= SUCK_HEIGHT - 32 ||
	      (player.y >= ga.HEIGHT - 32 &&
	       !aliens[alien_responsible].alive))
	    {
	      gamemode = GAMEMODE_ENTER;
	      
	      for (i = 0; i < MAX_ALIENS; i++)
		{
		  if (aliens[i].goaway == 0)
		    aliens[i].mode = MODE_ENTER;
		}
	      
	      if (player.y <= SUCK_HEIGHT - 32)
		{
		  aliens[alien_responsible].hasship = true;
		  turnoffplayer();
		  
		  text = "FIGHTER CAPTURED!";
		  show_text = 100;
		}
	      else
		player.alive = true;
	    }
	  
	  if (player.x > aliens[alien_responsible].x)
	    player.x--;
	  else if (player.x < aliens[alien_responsible].x)
	    player.x++;
	}
      
      
      ga.frame();
      
      
      /* Keep game speed normal: */
      
      syncRate();
      
      /*      if (counter % 6 == 0 && giant_bugs == 1 && paused == 0 && gameover == 0)
	      playsound(sound_fs, SND_BUZZ);*/
    }
  while (!done);
  
  if (checkforhigh() == 1)
    return(TITLEMODE_HIGHS);
  else
    return(TITLEMODE_TITLE);
}


int checkforhigh()
{
  int found, i, gotone;
  String name = null;
  
  
  gotone = 0;
  
  
  /* Is it a high score? */
  
  
  found = -1;
  
  for (i = 0; i < 10 && found == -1; i++)
    {
      if (score > highscores[i].score)
	{
	  found = i;
	}
    }
  
  if (found != -1)
    {
      gotone = 1;
      
      name = getname("High Score");
      
      for (i = 9; i > found; i--)
	{
	  highscores[i].score = highscores[i - 1].score;
	  highscores[i].name = highscores[i - 1].name;
	}
      
      highscores[found].score = score;
      highscores[found].name = name;
      
      highscoreslot = found;
    }

  
  /* Is it a high level? */
  
  found = -1;
  
  for (i = 0; i < 10 && found == -1; i++)
    {
      if (level > highlevels[i].score)
	{
	  found = i;
	}
    }
  
  if (found != -1)
    {
      gotone = 1;
      
      if (name == null)
	  name = getname("High Level");
      
      for (i = 9; i > found; i--)
	{
	  highlevels[i].score = highlevels[i - 1].score;
	  highlevels[i].name = highlevels[i - 1].name;
	}
      
      highlevels[found].score = level;
      highlevels[found].name = name;

      highlevelslot = found;
    }
  
  if ((num_hits * 100.0) / num_shots >= highhitratio)
    {
      gotone = 1;
      
      if (name == null)
	  name = getname("High Hit Ratio");
      
      highhitratio = (float)((num_hits * 100.0) / num_shots);
      highhitrationame = name;
      
      highhitratioslot = 0;
    }
  
  return(gotone);
}


    String checkCharacter(int key,char ch, String orig,int len) {
	if (orig.length() >= len)
	    return orig;
	if (km.wasReleased(key))
	    return orig+ch;
	else
	    return orig;
    }
    
    /* Get initials for high score/level/hr */

    
String getname(String title)
{
  int done, x, i, j;
  int counter=0;
  fireworks_type[] fireworks = new fireworks_type[MAX_FIREWORKS];

  String name="";
  
  done = 0;
  x = 0;

  for (i = 0; i < MAX_FIREWORKS; i++) {
      fireworks[i] = new fireworks_type();
    fireworks[i].alive = false;
  }
  
  //  silence(sound_fs);
  
  do
    {
	counter++;
      
      
      /* Redraw screen: */

      ga.clearbackbuffer();
      
      /* Draw fireworks: */
      
      for (i = 0; i < MAX_FIREWORKS; i++)
	{
	  if (fireworks[i].alive)
	    {
	      fireworks[i].time--;
	      
	      if (fireworks[i].time > 0)
		{
		  /* Move and draw firework missile: */
		  
		  fireworks[i].x = fireworks[i].x + fireworks[i].xm;
		  fireworks[i].y = fireworks[i].y + fireworks[i].ym;
		  fireworks[i].ym = fireworks[i].ym + 0.125f;

		  ga.setColor(Color.white);
		  ga.g_backbuffer.drawLine((int)(fireworks[i].x),
					   (int)(fireworks[i].y),
					   (int)(fireworks[i].x + fireworks[i].xm),
					   (int)(fireworks[i].y + fireworks[i].ym));
		}
	      else if (fireworks[i].time == 0)
		{
		  /* Explode!: */
		  
		    //		  playsound(sound_fs, SND_FIREWORKS);
		  
		  for (j = 0; j < MAX_FIREWORKSBITS; j++)
		    {
		      fireworks[i].bit[j].x = fireworks[i].x;
		      fireworks[i].bit[j].y = fireworks[i].y;
		      fireworks[i].bit[j].xm = (float)((Randnum.getInt(70) - 30)
						       / 10.0 +	fireworks[i].xm);
		      fireworks[i].bit[j].ym = (float)((Randnum.getInt(70) - 30)
						       / 10.0 +	fireworks[i].ym);
		    }
		}
	      else if (fireworks[i].time < 0)
		{
		  /* Draw firework bits: */
		  
		  for (j = 0; j < MAX_FIREWORKSBITS; j++)
		    {
		      fireworks[i].bit[j].x = fireworks[i].bit[j].x +
			fireworks[i].bit[j].xm;
		      fireworks[i].bit[j].y = fireworks[i].bit[j].y +
			fireworks[i].bit[j].ym;
		      fireworks[i].bit[j].ym = fireworks[i].bit[j].ym + 0.125f;

		      ga.setColor(ga.explosioncolors[Randnum.getInt(ga.NUM_EXPLOSION_COLORS)]);
		      ga.g_backbuffer.drawLine((int)fireworks[i].bit[j].x,
					       (int)fireworks[i].bit[j].y,
					       (int)fireworks[i].bit[j].x,
					       (int)fireworks[i].bit[j].y);
		    }
		}
	      
	      if (fireworks[i].time < -50)
		fireworks[i].alive = false;
	    }
	  else
	    {
	      if (Randnum.getInt(10) < 2)
		{
		  fireworks[i].alive = true;
		  fireworks[i].x = Randnum.getInt(ga.WIDTH);
		  fireworks[i].y = ga.HEIGHT;
		  fireworks[i].ym = -Randnum.getInt(10) - 1;
		  fireworks[i].xm = (Randnum.getInt(30)) / 10.0f;
		  if (fireworks[i].x > ga.WIDTH / 2)
		    fireworks[i].xm = -fireworks[i].xm;
		  fireworks[i].time = Randnum.getInt(50) + 20;
		}
	    }
	}
      
      
      /* Draw text: */

      ga.setColor(ga.explosioncolors[Randnum.getInt(ga.NUM_EXPLOSION_COLORS)]);
      ga.drawcenteredtext(0,ga.WIDTH, (ga.HEIGHT - ga.fh) / 2 - ga.fh,
			  "Congratulations!");
      
      ga.drawcenteredtext(0, ga.WIDTH,(ga.HEIGHT - ga.fh) / 2, title);
      
      ga.setColor(Color.white);
      if (counter%2 == 0) {
	  ga.drawcenteredtext(0, ga.WIDTH,
			      (ga.HEIGHT - ga.fh) / 2 + ga.fh * 2, leftAlign(name+"_",5));
      }
      else {
	  ga.drawcenteredtext(0, ga.WIDTH,
			      (ga.HEIGHT - ga.fh) / 2 + ga.fh * 2, leftAlign(name,5));
      }
      
      /* Get keys: */

      if (km.wasReleased(KeyEvent.VK_LEFT) ||
	  km.wasReleased(KeyEvent.VK_DELETE) ||
	  km.wasReleased(KeyEvent.VK_BACK_SPACE)) {
	  if (name.length() > 0) {
	      name = name.substring(0,name.length()-1);
	  }
      }
      
      if (km.wasReleased(KeyEvent.VK_ENTER)) {
	  done = 1;
      }

      name = checkCharacter(KeyEvent.VK_A,'A',name,5);
      name = checkCharacter(KeyEvent.VK_B,'B',name,5);
      name = checkCharacter(KeyEvent.VK_C,'C',name,5);
      name = checkCharacter(KeyEvent.VK_D,'D',name,5);
      name = checkCharacter(KeyEvent.VK_E,'E',name,5);
      name = checkCharacter(KeyEvent.VK_F,'F',name,5);
      name = checkCharacter(KeyEvent.VK_G,'G',name,5);
      name = checkCharacter(KeyEvent.VK_H,'H',name,5);
      name = checkCharacter(KeyEvent.VK_I,'I',name,5);
      name = checkCharacter(KeyEvent.VK_J,'J',name,5);
      name = checkCharacter(KeyEvent.VK_K,'K',name,5);
      name = checkCharacter(KeyEvent.VK_L,'L',name,5);
      name = checkCharacter(KeyEvent.VK_M,'M',name,5);
      name = checkCharacter(KeyEvent.VK_N,'N',name,5);
      name = checkCharacter(KeyEvent.VK_O,'O',name,5);
      name = checkCharacter(KeyEvent.VK_P,'P',name,5);
      name = checkCharacter(KeyEvent.VK_Q,'Q',name,5);
      name = checkCharacter(KeyEvent.VK_R,'R',name,5);
      name = checkCharacter(KeyEvent.VK_S,'S',name,5);
      name = checkCharacter(KeyEvent.VK_T,'T',name,5);
      name = checkCharacter(KeyEvent.VK_U,'U',name,5);
      name = checkCharacter(KeyEvent.VK_V,'V',name,5);
      name = checkCharacter(KeyEvent.VK_W,'W',name,5);
      name = checkCharacter(KeyEvent.VK_X,'X',name,5);
      name = checkCharacter(KeyEvent.VK_Y,'Y',name,5);
      name = checkCharacter(KeyEvent.VK_Z,'Z',name,5);
      name = checkCharacter(KeyEvent.VK_1,'1',name,5);
      name = checkCharacter(KeyEvent.VK_2,'2',name,5);
      name = checkCharacter(KeyEvent.VK_3,'3',name,5);
      name = checkCharacter(KeyEvent.VK_4,'4',name,5);
      name = checkCharacter(KeyEvent.VK_5,'5',name,5);
      name = checkCharacter(KeyEvent.VK_6,'6',name,5);
      name = checkCharacter(KeyEvent.VK_7,'7',name,5);
      name = checkCharacter(KeyEvent.VK_8,'8',name,5);
      name = checkCharacter(KeyEvent.VK_9,'9',name,5);
      name = checkCharacter(KeyEvent.VK_0,'0',name,5);

      km.reset();
      
      /* Refresh: */
      
      ga.frame();
      
      
      /* Pause: */
      
      syncRate();
      
    }
  while (done == 0);
  
  return name;
}

  
/* Reset level (graphics, shapes, objects, etc.): */

void initlevel()
{
  int i, j, l;
  
  
  /* Init aliens: */

  for (i = 0; i < MAX_ALIENS; i++)
    aliens[i].alive = false;

  
  for (i = 0; i < MAX_ALIENS; i++)
    {
      if (i < 10 || (i < 20 && level > 10))
	{
	  aliens[i].alive = true;
	  
	  aliens[i].hasship = false;
	  aliens[i].isship = false;
	  
	  
	  /* Alien types: */
	  
	  if (level % 2 == 0)
	    {
	      aliens[i].type = TYPE_GUARD;
	      if (i >= 5)
		aliens[i].type = TYPE_PAWN;
	    }
	  else
	    {
	      aliens[i].type = TYPE_GUARDA;
	      if (i >= 5)
		aliens[i].type = TYPE_PAWNA;
	    }
	  
	  aliens[i].mode = MODE_ENTER;
	  
	  
	  /* Set their home positions: */

	  aliens[i].homex = 24 * (i % 5) * 2 + 80 - 32;
	  aliens[i].homey = 48;
	  if (i >= 5 && i < 10)
	    aliens[i].homey = 80;
	  else if (i >= 10 && i < 15)
	    aliens[i].homey = 112;
	  
	  
	  aliens[i].gotox = aliens[i].homex;
	  aliens[i].gotoy = aliens[i].homey;
	  
	  
	  /* Do they escape or join the crew? */
	  
	  aliens[i].goaway = 0;
	  if ((i >= 10 && level < 10) || i >= 15)
	    aliens[i].goaway = 1;
	  
	  aliens[i].dir = DIR_UP;
	  
	  
	  /* Starting positions: */
	  
	  l = level % 4;
	  
	  if (l == 0)
	    {
	      aliens[i].x = -32 - i * 20;
	      if (i % 2 == 0)
		aliens[i].x = ga.WIDTH + i * 20;
	      
	      aliens[i].y = ga.HEIGHT / 2 + (i % 5) * 10;
	    }
	  else if (l == 1)
	    {
	      aliens[i].x = -32;
	      if (i % 2 == 0)
		aliens[i].x = ga.WIDTH;
	      
	      aliens[i].y = ga.HEIGHT / 2 + (i % 5) * 10;
	    }
	  else if (l == 2)
	    {
	      aliens[i].x = -32 - i * 20;
	      if (i % 2 == 0)
		aliens[i].x = ga.WIDTH + i * 20;
	      
	      aliens[i].y = (ga.HEIGHT * 2) / 3;
	    }
	  else if (l == 3)
	    {
	      aliens[i].x = -32 - i * 20;
	      if (i % 2 == 0)
		aliens[i].x = ga.WIDTH + i * 20;
	      
	      aliens[i].y = ga.HEIGHT - 32 - (i / 2) * 16;
	    }
	}
    }
  
  
  /* Init master aliens: */
  
  for (i = 0; i < 2; i++)
    {
      j = MAX_ALIENS - 2 + i;
      
      aliens[j].alive = true;
      aliens[j].type = TYPE_MASTER_0;
      
      aliens[j].homex = ga.WIDTH / 2 - 48 + (i * 64);
      aliens[j].homey = 16;
      
      aliens[j].gotox = ga.WIDTH / 2 - 16;
      aliens[j].gotoy = ga.HEIGHT / 3;
      
      aliens[j].x = (ga.WIDTH + 32) * i - 32;
      aliens[j].y = ga.HEIGHT / 2;
      
      aliens[j].goaway = 0;
      
      aliens[j].dir = DIR_UP;
      aliens[j].mode = MODE_ENTER;
      
      aliens[j].hasship = false;
      aliens[j].isship = false;
      
      aliens[j].hitpoints = 10;
    }
  
  
  /* Init star speed: */
  
  wantstarspeed = (level / 5) + 1;
  faststarspeed = ((level / 5) + 1) * 10;
  changestarspeed = (level / 5) + 1;

  starspeed = wantstarspeed;
  starspeedm = 0;
  starspeedtime = 30;
  gamemode = GAMEMODE_WARP;
  
  
  /* Init alien speed: */
  
  alien_speed = level / 3;
  if (alien_speed < 1)
    alien_speed = 1;
  else if (alien_speed > 4)
    alien_speed = 4;
  
  
  /* Giant bug mode? */
  
  giant_bugs = false;
  if (level % 10 == 0)
    giant_bugs = true;
}


/* Reset game (positions, etc.): */

void initgame()
{
  int i;
  
  
  /* Center player: */
  
  player.alive = true;
  player.size = 1;
  player.x = ga.WIDTH / 2;
  
  extraship.alive = false;
  
  lives = 3;
  score = 0;
  gameover = 0;
  num_shots = 0;
  num_hits = 0;
  
  
  /* Init bullets: */
  
  for (i = 0; i < MAX_BULLETS; i++)
    bullets[i].alive = false;
  
  player.shots_out = 0;

  
  /* Init explosion bits: */
  
  for (i = 0; i < MAX_EXPLOSIONBITS; i++)
    explosionbits[i].alive = false;
  
  /* Init explosions: */
  
  for (i = 0; i < MAX_EXPLOSIONS; i++)
    explosions[i].alive = false;
  
  
  /* Init stars: */
  
  initstars();
  
  
  /* Init planet: */
  
  planet.alive = false;


  /* Init. asteroids: */
  
  for (i = 0; i < MAX_ASTEROIDS; i++)
    asteroids[i].alive = false;
}


/* Reset stars: */

void initstars()
{
  int i;
  
  
  /* Starting position for stars: */
  
  for (i = 0; i < MAX_STARS; i++)
    {
      stars[i].x = Randnum.getInt(ga.WIDTH);
      stars[i].y = Randnum.getInt(ga.HEIGHT);
      stars[i].speed = Randnum.getInt(5);
    }
}


/* Determine which way to turn to change direction from curdir to wantdir  */

int dirtowards(int wantdir, int curdir)
{
  int m = 0;
  int newdir;
  
  
  if (wantdir < curdir)
    wantdir = wantdir + 8;
  
  if (wantdir == curdir)
    m = 0;
  else if (wantdir - curdir > 4)
    m = -1;
  else if (wantdir - curdir <= 4)
    m = 1;
  
  newdir = curdir + m;
  
  if (newdir < 0)
    newdir = 7;
  else if (newdir > 7)
    newdir = 0;
  
  return(newdir);
}


/* Adds a bullet: */

void addbullet(int x, int y, int xm, int ym, int owner)
{
  int found, i;
  
  found = -1;
  
  for (i = 0; i < MAX_BULLETS; i++)
    if (!bullets[i].alive)
      found = i;

  if (found != -1)
    {
      bullets[found].alive = true;
      bullets[found].x = x;
      bullets[found].y = y;
      bullets[found].xm = xm;
      bullets[found].ym = ym;
      bullets[found].owner = owner;
    }
}


/* Adds a few bits of explosion: */

void addexplosion(int x, int y, int xm, int ym)
{
  int i;
  
  
  for (i = 0; i < 5; i++)
    addexplosionbit(x + Randnum.getInt(5) - 2, y - Randnum.getInt(5) + 2,
		    xm + Randnum.getInt(5) - 2, ym + Randnum.getInt(5) - 2);
}


/* Adds a bit of explosion: */

void addexplosionbit(int x, int y, int xm, int ym)
{
  int i, found;
  
  found = -1;
  
  for (i = 0; i < MAX_EXPLOSIONBITS; i++)
    {
      if (!explosionbits[i].alive)
	found = i;
    }
  
  if (found != -1)
    {
      explosionbits[found].alive = true;
      explosionbits[found].time = 10 + Randnum.getInt(20);
      
      explosionbits[found].x = x;
      explosionbits[found].y = y;
      explosionbits[found].xm = xm / 2;
      explosionbits[found].ym = ym / 2;
      
      if (Randnum.getInt(10) < 3)
	explosionbits[found].ym = -ym;
    }
}


/* Add explosion, remove player (or one of the two ships if there are two): */

void killplayer(int x)
{
  int i;
  

  /* Make explosion: */

  addanimatedexplosion(x, ga.HEIGHT - 16);
  
  
  /* Kill or hurt player: */
  
  if (player.size > 1)
    {
      /* Lost one ship: */
      
      player.size--;
      
      if (x < player.x + 32)
	player.x = player.x + 32;
    }
  else
    {
      /* Dead! */
      
      turnoffplayer();


      /* Make all aliens go home: */
      
      for (i = 0; i < MAX_ALIENS; i++)
	{
	  if (aliens[i].alive && aliens[i].goaway == 0)
	    aliens[i].mode = MODE_ENTER;
	}
      
      gamemode = GAMEMODE_ENTER;
    }
  
  flashscreen = 4;
}


/* Kill player, remove a life, end game if no more lives: */

void turnoffplayer()
{
  player.alive = false;
  lives--;
  
  if (lives == 0)
    gameover = 1;
}   


/* Call drawshape for title screens: */

void helpshape(int pos, int y, int obj)
{
  int x=0;
  
  if (pos == HELPSHAPE_CENTER)
    x = (ga.WIDTH - ga.object_width[obj]) / 2;
  else if (pos == HELPSHAPE_LEFT)
    x = ga.WIDTH / 4 - ga.object_width[obj] / 2;
  else if (pos == HELPSHAPE_RIGHT)
    x = (ga.WIDTH * 3) / 4 - ga.object_width[obj] / 2;
  
  ga.drawshape(x, y, obj);
}


/* Draw help screen's text: */

void helptext(int y, String text) {
    ga.setColor(Color.white);
    ga.drawcenteredtext(0, ga.WIDTH, y + 32 + ga.fh,text);
}


/* Remove bullet. Count one less bullet out if this was the player's: */

void killbullet(int which) {
    if (bullets[which].owner == OWNER_PLAYER) {
    player.shots_out--;
    }
  
  bullets[which].alive = false;
}


/* Load highs from disk or get defaults: */

void loadhighscores() {
    // FILE * fi;
    int i, z;
    
  
  /* Open file: */
  
  //  fi = fopen("galaxa-highs.dat", "r");
  
  //  if (fi == NULL)
  //    {
      /* Set defaults: */
      
  //      perror("galaxa-highs.dat");
      
      for (i = 0; i < 10; i++)
	{
	  highscores[i].score = 10000 - i * 750;
	  
	  z = Randnum.getInt(3);
	  
	  if (z == 0)
	    highscores[i].name= "NBS";
	  else if (z == 1)
	    highscores[i].name= "BJK";
	  else if (z == 2)
	    highscores[i].name= "GAL";
	  
	  
	  highlevels[i].score = 5;
	  highlevels[i].name= "BJK";
	}
      
      highhitratio = 50.0f;
      highhitrationame= "FJI";
      //    }
//  else
//    {
      /* Load from file: */
      
//      for (i = 0; i < 10; i++)
//	{
	    //	  fscanf(fi, "%d %s", &(highscores[i].score), highscores[i].name);
//	}
      
//      for (i = 0; i < 10; i++)
//	{
	    //	  fscanf(fi, "%d %s", &(highlevels[i].score), highlevels[i].name);
//	}
      
      //      fscanf(fi, "%f %s", &highhitratio, highhitrationame);
//    }
}


/* Dump scores: */

void savehighscores()
{
    //  FILE * fi;
  int i;
  
  //  fi = fopen("galaxa-highs.dat", "w");
  
  //  if (fi == NULL)
  //    {
  //      perror("galaxa-highs.dat");
  //    }
  //  else
  //    {
  //      for (i = 0; i < 10; i++)
  //	{
	    //  fprintf(fi, "%d %s\n", highscores[i].score, highscores[i].name);
  //	}
  //      for (i = 0; i < 10; i++)
  //	{
	    //	  fprintf(fi, "%d %s\n", highlevels[i].score, highlevels[i].name);
  //	}
      
      //      fprintf(fi, "%f %s\n", highhitratio, highhitrationame);
      
  //      fclose(fi);
  //    }
}


/* Add an animated explosion graphic: */

void addanimatedexplosion(int x, int y)
{
  int i, found;
  
  found = -1;
  
  for (i = 0; i < MAX_EXPLOSIONS; i++)
    {
      if (!explosions[i].alive)
	found = i;
    }
  
  if (found == -1)
    found = 0;
  
  explosions[found].alive = true;
  explosions[found].frame = 0;
  explosions[found].x = x;
  explosions[found].y = y;
  
  //  playsound(sound_fs, SND_FLASH);
}


/* Add an asteroid to the game.
   Send -1, -1, 0, 0 to have arbitrary position/direction determined: */

void addasteroid(int x, int y, int xm, int ym, int size)
{
  int i, found, z;
  
  found = -1;
  
  for (i = 0; i < MAX_ASTEROIDS; i++)
    {
      if (!asteroids[i].alive)
	found = i;
    }
  
  if (xm == 0 && ym == 0)
    ym = 1;
	      
  if (found != -1)
    {
      if (x == -1)
	{
	  z = Randnum.getInt(3);
	  
	  if (z == 0)
	    {
	      x = Randnum.getInt(ga.WIDTH);
	      xm = Randnum.getInt(5);
	      
	      if (x > ga.WIDTH / 2)
		xm = -xm;
	      
	      ym = Randnum.getInt(5);
	    }
	  else if (z == 1 || z == 2)
	    {
	      if (z == 1)
		{
		  x = 0;
		  xm = Randnum.getInt(5);
		}
	      else if (z == 2)
		{
		  x = ga.WIDTH - 50;
		  xm = -Randnum.getInt(5);
		}
	      
	      y = Randnum.getInt((ga.HEIGHT / 3) * 2);
	      
	      ym = Randnum.getInt(5);
	    }
	}
      
      asteroids[found].alive = true;
      asteroids[found].x = x;
      asteroids[found].y = y;
      asteroids[found].xm = xm;
      asteroids[found].ym = ym;
      asteroids[found].size = size;
      asteroids[found].anim = Randnum.getInt(5);
      asteroids[found].animm = Randnum.getInt(3) - 1;
      asteroids[found].animspeed = Randnum.getInt(5) + 1;
    }
}

public String leftAlign(String s, int size) {
    String s2 = "          ";
    while (s.length() < size) {
	s += s2;
    }
    return s.substring(0,size);
}
public String rightAlign(String s, int size) {
    String s2 = "          ";
    while (s.length() < size) {
	s = s2+s;
    }
    return s.substring(s.length()-size);
}

}
