#include "empire.h"
#include "logic.h"

void save_mission();
void debug_mission();
void save_mission_to_file(string thepath, string thename);
void load_missiondata();
void load_mission(string path);
int victory();
int defeat();
int check_conditions();
int select_mission();
int select_missionplayers();
int do_mission();

extern void draw_minimap(int x, int y, string file);
extern void description(int c, int x, int y);
extern void get_connected_beaches();
extern void get_teleports();

const int MISSION_SELECT       = 0;
const int MISSION_SELECTPLAYER = 1;
const int MISSION_INPROGRESS   = 2;
const int MISSION_COMPLETED    = 3;
const int MISSION_FAILED       = 4;
const int MISSION_EXIT         = 5;

//bit flags:
const int MODE_TIMED    = 0x01;  //time-based game
const int MODE_STANDARD = 0x02;  //standard defeat-the-enemy game
const int MODE_SURVIVAL = 0x04;  //just survive
const int MODE_PROTECT  = 0x08;  //protect a specific unit
const int MODE_DEFEND   = 0x10;  //prevent a tile from being captured
const int MODE_CONQUER  = 0x20;  //capture a tile
const int MODE_KILL     = 0x40;  //destroy a specific unit

extern int numplayers;

_mission_variables mis;

int mission()
{
  static bool first = true;
  static int missionstate;
  
  if (first)
  {
    missionstate = MISSION_SELECT;
    first = false;
  }
  
  switch(missionstate)
  {
    case MISSION_SELECT:
      missionstate = select_mission();
      break;
    case MISSION_SELECTPLAYER:
      missionstate = select_missionplayers();
      break;
    case MISSION_INPROGRESS:
      missionstate = do_mission();
      break;
    case MISSION_COMPLETED:
      missionstate = victory();
      break;
    case MISSION_FAILED:
      missionstate = defeat();
      break;
    case MISSION_EXIT:
      first = true;
      return MENU;
      break;
  }
  return MISSION;
}

