/*
  ______                                       _ _                       
 |  ____|                                /\   | | |                      
 | |__   _ __ ___  _ __  _ _ __ ___     /  \  | | | ___  __ _ _ __ ___   
 |  __| |  _   _ \|  _ \| |  __/ _ \   / /\ \ | | |/ _ \/ _  |  __/ _ \  
 | |____| | | | | | |_) | | | |  __/  / ____ \| | |  __/ (_| | | | (_) | 
 |______|_| |_| |_|  __/|_|_|  \___| /_/    \_|_|_|\___|\__  |_|  \___/  
                  | |           ___                      __/ |           
                  |_|          |__ \                    |___/            
                                  ) |
                                 / / 
                                / /_ 
                               |____|
 BY KENT DEVILLAFRANCA
*/

#include "empire.h"
#define DEBUGGING 1

volatile int counter;

_globalsettings global;
_logic_variables var;
_character *currentcharacter[4];
_character *loadedcharacter[4];
vector<_character *> character;
vector<Bitmap *> avatars;
_player player[4];
_map worldmap;
_tile tile;
_minimap minimap;

int first_mission_character;  //the first "mission-only" AI character

DATAFILE *graphics;
DATAFILE *dunits;

bitmapdat land, river, sea, shoal, buildings, special;
bitmapdat mouse;
bitmapdat glb;
bitmapdat explode1;
bitmapdat units[4][18];

Bitmap *transition;
Bitmap *mapunits[72];

TextRenderer normal;
TextRenderer big;

string title_music;

void load_global_settings();
void init_tile_animations();
int load_characters();

int intro();
int logic();
int menu();
int mapedit();
int playeredit();
int show_winner();
int mission();
int do_transition(int target);
int player_color(int c);
void save_debug_info();
void save_pathmap_info();
void save_unitmap_info();
void empdebug(string text);
string init_everything();

string unit_name(int type);
int unit_type(string name);

void timer_handler()
{
  counter++;
}
END_OF_FUNCTION(timer_handler);


_init_variables init;