int select_mission()
{  //this is mostly just a modified version of do_load() from mainmenu.cpp
  static bool first = true;
  static bool ok, canload, showmap;
  static int oldsel;
  static _button back, load, start, situation, preview;
  static string text;
  static _listbox files;
  bool missionok;
  unsigned int i;
  int x, y, a, b, c, d, sel;
  char p[30] = "";
  string name;
  
  if (first)
  {
    oldsel = -1;
    ok = true;
		showmap = false;
    ifstream missions("missions/missionlist.txt");
    if (missions.bad())
    {
      ok = false;
    }
    back.init(10, 455, 100, 20, "Back");
		start.init(530, 455, 100, 20, "Start Mission");
		situation.init(290, 55, 120, 20, "Situation & Orders");
		preview.init(420, 55, 100, 20, "Map Screen");
		files.init(50, 55, 200, 350);
		
    if (ok)
    {
      i = 0;
      while (!missions.eof())
      {
        getline(missions, text);
        if (!(text == ""))
        {  // add the line to the mission list as long as it isn't blank
          files.additem(text.c_str());
        }
        i++;
      }
    }
		else
		{
			files.additem("Unable to load 'missionlist.txt'");
		}
    canload = false;
    if (exists("missions/mission.sav"))
    {
      load.init(235, 455, 170, 20, "Continue Previous Mission");
      canload = true;
    }
    first = false;
  }
  
  glb.draw(10, 0, 0);
  buffer_textout_centre_ex(big, "SELECT THE MISSION", 320, 420, BLACK);
  files.check();

  back.check();
  if (back.clicked())
  {
    first = true;
    return MISSION_EXIT;
  }
  
	if (ok)
	{
		sel = files.getsel();
		if (sel != -1)
		{
      if (sel != oldsel)
      {
				showmap = false;
				oldsel = sel;
        sprintf(p, "missions/mission%-1d.dat", sel);
        ifstream m(p);
        missionok = true;
        text = "";
        if (m.bad())
        {
          missionok = false;
          m.close();
        }
        if (missionok)
        {
          getline(m, text);  //this is just "-DESCRIPTION-"
          getline(m, text);  //this is the actual description
          m.close();
        }
      }
      
      buffer_rectfill(291, 81, 614, 359, BLACK, 0.65);
      buffer_rect(290, 80, 615, 360, VDGREY);
      buffer_textout_ex(big, files.selected(), 300, 90, WHITE);
      
			sprintf(p, "missions/completed%d", sel);
			if (exists(p))
			{
				buffer_textout_ex(normal, "Complete", 300, 130, GREEN);
			}
			
			if (showmap)
			{
      	sprintf(p, "missions/mission%-1d.map", sel);
      	draw_minimap(340, 150, p);
			}
			else
			{
				multiline_textout_ex(normal, text, 300, 150, 303, WHITE);
			}
			
			start.check();
			situation.check();
			preview.check();
			
			if (situation.clicked())
			{
				showmap = false;
			}
			if (preview.clicked())
			{
				showmap = true;
			}

      if (start.clicked())
      {
        sprintf(p, "missions/mission%-1d.map", sel);
        missionok = true;
        ifstream m(p);
        if (m.bad())
        {
          missionok = false;
        }
        sprintf(p, "missions/mission%-1d.dat", sel);
        ifstream dat(p);
        if (dat.bad())
        {
          missionok = false;
        }
        dat.close();
        if (missionok)
        {
          mis.mission_number = sel;
          worldmap.reset();
          player[0].reset();  //get rid of any previous unit settings
          player[1].reset();
          player[2].reset();
          player[3].reset();
          sprintf(p, "mission%-1d", sel);
          worldmap.set_name(p);
          m >> worldmap.l >> worldmap.h >> numplayers;
          x = 0;
          while (x < numplayers)
          {  //initialize all players participating in this game
            player[x].playing = 1;
            player[x].everplaying = 1;
            player[x].cash = 0;
            player[x].power = 0;
            x++;
          }

          y = 0;
          while (y < worldmap.h)
          {
            x = 0;
            while (x < worldmap.l)
            {
              m >> a;
              worldmap.tile[x][y].change_type(a / 100, a % 100);
              x++;
            }
            y++;
          }
          x = 0;
          while (x < 50 * numplayers)  //loading any placed units
          {
            m >> a;
            if (a != -1)  //if there is a saved unit for this i
            {
              m >> b >> c >> d;
              player[d].create_unit(c, a, b, d);
            }
            else  //if a is -1, there are no more saved units
            {
              x = 50 * numplayers;
            }
            x++;
          }
            
          load_missiondata();
          x = 0;
          while (x < numplayers)
          {
            if (x < mis.first_opponent)
            {
              player[x].team = 0;
            }
            else
            {
              player[x].team = 1;
            }
            x++;
          }

          name = worldmap.get_name();
          sprintf(p, "missions/mission%-1d.ai", mis.mission_number);
          load_ai_from_file(p);

          first = true;
          get_connected_beaches();
					get_teleports();
          minimap.create();
          global.loaded_game = 0;
          global.very_first_turn = 1;
          return MISSION_SELECTPLAYER;
        }
      }
    }
  }
  
  if (canload)
  {
    load.check();
    if (load.clicked())
    {
      load_mission("missions/mission.sav");
      first = true;
      get_connected_beaches();
			get_teleports();
      minimap.create();
      global.loaded_game = 1;
      global.very_first_turn = 1;
      return MISSION_INPROGRESS;
    }
  }
  if (key[KEY_Z])
  {
    if (exists("missions/missiondebug.sav"))
    {
      load_mission("missions/missiondebug.sav");
      first = true;
      get_connected_beaches();
			get_teleports();
      minimap.create();
      global.loaded_game = 1;
      global.very_first_turn = 1;
      return MISSION_INPROGRESS;
    }
  }

  draw_mouse();
  
  return MISSION_SELECT;
}

int do_mission()
{
  static int t;
  int a, b;
  char c[20];
  
  if (global.very_first_turn == 1)
  {
    var.logicstate = NOTHING_HAPPENING;
    var.first = true;
    global.very_first_turn = 0;
  }
  if (var.first)
  {  //if it's a new turn
    init_logic();
    if (global.loaded_game != 1)
    {  //make sure daysleft doesn't decrement just because the game was loaded
      player[pturn].tookturn++;
    }

    if (player[pturn].tookturn > 1)  //the player has taken a second turn
    {  //that means a day has passed
      mis.daysleft--;
      a = 0;
      while (a < 4)
      {
        if (player[a].playing == 1)
        {
          player[a].tookturn = 0;  //reset all tookturn variables
        }
        a++;
      }
      player[pturn].tookturn = 1;
    }
    debug_mission();  //save the game to debug later if the game crashes
    var.first = false;
  }
  
  
  if ((var.logicstate == NOTHING_HAPPENING) || (var.logicstate == AI_TURN))
  {  //if nothing's going on, or it's a normal AI turn
    a = 0;
    while (a < 4)
    {  //check each player to see if they are not beaten
      if (player[a].playing == 1)
      {
        if (player[a].defeated(a))
        {  //if they are defeated, but still on the map
          player[a].playing = 0;
          transform_buildings(a, -1);
          if (a == pturn)
          {  //if the player was defeated on his own turn
            pturn++;  //it is the next person's turn
            while (player[pturn].playing != 1)
            {
              pturn++;
              if (pturn >= 4) pturn = 0;
            }
          }
          var.logicstate = PLAYER_DEFEATED;
          var.theplayer = a;
        }
      }
      a++;
    }
  }
  
	if (var.logicstate != IN_OPTIONS_MENU)
	{
    worldmap.draw_tiles();
	}
  
  if (gameoptions.time != -999)
  {  //if there is a time limit
    if ((var.logicstate != TIME_UP_INDICATOR) && (var.logicstate != AI_TURN) && (var.logicstate != AI_POWER_ANIMATION))
    {
      if (mouse_y < 240)
      {
        b = 468;
      }
      else
      {
        b = 0;
      }
      
      sprintf(c, "Time Left: %-1ds", var.time / 50);
      buffer_rectfill(318 - text_length(font, c) / 2, b, text_length(font, c) + 4, 12, DGREY, 0.75);
      buffer_textout_centre_ex(normal, c, 320, b, WHITE);
      if (var.time < 1)
      {
        pturn++;
        while (player[pturn].playing != 1)
        {
          pturn++;
          if (pturn >= 4) pturn = 0;
        }
        var.logicstate = TIME_UP_INDICATOR;
      }
    }
  }
  else
  {
    var.time = 0;  //if it's not being used, just keep it at 0 for simplicity
  }
  if (mis.modeflag & MODE_TIMED)
  {
    a = 0;
    if (gameoptions.time != -999)
    {
      a = 12;
    }
    if (mouse_y < 240)
    {
      b = 468 - a;
    }
    else
    {
      b = a;
    }
    
    sprintf(c, "%-1d Days Left", mis.daysleft);
    buffer_rectrounded(280, b, 360, b + 12, DGREY, 0.75);
    buffer_textout_centre_ex(normal, c, 320, b, WHITE);
  }

  if (var.logicstate == NOTHING_HAPPENING)
  {
    if (check_explodes())
    {
      var.logicstate = EXPLODING;
    }
  }

	if (var.logicstate != IN_OPTIONS_MENU)
	{
    do_particles();
	}
  
  switch(var.logicstate)
  {
    case AI_TURN:
      a = check_conditions();
      if (a == 1)  //victory
      {
        var.first = 1;
        global.very_first_turn = 1;
        play_song(title_music);
//        draw_all(transition);
        return MISSION_COMPLETED;
      }
      else if (a == 2)  //defeat
      {
        var.first = 1;
        global.very_first_turn = 1;
        play_song(title_music);
//        draw_all(transition);
        return MISSION_FAILED;
      }
      ai();
      break;
    case AI_POWER_ANIMATION:
      ai_powerflash();
      break;
    case NOTHING_HAPPENING:
      a = check_conditions();
      if (a == 1)  //victory
      {
        var.first = 1;
        global.very_first_turn = 1;
        play_song(title_music);
//        draw_all(transition);
        return MISSION_COMPLETED;
      }
      else if (a == 2)  //defeat
      {
        var.first = 1;
        global.very_first_turn = 1;
        play_song(title_music);
//        draw_all(transition);
        return MISSION_FAILED;
      }
      var.time--;
      nothing_happening();
      minimap.check();
      draw_mouse();
      break;
    case IN_BATTLE:
      battle();
      break;
    case UNIT_SELECTED:
      var.time--;
      unit_selected();
      draw_mouse();
      break;
    case UNIT_MOVING:
      unit_moving();
      draw_mouse();
      break;
    case UNIT_ATTACKING:
      var.time--;
      unit_attacking();
      draw_mouse();
      break;
    case UNIT_UNLOADING:
      var.time--;
      unit_unloading();
      draw_mouse();
      break;
    case UNIT_TELEPORTING:
      unit_teleporting();
      draw_mouse();
      break;
    case SAVING_GAME:
      save_mission();
      draw_mouse();
      break;
    case AI_MENU:
      ai_menu();
      draw_mouse();
      break;
    case IN_GENERAL_MENU:
      general_menu();
      draw_mouse();
      break;
    case IN_ACTION_MENU:
      action_menu();
      draw_mouse();
      break;
    case IN_UNIT_BUILD_MENU:
      var.time--;
      build_menu();
      draw_mouse();
      break;
    case POWER_ANIMATION:
      powerflash();
      break;
		case IN_OPTIONS_MENU:
      if (do_gameoptions(true) == 0)
      {
        var.logicstate = IN_GENERAL_MENU;
      }
      break;
    case SCROLLING:
      scroll_to_hq(pturn);
      break;
    case ONE_TEAM_LEFT:
      do_particles();
      windelay();
		  stop_music();
//      clear_to_color(transition, BLACK);  //for the transition to the winner screen
//      draw_all(transition);  //this draw_all() was explained in mainmenu.cpp
//      buffer_blit(transition, 0, 0, 0, 0, 640, 480);
      break;
    case WINNER:
      break;
    case BACK_TO_MAIN_MENU:
      t = 0;
      var.logicstate = FADE_EXIT;
      break;
    case FADE_EXIT:
      if (t < 24)
      {
        buffer_rectfill(0, 0, 640, 480, BLACK, float(t * 10) / 255.0);
        t++;
      }
      else
      {
        buffer_clear_to_color(BLACK);
        player[0].reset();
        player[1].reset();
        player[2].reset();
        player[3].reset();
        var.first = 1;
        global.very_first_turn = 1;
        play_song(title_music);
        return MISSION_EXIT;
      }
      break;
    case TIME_UP_INDICATOR:
      time_up();
      break;
    case EXPLODING:
      if (do_explodes() == 1)
      {  //if the explosion has finished
        var.logicstate = NOTHING_HAPPENING;
      }
      break;
    case PLAYER_DEFEATED:
      destroy_theplayers_units();
      break;
  }
  return MISSION_INPROGRESS;
}