int main()
{
  int j, oldstatus, transitionto = TRANSITION;
  unsigned int i;
  bool draw;
  i = 0;
  oldstatus = GAMEINTRO;
  
  title_music = "data/music/title";
  
  empdebug("-CLEAR-");
  empdebug(""); empdebug("Starting Empire Allegro 2...");
  empdebug("Setting up all the stuff...");
	
	#ifdef ALLEGRO_LINUX
		XInitThreads();  //without this, moving the window will crash on Intel i810 systems
  #endif
	
	string s = init_everything();
  if (s != "-")
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    empdebug(s);
    return 1;
  }
  
  global.gamestatus = GAMEINTRO;
  
  drawqueue.reserve(500);
  
  counter = 0;
  worldmap.reset();
  var.first = true;
  draw = true;
  
  empdebug("Finished doing the initial setup and loading, going into the actual game...");
  
  while (global.gamestatus != QUIT)
  {

    while (counter > 0)
    {
			if (global.sound)
			{
				FMOD_System_Update(fmodmain);
			  ensure_music_is_playing();
			}
			
      drawqueue.clear();
      buffer_clear_to_color(BLACK);
      //oldstatus = global.gamestatus;
      if ((key[KEY_LCONTROL]) && (key[KEY_B]))
      {
        global.gamestatus = QUIT;
      }
      switch(global.gamestatus)
      {
        case GAMEINTRO:
          global.gamestatus = intro();
          break;
        case MENU:
          global.gamestatus = menu();
          break;
        case LOGIC:
          global.gamestatus = logic();
          break;
        case GAMEOVER:
          global.gamestatus = show_winner();
          break;
        case MAPEDIT:
          global.gamestatus = mapedit();
          break;
        case PLAYEREDIT:
          global.gamestatus = playeredit();
          break;
        case MISSION:
          global.gamestatus = mission();
          break;
        case TRANSITION:
          global.gamestatus = do_transition(transitionto);
          break;
      }
      draw = true;
			/*if ((global.gamestatus != oldstatus) && (oldstatus != TRANSITION))
      {
        if ((oldstatus != GAMEINTRO) && (global.gamestatus != QUIT))
        {
          transitionto = global.gamestatus;
          if (transitionto == TRANSITION)  //if the gamestatus was set to TRANSITION
          {
            transitionto = MENU;  //it was from a change in the menu
          }
          draw_all();
          copy_screen_to(transition);
          draw = false;
          global.gamestatus = TRANSITION;
        }
      }*/
      counter--;
    }
    if (draw)
    {
      draw_all();
      draw = false;
    }

    if ((key[KEY_D]) && (global.gamestatus == LOGIC))
    {  //save a metric crapload of debug info
      save_debug_info();
      save_pathmap_info();
      save_unitmap_info();
    }
		if (key[KEY_F12])
		{  //save a screenshot
			Canvas::Save("screenshot.png");
			counter = 0;
		}
			
    rest(1);
  }
  
  Settings::RestoreOldProjection();
	empdebug("Game over, saving settings...");
  ofstream settings("empire.ini");
  if (!(settings.bad()))
  {
    settings << "MouseSpeed " << global.mspeed << "\n";
    settings << "SFXVolume " << global.volume << "\n";
    settings << "MusicVolume " << global.music_volume << "\n";
    settings << "fullscreen " << global.fullscreen << "\n";
    settings << "particles " << global.particles << "\n";
    settings << "maporder " << global.maporder << "\n";
    settings << "windowedres " << global.windowed_resolution << "\n";
    settings << "scrolldivider " << global.scroll_divider << "\n";
    settings << "AIscrolldivider " << global.AI_scroll_divider << "\n";
    settings << "battleanimation " << global.battle_animation << "\n";
    settings.close();
  }
  
  empdebug("Unloading the bitmaps...");
  i = 0;
  while (i < avatars.size())
  {
    avatars[i]->Destroy();
    i++;
  }
	empdebug("deleting characters");
	i = 0;
	while (i < character.size())
	{
		character[i]->destroy();
		delete(character[i]);
		i++;
	}
	i = 0;
	while (i < 4)
	{
		if (loadedcharacter[i] != NULL)
		{
			delete(loadedcharacter[i]);
			loadedcharacter[i] = NULL;
		}
		i++;
	}
	empdebug("done deleting characters");
  
  shutdown_sound();
	
	multiline_textout_ex(normal, "/GAMEOVER/", 0, 0, 0, 0);  //frees malloc'd memory used in static char*s

  transition->Destroy();
	delete transition;
	
  minimap.destroy();
  land.destroy();
  river.destroy();
  sea.destroy();
  shoal.destroy();
  buildings.destroy();
  special.destroy();
  mouse.destroy();
  glb.destroy();
  explode1.destroy();
  i = 0;
  while (i < 4)
  {
    j = 0;
    while (j < 18)
    {
      units[i][j].destroy();
      j++;
    }
    i++;
  }
  empdebug("Finished unloading everything, exiting...");
  allegro_exit();
  empdebug("Done.");
	exit(0);
  return 0;
}
END_OF_MAIN()





int intro()
{
  static bool first = true;
  static float a;
  static int x;
  if (first)
  {
    a = 0.0;
    x = (640 - glb.bmp(0)->Width()) / 2;
    first = false;
  }
  if (a < 1.0)
  {  //fade in the globe
    glb.draw(0, x, 100, a);
  }
  else if (a < 1.50)
  {  //flash white for 2 cycles
    glb.draw(0, x, 100);
  }
  else if (a < 1.54)
  {
    buffer_clear_to_color(WHITE);
  }
  else
  {
    global.gamestatus = menu();
    return MENU;
  }
  a += 0.02;
  return GAMEINTRO;
}




string init_everything()
{
  bool goodmode = false;
  bool fullscreen = false;
  int i, j, z;
  DATAFILE *dexplosions;
  DATAFILE *dexplode1;
  DATAFILE *dp[4];
  DATAFILE *dtiles;
  DATAFILE *dmouse;
  DATAFILE *dland;
  DATAFILE *driver;
  DATAFILE *dsea;
  DATAFILE *dshoal;
  DATAFILE *dbuildings;
  DATAFILE *dspecial;
  DATAFILE *dglb;
  DATAFILE *t, *q;
 
  srand(time(NULL));
  LOCK_VARIABLE(counter);
  LOCK_FUNCTION(timer_handler);
  
  empdebug("  Setup::SetupProgram()...");
	if (!Setup::SetupProgram())
  {
    return "Couldn't set up the program for some reason.";
  }
	empdebug("    ...done");
  
	empdebug("  load_global_settings()...");
  load_global_settings();
	empdebug("    ...done");
  
  if (global.fullscreen == 1)
  {
    fullscreen = true;
  }
	
	i = 0;
	while (i < 4)
	{
		loadedcharacter[i] = NULL;
		currentcharacter[i] = NULL;
		i++;
	}
  
	empdebug("  Setup::SetupScreen()...");
  z = 0;
  while ((!goodmode) && (z < 4))
  {
    if (fullscreen)
    {
      i = 640; j = 480;
    }
    else
    {
      switch(global.windowed_resolution)
      {
        default:
        case 0:
          i = 640; j = 480;
          break;
        case 1:
          i = 800; j = 600;
          break;
        case 2:
          i = 1024; j = 768;
          break;
        case 3:
          i = 1280; j = 960;
          break;
      }
    }
    if (!Setup::SetupScreen(i, j, fullscreen))
    {
			if (fullscreen)
			{
				global.fullscreen = false;
				fullscreen = false;
				z--;
				empdebug("Couldn't start using fullscreen!  Switching to windowed.");
			}
			else
			{
				empdebug("Couldn't start using windowed resolution, trying next one...");
        global.windowed_resolution++;
        if (global.windowed_resolution > 3) global.windowed_resolution = 0;
		  }
    }
    else
    {
      goodmode = true;
    }
    z++;
    if (fullscreen) z = 4;
  }
  if (!goodmode)
  {
    return "Couldn't set up a graphics mode (this game uses OpenGL, so maybe it's your drivers).";
  }
	empdebug("    ...done");
	global.screen_width = i;
	global.screen_height = j;
  Settings::SetOrthographicProjection(640, 480);

	glPointSize(2);
	
  gfx_driver->w = 640;  //these two lines are so Glyph Keeper
  gfx_driver->h = 480;  //gets the text size right
  
  normal.Load("data/rock.ttf", 12, 10, Rgba(0, 0, 0, 255));
  big.Load("data/rock.ttf", 20, 20, Rgba(0, 0, 0, 255));
  
	Canvas::Fill(Rgba(BLACK, 255));
  big.SetColor(Rgba(WHITE, 255));
  big.Print("Loading...", 20, 30);
	Canvas::Refresh();

  install_int_ex(timer_handler, BPS_TO_TIMER(50));
	
  if (!init_sound())
  {
		global.sound = false;
		empdebug("  Couldn't set up FMOD, continuing without music or sound...");
  }
  
	if (global.sound)
	{
  	load_sounds();
	}
	jpgalleg_init();
  
	empdebug("  Loading bitmaps from data/empire.dat...");
  graphics = load_datafile("data/empire.dat");
  if (!graphics)
  {
    return "Unable to load data/empire.dat";
  }
  dtiles      = (DATAFILE *)graphics[0].dat;
      dland      = (DATAFILE *)dtiles[0].dat;
      driver     = (DATAFILE *)dtiles[1].dat;
      dsea       = (DATAFILE *)dtiles[2].dat;
      dshoal     = (DATAFILE *)dtiles[3].dat;
      dbuildings = (DATAFILE *)dtiles[4].dat;
      dspecial   = (DATAFILE *)dtiles[5].dat;
  dmouse      = (DATAFILE *)graphics[1].dat;
  dglb        = (DATAFILE *)graphics[2].dat;
  dexplosions = (DATAFILE *)graphics[3].dat;
      dexplode1  = (DATAFILE *)dexplosions[0].dat;
  
  land.load(dland);
  river.load(driver);  //my datafile names are originality incarnate
  sea.load(dsea);
  shoal.load(dshoal);
  buildings.load(dbuildings);
  special.load(dspecial);
  init_tile_animations();
  mouse.load(dmouse);
  glb.load(dglb);  //fun fact: glb originally only held the globe from the title, now it holds random stuff
  explode1.load(dexplode1);
	empdebug("    ...done");
	
	transition = new Bitmap(640, 480);

  empdebug("  Loading bitmaps from data/units.dat...");
  dunits = load_datafile("data/units.dat");
  if (!units)
  {
    return "Unable to load data/units.dat";
  }
  dp[0] = (DATAFILE *)dunits[0].dat;
  dp[1] = (DATAFILE *)dunits[1].dat;
  dp[2] = (DATAFILE *)dunits[2].dat;
  dp[3] = (DATAFILE *)dunits[3].dat;
  
  i = 0;
  while (i < 4)
  {
    t = dp[i];
    j = 0;
    while (j < 18)
    {
      q = (DATAFILE *)t[j].dat;
      units[i][j].load(q);  //load all the unit bitmaps (i = team, j = unit type)
      j++;
    }
    i++;
  }

  i = 0;
  while (i < 4)
  {
    j = 0;
    while (j < 18)
    {
      mapunits[(j * 4) + i] = units[i][j].bmp(0);
      j++;
    }
    i++;
  }
	empdebug("    ...done");
	
  empdebug("  load_characters()...");
  if (load_characters() != 0)
  {
    return "Unable to load data/players.dat or data/missionplayers.dat";
  }
	empdebug("  ...done");
  
  mouse_type = MOUSE_NORMAL;
  return "-";
}