void save_mission()
{
  static bool first = true;
  static _button ok, cancel;
  static bool ask, saved;
  
  if (first)
  {
    ok.init(215, 215, 100, 20, "Save");
    cancel.init(325, 215, 100, 20, "Cancel");
    saved = false;
    if (exists("missions/mission.sav") != 0)
    {
      ask = true;
    }
    else
    {
      ask = false;
    }
    first = false;
  }
  
  buffer_rect(200, 185, 440, 245, DGREY);
  buffer_rect(199, 184, 441, 246, GREY);
  buffer_rect(198, 183, 442, 247, DGREY);
  buffer_rectfill(201, 186, 439, 244, GREY);
  
  if (ask)
  {
    buffer_textout_centre_ex(normal, "Overwrite previous save?", 320, 195, BLACK);
    ok.check();
    cancel.check();
    if (ok.clicked())
    {
      ask = false;
    }
    if (cancel.clicked())
    {
      first = true;
      var.logicstate = NOTHING_HAPPENING;
    }
  }
  else if (!saved)
  {
    save_mission_to_file("missions/mission.sav", "Mission");
    ok.init(215, 215, 210, 20, "OK");
    saved = true;
  }
  else
  {
    buffer_textout_centre_ex(normal, "Mission saved", 320, 195, BLACK);
    ok.check();
    if (ok.clicked())
    {
      first = true;
      var.logicstate = NOTHING_HAPPENING;
    }
  }
}