void init_tile_animations()
{
  bitmapdat *tiledats[6] = {&land, &river, &sea, &shoal, &buildings, &special};
  bitmapdat *current;
  int i = 0;
  int j;
  animtiles temp;
  
  while (i < 6)
  {
    current = tiledats[i];
    j = 0;
    while (j < current->size)
    {
      if (current->bmp(j)->Width() > MAP_TILE_SIZE)
      {
        temp.set = i;
        if (i > 4) temp.set++;  //compensate for the units datafile (which is set 5, but doesn't show up here)
        temp.num = j;
        temp.framenum = current->bmp(j)->Width() / MAP_TILE_SIZE;
        temp.frameinc = 0.08;
        animated_tiles.push_back(temp);
      }
      j++;
    }
    i++;
  }
}




void load_global_settings()
{
  ifstream opt("empire.ini");
	char descriptor[30];
  
	global.sound = true;
	
	global.mspeed = 2;
  global.volume = 75;
  global.music_volume = 100;
  global.fullscreen = 0;
  global.particles = 1;
  global.maporder = 0;
  global.windowed_resolution = 0;
  global.scroll_divider = 4;
  global.AI_scroll_divider = 2;
  global.battle_animation = 1;
	
	if (!opt.bad())
  {
    opt >> descriptor >> global.mspeed;
    opt >> descriptor >> global.volume;
    opt >> descriptor >> global.music_volume;
    opt >> descriptor >> global.fullscreen;
    opt >> descriptor >> global.particles;
    opt >> descriptor >> global.maporder;
    opt >> descriptor >> global.windowed_resolution;
    opt >> descriptor >> global.scroll_divider;
    if ((global.scroll_divider < 1) || (global.scroll_divider > 16))
    {  //if someone's been messing with the config file stupidly
      global.scroll_divider = 4;  //this will set scroll_divider back to the default
    }  //(preventing weird scrolling issues and possibly a divide by zero error)
    opt >> descriptor >> global.AI_scroll_divider;
    if ((global.AI_scroll_divider < 1) || (global.AI_scroll_divider > 16))
    {  //if someone's been messing with the config file stupidly
      global.AI_scroll_divider = 2;  //this will set AI_scroll_divider back to the default
    }  //(preventing weird scrolling issues and possibly a divide by zero error)
    opt >> descriptor >> global.battle_animation;
  }
}





int do_transition(int target)
{
	return target;
/*  static int time = 0;
  static int type = 0;
  static bool out = true;
  static bool first = true;
  int j;
  
  if (first)
  {
    type = 0;//rand()%4;
    time = 0;
    first = false;
    out = true;
  }

  time++;
  if (out)
  {
    buffer_blit(transition, 0, 0);
    switch(type)
    {
      case 0:
        j = 0;
        while (j < 32)
        {
					buffer_rectfill(20 * j, 0, time + 20 * j, 480, BLACK);
          j++;
        }
        if (time >= 20)
        {
          time = -1;
          out = false;
        }
        break;
      case 1:
        buffer_rectfill(0, 0, 32 * time, 480, BLACK);
        if (time >= 20)
        {
          time = -1;
          out = false;
        }
        break;
      case 2:
        j = 0;
        while (j < 480)
        {
          if (j % 2 == 0)
          {
            buffer_hline(0, j, 40 * time - (j / 2), BLACK);
          }
          else
          {
            buffer_hline(640 - (40 * time) + (j / 2), j, 640, BLACK);
          }
          j++;
        }
        if (time >= 23)
        {
          time = -1;
          out = false;
        }
        break;
      case 3:
        buffer_rectfill(0, 0, 640, time * 20, BLACK);
        buffer_rectfill(0, 480 - (time * 20), 640, 480, BLACK);
        if (time >= 12)
        {
          time = -1;
          out = false;
        }
        break;
    }
  }
  else
  {
    if (time == 0)
    {
      switch(target)
      {  //do the transitioned-to function once, to draw it
        case MENU:
          menu();
          break;
        case MAPEDIT:
          mapedit();
          break;
        case PLAYEREDIT:
          playeredit();
          break;
        case MISSION:
          mission();
          break;
      }
      draw_all(transition);
    }
    else
    {
      buffer_blit(transition, 0, 0);
      switch (type)
      {
        case 0:
          j = 0;
          while (j < 32)
          {
            buffer_rectfill(time + 20 * j, 0, 20 + 20 * j, 480, BLACK);
            j++;
          }
          if (time >= 20)
          {
            first = true;
            return target;
          }
          break;
        case 1:
          buffer_rectfill(32 * time, 0, 640, 480, BLACK);
          if (time >= 20)
          {
            first = true;
            return target;
          }
          break;
        case 2:
          j = 0;
          while (j < 480)
          {
            if (j % 2 == 0)
            {
              buffer_hline(40 * time - (j / 2), j, 640, BLACK);
            }
            else
            {
              buffer_hline(0, j, 640 - (40 * time) + (j / 2), BLACK);
            }
            j++;
          }
          if (time >= 23)
          {
            first = true;
            return target;
          }
          break;
        case 3:
          buffer_rectfill(0, 0, 640, 240 - (time * 20), BLACK);
          buffer_rectfill(0, 240 + (time * 20), 640, 480, BLACK);
          if (time >= 12)
          {
            first = true;
            return target;
          }
          break;
      }
    }
  }
  return TRANSITION;*/
}


int load_characters()
{
  int i, num;
  char thepath[30];
	string z;
	
  ifstream playerdat("data/players.dat");
  if (playerdat.bad())
  {
    empdebug("Couldn't load data/players.dat");
		return 1;
  }
	
	getline(playerdat, z);
	num = atoi(z.c_str());
	i = 0;
  while (i < num)
  {
		sprintf(thepath, "data/player%d.bmp", i + 1);
    
		avatars.push_back(new Bitmap(80, 80));
		avatars[avatars.size() - 1]->Load(thepath, CONVERT_MAGIC_PINK);
		character.push_back(new _character);
		load_character(&playerdat, character[character.size() - 1]);
		
    i++;
  	empdebug("    Loaded player.");
  }
  first_mission_character = i;
  playerdat.close();

  ifstream misplayerdat("data/missionplayers.dat");
  if (misplayerdat.bad())
  {
		empdebug("Couldn't load data/missionplayers.dat");
    return 1;
  }

  getline(misplayerdat, z);
  num = atoi(z.c_str());
  i = 0;
  while (i < num)
  {
		sprintf(thepath, "data/missionplayer%d.bmp", i + 1);
		
    avatars.push_back(new Bitmap(80, 80));
  	avatars[avatars.size() - 1]->Load(thepath, CONVERT_MAGIC_PINK);
    character.push_back(new _character);
		load_character(&misplayerdat, character[character.size() - 1]);
    
		i++;
	  empdebug("    Loaded missionplayer");
  }
  misplayerdat.close();

  return 0;
}