void debug_mission()
{
  save_mission_to_file("missions/missiondebug.sav", "Debuggery");
}

void save_mission_to_file(string thepath, string thename)
{
  ofstream savefile(thepath.c_str());
  if (!(savefile.bad()))
  {
    savefile << thename.c_str() << "\n" << worldmap.l << "\n" << worldmap.h << "\n";

		save_map_and_players(&savefile);
		
    savefile << "pturn " << pturn << "\n" << mis.mission_number << "\n" << gameoptions.funding << "\n";
    savefile << numplayers << "\n" << gameoptions.show_damage << "\n" << gameoptions.time << "\n";
    savefile << var.time << "\n" << mis.conquerx << "\n" << mis.conquery << "\n";
    savefile << mis.daysleft << "\n" << mis.defendx << "\n" << mis.defendy << "\n";
    savefile << mis.first_opponent << "\n" << mis.modeflag << "\n";
		
		save_currentcharacters(thepath.c_str());
  }
  savefile.close();
}

int check_conditions()
{
  int i, j;
  bool condition;
  bool all_enemies_defeated = true;
  bool all_allies_defeated = true;
  
  i = mis.first_opponent;
  while ((i < numplayers) && (i < 4))
  {
    if (player[i].playing == 1)
    {
      all_enemies_defeated = false;
    }else empdebug("all enemies defeated");
    i++;
  }
  i = 0;
  while ((i < 4) && (i < mis.first_opponent))
  {
    if (player[i].playing == 1)
    {
      all_allies_defeated = false;
    }
    i++;
  }
  
  //check for defeat conditions first
  if (all_allies_defeated)
  {  //no matter what mode, if all there aren't any good guys left, you lose
    return 2;
  }
  if ((mis.modeflag & MODE_TIMED) && (mis.daysleft <= 0))
  {  //if the mission had a limited number of days and it's now finished
    if (mis.modeflag & (MODE_STANDARD | MODE_CONQUER | MODE_KILL))
    {  //if it was a standard, conquer, or kill mission, you lose
      return 2;
    }
  }
  if (mis.modeflag & MODE_PROTECT)
  {
    j = 0;
    while (j < mis.first_opponent)
    {
      i = 0;
      while (i < 50)
      {
        if ((player[j].unit[i].exists == 0) && (player[j].unit[i].missioncritical == 1))
        {  //if there was a mission-critical unit that's been destroyed
          return 2;  //you lose
        }
        i++;
      }
      j++;
    }
  }
  if (mis.modeflag & MODE_DEFEND)
  {
    i = mis.first_opponent;
    while ((i < numplayers) && (i < 4))
    {
      if (worldmap.tile[mis.defendx][mis.defendy].owned_by(i))
      {  //if the tile to defend is owned by an enemy
        return 2;  //you lose
      }
      i++;
    }
  }

  if ((mis.modeflag & MODE_TIMED) && (mis.daysleft <= 0))
  {  //if the mission had a limited number of days and it's now finished
    if (mis.modeflag & (MODE_SURVIVAL | MODE_PROTECT | MODE_DEFEND))
    {  //if the goal was to survive or protect something
      return 1;  //time up means you win
    }
  }
  if ((mis.modeflag & ~MODE_CONQUER) && (all_enemies_defeated))
  {  //if the mission objective was anything but "capture a tile" and all enemy units are defeated
    return 1;  //you win
  }
  if (mis.modeflag & MODE_CONQUER)
  {
    i = 0;
    while (i < mis.first_opponent)
    {
      if (worldmap.tile[mis.conquerx][mis.conquery].owned_by(i))
      {  //if the tile to capture is owned by you or an ally
        return 1;  //you win
      }
      i++;
    }
  }
  if (mis.modeflag & MODE_KILL)
  {
    condition = true;
    j = mis.first_opponent;
    while (j < numplayers)
    {
      i = 0;
      while (i < 50)
      {
        if ((player[j].unit[i].exists == 1) && (player[j].unit[i].missioncritical == 1))
        {  //if a unit that must be destroyed still exists
          condition = false;
          i = 50;
          j = numplayers;
        }
        i++;
      }
      j++;
    }
    if (condition)
    {  //if there aren't any enemy mission-critical units left
      return 1;  //you win
    }
  }
  
  return 0;
}

void load_missiondata()
{
  char ch[20];
  char p[30];
  int i, n, z, protect, kill;
  vector<int> opp;
  string str;
  sprintf(p, "missions/mission%-1d.dat", mis.mission_number);  //already made sure this file exists
  ifstream dat(p);
  getline(dat, str);  //"-DESCRIPTION-"
  getline(dat, str);  //the description
  gameoptions.show_damage = true;
  gameoptions.time = -999;
	gameoptions.funding = 1000;
  mis.daysleft = -1;
  mis.conquerx = -1;
  mis.conquery = -1;
  mis.modeflag = 2;
  mis.defendx = -1;
  mis.defendy = -1;
  while (!dat.eof())
  {
    dat >> ch;
    if (strcmp(ch, "-MODE-") == 0)
    {
      dat >> mis.modeflag;
    }
    else if (strcmp(ch, "-DAYS-") == 0)
    {
      dat >> mis.daysleft;
    }
    else if (strcmp(ch, "-DEFEND-") == 0)
    {
      dat >> mis.defendx >> mis.defendy;
    }
    else if (strcmp(ch, "-PROTECT-") == 0)
    {
      dat >> protect;
      while (protect != -1)
      {
        player[protect / 100].unit[protect % 100].missioncritical = 1;
        dat >> protect;
      }
    }
    else if (strcmp(ch, "-KILL-") == 0)
    {
      dat >> kill;
      while (kill != -1)
      {
        player[kill / 100].unit[kill % 100].missioncritical = 1;
        dat >> kill;
      }
    }
    else if (strcmp(ch, "-CONQUER-") == 0)
    {
      dat >> mis.conquerx >> mis.conquery;
    }
    else if (strcmp(ch, "-OPPONENTS-") == 0)
    {
      opp.clear();
      z = 0;
      while (z != -1)
      {
        dat >> z;
        if (z != -1)
        {
          opp.push_back(z);
        }  //finds number of opponents
      }
      n = 0;
      mis.first_opponent = numplayers - opp.size();
      i = mis.first_opponent;
      while (i < numplayers)
      {
        player[i].number = first_mission_character + opp[n];
        player[i].controller = AI;
        n++;
        i++;
      }  //this way there can be two or three human-controlled against one or two mission opponents
    }
    else if (strcmp(ch, "-FUNDS-") == 0)
    {
      dat >> gameoptions.funding;
    }
    else if (strcmp(ch, "-STARTINGCASH-") == 0)
    {
      i = 0;
      while (i < numplayers)
      {
        dat >> player[i].cash;
        i++;
      }
    }
    else if (strcmp(ch, "-TIME-") == 0)
    {
      dat >> gameoptions.time;
    }
  }
  dat.close();
}