int show_winner()
{
  static int time = 0;
  static int delay = 0;
  static int current = -1;
  int i, t;
  if (time == 0)
  {
    delay = 0;
    current = -1;
//    buffer_blit(transition, 0, 0, 0, 0, 640, 480);
    time++;
  }
  else if (time < 60)
  {
    t = 60 - time;
//    buffer_blit(transition, 0, 0, 0, 0, 640, 480);
    buffer_rectfill(0, 0, 319 * time / 60, 480, DGREY);
    buffer_vline(320 * time / 60, 0, 480, GREY);
    buffer_vline(321 * time / 60, 0, 480, LGREY);
    buffer_rectfill(320 + (321 * t / 60), 0, 640, 480, DGREY);
    buffer_vline(320 + (320 * t / 60), 0, 480, GREY);
    buffer_vline(319 + (320 * t / 60), 0, 480, LGREY);
    buffer_textout_centre_ex(big, "Game Over", 320, time - 50, WHITE);
    time++;
  }
  else if (time < 128)
  {  //fade to black
    t = 128 - time;
    buffer_clear_to_color(makecol(t, t, t));
    buffer_textout_centre_ex(big, "Game Over", 320, 10, WHITE);
    time++;
  }
  else if (time < 188)
  {  //move player pictures from the bottom of the screen to y = 100
    time++;
    t = 188 - time;
    buffer_textout_centre_ex(big, "Game Over", 320, 10, WHITE);
    i = 0;
    while (i < 4)
    {
      if (player[i].everplaying == 1)
      {
        buffer_rectfill(130 + (100 * i), 100 + (t * 6), 130 + (100 * i) + 83, 183 + (t * 6), player_color(i));
        buffer_draw_sprite(currentcharacter[i]->picture, 132 + (100 * i), 102 + (t * 6));
      }
      i++;
    }
  }
  else if (time < 220)
  {  //pause for a bit
    buffer_textout_centre_ex(big, "Game Over", 320, 10, WHITE);
    i = 0;
    while (i < 4)
    {
      if (player[i].everplaying == 1)
      {
        buffer_rectfill(130 + (100 * i), 100, 130 + (100 * i) + 83, 183, player_color(i));
        buffer_draw_sprite(currentcharacter[i]->picture, 132 + (100 * i), 102);
      }
      i++;
    }
    time++;
  }
  else if (time == 220)
  {  //go through and replace defeated players with an X 
    buffer_textout_centre_ex(big, "Game Over", 320, 10, WHITE);
    i = 0;
    while (i < 4)
    {
      if (player[i].everplaying == 1)
      {
        buffer_rectfill(130 + (100 * i), 100, 130 + (100 * i) + 83, 183, player_color(i));
      }
      i++;
    }
    i = 0;
    while (i < 4)
    {
      if (i <= current)
      {
        if (player[i].everplaying == 1)
        {
          if (player[i].playing == 0)
          {
            glb.draw(19, 132 + (100 * i), 102);
          }
          else
          {
            buffer_draw_sprite(currentcharacter[i]->picture, 132 + (100 * i), 102);
          }
        }
      }
      else
      {
        if (player[i].everplaying == 1)
        {
          buffer_draw_sprite(currentcharacter[i]->picture, 132 + (100 * i), 102);
        }
      }
      i++;
    }
    if ((delay == 0) && (current < 4))
    {
      delay = 25;
      current++;
      if ((player[current].everplaying == 1) && (player[current].playing == 0))
      {
        i = rand()%3;
        switch(i)
        {
          case 0:
            play_sound(S_TANKFIRE);
            break;
          case 1:
            play_sound(S_MDTANKFIRE);
            break;
          case 2:
            play_sound(S_EXPLOSION);
            break;
        }
      }
    }
    else if (current < 4)
    {
      delay--;
    }
    if (current == 4)
    {
      time++;  //keeps this section active until current == 4
    }
  }
  else
  {
    if (time == 221)
    {
      play_sound(S_VICTORY);
    }
    else
    {
      time--;  //just to keep time from increasing any more
    }
    buffer_textout_centre_ex(big, "Game Over", 320, 10, WHITE);
    i = 0;
    t = 0;
    while (i < 4)
    {
      if (player[i].everplaying == 1)
      {
        buffer_rectfill(130 + (100 * i), 100, 130 + (100 * i) + 83, 183, player_color(i));
        if (player[i].playing == 0)
        {
          glb.draw(19, 132 + (100 * i), 102);
        }
        else
        {
          t++;
          buffer_rectrounded(129 + (100 * i), 99, 214 + (100 * i), 184, WHITE);
          buffer_draw_sprite(currentcharacter[i]->picture, 132 + (100 * i), 102);
        }
      }
      i++;
    }
    if (t == 1)
    {
      buffer_textout_centre_ex(big, "The Winner!", 320, 250, WHITE);
    }
    else
    {
      buffer_textout_centre_ex(big, "The Winners!", 320, 250, WHITE);
    }
    buffer_textout_centre_ex(normal, "Press Enter", 320, 400, WHITE);
    time++;
  }
  if (key[KEY_ENTER])
  {
    play_song(title_music);
    position_mouse(320, 240);
    time = 0;
    player[0].reset();
    player[1].reset();
    player[2].reset();
    player[3].reset();
    return MENU;
  }
  return GAMEOVER;
}