int select_missionplayers()
{
  static bool first = true;
  static int delay;
  static _button pbutton[4], back, ok;
  int i, j;
  
  if (first)
  {
    delay = 30;
    i = 0;
    while (i < numplayers)
    {
      if (i < mis.first_opponent)
      {
        j = i;
        while (j >= first_mission_character) j -= first_mission_character;  //in case playable characters < numplayers
        pbutton[i].init(50 + (100 * i), 55, 80, 80, "", character[j]->picture);
        player[i].number = j;
				currentcharacter[i] = character[j];
      }
      else
      {
        currentcharacter[i] = character[player[i].number];
				pbutton[i].init(480 - (100 * i), 230, 80, 80, "", currentcharacter[i]->picture);
        pbutton[i].clickable = false;
      }
      i++;
    }
    back.init(10, 455, 100, 20, "Back");
    ok.init(530, 455, 100, 20, "Start");
    first = false;
  }
  
  glb.draw(20, 0, 0);
  
  i = 0;
  while (i < numplayers)
  {
    buffer_rect(pbutton[i].x - 1, pbutton[i].y - 1, pbutton[i].x + 80, pbutton[i].y + 80, DGREY);
    pbutton[i].check();
    if (pbutton[i].mouseover())
    {
      description(player[i].number, 320, 380);
    }
    if (i < mis.first_opponent)
    {
      if ((pbutton[i].clicked()) && (delay == 0))
      {
        player[i].number++;
        if (player[i].number >= first_mission_character)
        {
          player[i].number = 0;
        }
        pbutton[i].init(50 + (100 * i), 55, 80, 80, "", currentcharacter[i]->picture);
      }
    }
    i++;
  }
  back.check();
  ok.check();
  draw_mouse();
  
  if (delay > 0)
  {
    delay--;
  }
  
  if (back.clicked())
  {
    first = true;
    return MISSION_SELECT;
  }
  if (ok.clicked())
  {
    first = true;
    return MISSION_INPROGRESS;
  }
  
  return MISSION_SELECTPLAYER;
}

void load_mission(string path)
{
  int o, p, num, safety;
  int type, tilex, tiley, ammo, gas, ready, capturing, submerged, missioncritical, unum;
  float health;
  int temp;
  char d[30];

  ifstream savefile(path.c_str());
  if (!(savefile.bad()))
  {
    worldmap.reset();
    savefile >> d >> worldmap.l >> worldmap.h;
    o = 0;
    while (o < worldmap.h)
    {
      p = 0;
      while (p < worldmap.l)
      {
        savefile >> temp;
        worldmap.tile[p][o].change_type(temp / 100, temp % 100);
        p++;
      }
      o++;
    }
    safety = 0;
    o = 0;
    while (o < 4)
    {
      player[o].clear_units();
      savefile >> d >> player[o].playing;
      savefile >> d >> player[o].everplaying;
      if (player[o].everplaying == 1)
      {
				
				
        savefile >> d >> player[o].number;
        savefile >> d >> player[o].cash;
        savefile >> d >> player[o].power;
        savefile >> d >> player[o].controller;
        savefile >> d >> player[o].powered;
        savefile >> d >> unum;
        savefile >> d >> player[o].team;
        savefile >> d >> player[o].tookturn;
        p = 0;
        while (p < unum)
        {
          savefile >> d >> type;
          savefile >> d >> tilex;
          savefile >> d >> tiley;
          savefile >> d >> health;
          savefile >> d >> ammo;
          savefile >> d >> gas;
          savefile >> d >> ready;
          savefile >> d >> capturing;
          savefile >> d >> submerged;
          savefile >> d >> missioncritical;
          num = player[o].create_unit(type, tilex, tiley, o);
          player[o].unit[num].health = health;
          player[o].unit[num].ammo = ammo;
          player[o].unit[num].gas = gas;
          player[o].unit[num].ready = ready;
          player[o].unit[num].capturing = capturing;
          player[o].unit[num].submerged = submerged;
          player[o].unit[num].missioncritical = missioncritical;
          savefile >> d >> player[o].unit[num].load[0].loaded;
          savefile >> d >> player[o].unit[num].load[0].type;
          savefile >> d >> player[o].unit[num].load[0].health;
          savefile >> d >> player[o].unit[num].load[0].ammo;
          savefile >> d >> player[o].unit[num].load[0].gas;
          savefile >> d >> player[o].unit[num].load[0].subload.loaded;
          savefile >> d >> player[o].unit[num].load[0].subload.type;
          savefile >> d >> player[o].unit[num].load[0].subload.health;
          savefile >> d >> player[o].unit[num].load[0].subload.ammo;
          savefile >> d >> player[o].unit[num].load[0].subload.gas;
          savefile >> d >> player[o].unit[num].load[1].loaded;
          savefile >> d >> player[o].unit[num].load[1].type;
          savefile >> d >> player[o].unit[num].load[1].health;
          savefile >> d >> player[o].unit[num].load[1].ammo;
          savefile >> d >> player[o].unit[num].load[1].gas;
          savefile >> d >> player[o].unit[num].load[1].subload.loaded;
          savefile >> d >> player[o].unit[num].load[1].subload.type;
          savefile >> d >> player[o].unit[num].load[1].subload.health;
          savefile >> d >> player[o].unit[num].load[1].subload.ammo;
          savefile >> d >> player[o].unit[num].load[1].subload.gas;
          p++;
        }
      }
      o++;
    }
    savefile >> d >> pturn >> mis.mission_number;
		load_missiondata();
		savefile >> gameoptions.funding >> numplayers;
    savefile >> gameoptions.show_damage >> gameoptions.time >> loaded_time;
    savefile >> mis.conquerx >> mis.conquery >> mis.daysleft >> mis.defendx;
    savefile >> mis.defendy >> mis.first_opponent >> mis.modeflag;
    worldmap.set_name("mission");
  }
}

int victory()
{
  static int time = 0;
  static int delay = 0;
  static int current = -1;
	char filename[40];
  int 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);
    time++;
  }
  else if (time < 128)
  {  //fade to black
    t = 128 - time;
    buffer_clear_to_color(makecol(t, t, t));
    time++;
  }
  else if (time < 168)
  {  //pause for a bit
    time++;
  }
  else
  {
    if (time == 168)
    {
      play_sound(S_VICTORY);
    }
    else
    {
      time--;  //just to keep time from increasing any more
    }
    buffer_textout_centre_ex(big, "Victory!", 320, 200, WHITE);
    buffer_textout_centre_ex(normal, "Press Enter", 320, 400, WHITE);
    time++;
  }
  if (key[KEY_ENTER])
  {
    position_mouse(320, 240);
    time = 0;
    player[0].reset();
    player[1].reset();
    player[2].reset();
    player[3].reset();
		
		//mark the mission as completed
		sprintf(filename, "missions/completed%d", mis.mission_number);
		ofstream completion(filename);
		completion.close();
		
//    clear_to_color(transition, BLACK);
    return MISSION_EXIT;
  }
  return MISSION_COMPLETED;
}

int defeat()
{
  static int time = 0;
  static int delay = 0;
  static int current = -1;
  int 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);
    time++;
  }
  else if (time < 128)
  {  //fade to black
    t = 128 - time;
    buffer_clear_to_color(makecol(t, t, t));
    time++;
  }
  else if (time < 168)
  {  //pause for a bit
    time++;
  }
  else
  {
    if (time == 168)
    {
      play_sound(S_DEFEAT);
    }
    else
    {
      time--;  //just to keep time from increasing any more
    }
    buffer_textout_centre_ex(big, "Defeat", 320, 200, GREY);
    buffer_textout_centre_ex(normal, "Press Enter", 320, 400, WHITE);
    time++;
  }
  if (key[KEY_ENTER])
  {
    position_mouse(320, 240);
    time = 0;
    player[0].reset();
    player[1].reset();
    player[2].reset();
    player[3].reset();
//    clear_to_color(transition, BLACK);
    return MISSION_EXIT;
  }
  return MISSION_FAILED;
}