void save_debug_info()
{
  int i = 0;
  int j, k;
  _unit* u;
  ofstream dump("empiredump.txt");
  while (i < 4)
  {
    if (player[i].playing == 1)
    {
      dump << "PLAYER " << i << "\n";
      j = 0;
      while (j < 50)
      {
        u = &player[i].unit[j];
        dump << "  UNIT " << j << "\n";
        dump << "    exists:         " << u->exists << "\n";
        dump << "    type:           " << unit_name(u->type) << "\n";
        dump << "    tilex:          " << u->tilex << "\n";
        dump << "    tiley:          " << u->tiley << "\n";
        dump << "    ready:          " << u->ready << "\n";
        dump << "    color:          " << u->color << "\n";
        dump << "    number:         " << u->number << "\n";
        dump << "    gas:            " << u->gas << "\n";
        dump << "    ammo:           " << u->ammo << "\n";
        dump << "    health:         " << u->health << "\n";
        dump << "    capturing:      " << u->capturing << "\n";
        dump << "    submerged:      " << u->submerged << "\n";
        if ((u->type == T_COPTER) || (u->type == LANDER) || (u->type == APC))
        {
          k = 0;
          while (k < 2)
          {
            dump << "      UNIT LOAD " << k << "\n";
            dump << "        loaded:  " << u->load[k].loaded << "\n";
            dump << "        type:    " << unit_name(u->load[k].type) << "\n";
            dump << "        gas:     " << u->load[k].gas << "\n";
            dump << "        ammo:    " << u->load[k].ammo << "\n";
            dump << "        health:  " << u->load[k].health << "\n";
            if (u->load[k].type == APC)
            {
              dump << "          UNIT LOAD " << k << " SUBLOAD\n";
              dump << "            loaded:  " << u->load[k].subload.loaded << "\n";
              dump << "            type:    " << unit_name(u->load[k].subload.type) << "\n";
              dump << "            gas:     " << u->load[k].subload.gas << "\n";
              dump << "            ammo:    " << u->load[k].subload.ammo << "\n";
              dump << "            health:  " << u->load[k].subload.health << "\n";
            }
            k++;
          }
        }
        dump << "\n";
        j++;
      }
      dump << "\n";
    }
    i++;
  }
}

void save_pathmap_info()
{
  int i, j, k;
  ofstream path("pathmap.txt");
  j = 0;
  while (j < worldmap.h)
  {
    i = 0;
    while (i < worldmap.l)
    {
      k = worldmap.tile[i][j].get_step();
      if (k < 10) path << " ";
      path << k << " ";
      if (k < 99) path << " ";
      i++;
    }
    path << "\n";
    j++;
  }
}

void save_unitmap_info()
{
  int i, j, k;
  ofstream unit("unitmap.txt");
  j = 0;
  while (j < worldmap.h)
  {
    i = 0;
    while (i < worldmap.l)
    {
      k = worldmap.tile[i][j].unit_here();
      if ((k < 100) && (k != -1)) unit << " ";
      if (k < 10) unit << " ";
      unit << k << " ";
      i++;
    }
    unit << "\n";
    j++;
  }
}

string unit_name(int type)
{
  switch(type)
  {
    case ANTI_AIR:
      return "Anti-Air";
      break;
    case APC:
      return "APC";
      break;
    case ARTILLERY:
      return "Artillery";
      break;
    case B_COPTER:
      return "B-Copter";
      break;
    case B_SHIP:
      return "B-Ship";
      break;
    case BOMBER:
      return "Bomber";
      break;
    case CRUISER:
      return "Cruiser";
      break;
    case FIGHTER:
      return "Fighter";
      break;
    case INFANTRY:
      return "Infantry";
      break;
    case LANDER:
      return "Lander";
      break;
    case MD_TANK:
      return "Md-Tank";
      break;
    case MECH:
      return "Mech";
      break;
    case MISSILES:
      return "Missiles";
      break;
    case RECON:
      return "Recon";
      break;
    case ROCKETS:
      return "Rockets";
      break;
    case SUB:
      return "Sub";
      break;
    case T_COPTER:
      return "T-Copter";
      break;
    case TANK:
      return "Tank";
      break;
  }
  return "-";
}

int unit_type(string name)
{
  if (name == "Anti-Air")
  {
    return ANTI_AIR;
  }
  else if (name == "APC")
  {
    return APC;
  }
  else if (name == "Artillery")
  {
    return ARTILLERY;
  }
  else if (name == "B-Copter")
  {
    return B_COPTER;
  }
  else if (name == "B-Ship")
  {
    return B_SHIP;
  }
  else if (name == "Bomber")
  {
    return BOMBER;
  }
  else if (name == "Cruiser")
  {
    return CRUISER;
  }
  else if (name == "Fighter")
  {
    return FIGHTER;
  }
  else if (name == "Infantry")
  {
    return INFANTRY;
  }
  else if (name == "Lander")
  {
    return LANDER;
  }
  else if (name == "Md-Tank")
  {
    return MD_TANK;
  }
  else if (name == "Mech")
  {
    return MECH;
  }
  else if (name == "Missiles")
  {
    return MISSILES;
  }
  else if (name == "Recon")
  {
    return RECON;
  }
  else if (name == "Rockets")
  {
    return ROCKETS;
  }
  else if (name == "Sub")
  {
    return SUB;
  }
  else if (name == "T-Copter")
  {
    return T_COPTER;
  }
  else if (name == "Tank")
  {
    return TANK;
  }
  return -1;
}

int player_color(int c)
{
  switch(c)
  {
    case 0:
      return RED;
      break;
    case 1:
      return BLUE;
      break;
    case 2:
      return GREEN;
      break;
    case 3:
      return YELLOW;
      break;
    default:
      return BLACK;
      break;
  }
}

void empdebug(string text)
{
	if (DEBUGGING == 1)
	{
		if (text == "-CLEAR-")
		{
		  ofstream d("empdebug.txt");
		  d.close();
		}
		else
		{
			ofstream d("empdebug.txt", ios::app);
		  if (!d.bad())
			{
				d << text.c_str() << "\n";
			}
			d.close();
		}
	}
}
