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

extern bool ai_unit_animating;

int pturn;
vector<int> movelist;
vector<_unitexplosion> boom;

int logic()
{
  static int t;
  int temp1;
  char c[20];
  if (global.very_first_turn == 1)
  {
    var.logicstate = NOTHING_HAPPENING;
    var.first = true;
    global.very_first_turn = 0;
  }
  if (var.first == true)
  {  //if it's a new turn
    init_logic();
    debug_savegame();  //save the game to debug later if the game crashes
    var.first = false;
  }
  
  if ((var.logicstate == NOTHING_HAPPENING) || ((var.logicstate == AI_TURN) && (!ai_unit_animating)))
  {  //if nothing's going on, or it's a normal AI turn
    temp1 = 0;
    while (temp1 < 4)
    {  //check each player to see if they are not beaten
      if (player[temp1].playing == 1)
      {
        if (player[temp1].defeated(temp1))
        {  //if they are defeated, but still on the map
          player[temp1].playing = 0;
          transform_buildings(temp1, -1);
          if (temp1 == 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 = temp1;
        }
      }
      temp1++;
    }
  }
  if (var.logicstate == NOTHING_HAPPENING)
  {
    if (one_team_left())
    {
      var.logicstate = ONE_TEAM_LEFT;
      var.windelay = 20;
    }
  }
  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) && (var.logicstate != IN_OPTIONS_MENU))
    {
      if (mouse_y < 240)
      {
        temp1 = 468;
      }
      else
      {
        temp1 = 0;
      }
      
      sprintf(c, "Time Left: %-1ds", var.time / 50);
      buffer_rectfill(318 - text_length(font, c) / 2, temp1, text_length(font, c) + 4, 12, DGREY, 0.75);
      buffer_textout_centre_ex(normal, c, 320, temp1, 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 (var.logicstate == NOTHING_HAPPENING)
  {
    if (check_explodes())
    {
      var.logicstate = EXPLODING;
    }
  }

  if (var.logicstate != IN_OPTIONS_MENU)
  {
    do_particles();
  }
  switch(var.logicstate)
  {
    case AI_TURN:
      ai();
      break;
    case AI_POWER_ANIMATION:
      ai_powerflash();
      break;
    case NOTHING_HAPPENING:
      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_game();
      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 IN_OPTIONS_MENU:
      if (do_gameoptions(true) == 0)
      {
        var.logicstate = IN_GENERAL_MENU;
      }
      break;
    case POWER_ANIMATION:
      powerflash();
      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:
      var.first = 1;
      return GAMEOVER;
    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 MENU;
      }
      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 LOGIC;
}

bool one_team_left()
{
  int temp1 = 0;
  int temp2 = -1;
  while (temp1 < 4)
  {  //this loop sees if there's more than one team left in the game
    if (player[temp1].playing == 1)
    {
      if (temp2 > -1)
      {
        if (player[temp1].team != temp2)
        {
          return false;  //found a different team
        }
      }
      else
      {  //the team of the first player in the game
        if (temp2 == -1)
        {
          temp2 = player[temp1].team;
        }
      }
    }
    temp1++;
  }
  return true;
}


void time_up()
{
  static bool first = true;
  static int t;
  if (first)
  {
    t = 50;
    first = false;
    play_sound(S_TANKFIRE);
  }
  buffer_textout_centre_ex(big, "TIME UP", 320, 200, BLACK);
  t--;
  if (t < 0)
  {
    var.first = true;
    var.logicstate = NOTHING_HAPPENING;
    first = true;
  }
}

void ai_menu()
{
  static bool first = true;
  static _button items[2];
  if (first)
  {
    items[0].init(502, 2, 135, 28, "Quit to Menu");
    items[1].init(502, 32, 135, 28, "Cancel");
    position_mouse(570, 45);
    set_mouse_range(500, 0, 639, 61);
    first = false;
  }
  
  buffer_menuback(500, 0, 639, 63, GREY, GREY, LGREY, 0.8);
  items[0].check();
  items[1].check();
  if (items[0].clicked())
  {
    first = true;
    do_ai(pturn, true);  //this resets the static ints in do_ai()
    var.logicstate = BACK_TO_MAIN_MENU;
    set_mouse_range(0, 0, 639, 479);
  }
  if (items[1].clicked())
  {
    first = true;
    var.logicstate = AI_TURN;
    set_mouse_range(0, 0, 639, 479);
  }
}


void init_logic()
{
  int z;
  char songpath[20];

  sprintf(songpath, "data/player%-1d.m", player[pturn].number + 1);
  play_song(songpath);

  var.unloadstatus = 0;
  var.unloadnum = 0;
  var.cancel_attack = false;
  var.cancel_unload = false;
  var.cancel_teleport = false;
  var.movedthisturn = 0;
  if (!((player[pturn].controller == AI) && (player[pturn].units_in_play() > 0)))
  {  //if the player is human or an AI with no units, scroll to the HQ
    var.logicstate = SCROLLING;  //sets it to scroll to the current player's HQ
    worldmap.draw_tiles();
  }
  check_scrolling(worldmap.scroll_x, worldmap.scroll_y);  //if I don't do this, the static floats
  var.first = false;                                      //in check_scrolling aren't the right
  z = 0;                                                  //ones and bad things happen
  while (z < 4)
  {
    if (player[z].playing == 1)
    {
      if (global.loaded_game == 0)  //if the game has just been loaded from a
      {                             //file, the units should not be refreshed
        player[z].ready_units();
      }
    }
    z++;
  }
  if (gameoptions.time != -999)
  {
    var.time = gameoptions.time;
  }
  boom.resize(0);  //remove all explosions from existence
  p_effects.resize(0);  //same for particles
  if (global.loaded_game == 0)  //likewise, the player does not receive more cash
  {                             //and units are not repaired when the game is loaded
    player[pturn].cash += buildings_owned(pturn) * gameoptions.funding;
    if (player[pturn].cash > 1000000) player[pturn].cash = 1000000;
    player[pturn].powered = 0;  //if the player was powered last turn, dispel it now
    repair_units(pturn);
    decrease_gas(pturn);
  }
  if (global.loaded_game == 1)  //next turn, it won't matter whether the game
  {                             //was originally loaded from a file or not
    var.time = loaded_time;
    global.loaded_game = 0;
  }
  position_mouse(320, 240);
}

void battle()
{
  int pa = var.attacker / 100;
  int ua = var.attacker % 100;
  int pd = var.defender / 100;
  int ud = var.defender % 100;
  int battle = do_battle(&player[pa].unit[ua], &player[pd].unit[ud]);
  if (battle == 0)  //if the battle just ended
  {
    var.logicstate = NOTHING_HAPPENING;
  }
}

void windelay()
{
  if (var.windelay <= 0)
  {
    var.logicstate = WINNER;
  }
  else
  {
    var.windelay--;
  }
}

void powerflash()
{
  if (do_powerflash(pturn) == -1)
  {  //if the animation has just ended
    var.logicstate = NOTHING_HAPPENING;
  }
}

void ai_powerflash()
{
  if (do_powerflash(pturn) == -1)
  {
    var.logicstate = AI_TURN;
  }
}

void save_game()
{
  if (do_savemenu() == 0)
  {  //if the savemenu has just closed
    var.logicstate = NOTHING_HAPPENING;
  }
}

void ai()
{
  bool can_rightclick = true;
  int temp1 = do_ai(pturn);
  int indicator = temp1 / 10;  //if the AI uses its power, it indicates that in temp1's tens column
  if (indicator == 1)  //signals that the AI has just used its special power
  {
    var.logicstate = AI_POWER_ANIMATION;
    can_rightclick = false;
  }
  else if (indicator == 2)  //signals that the AI is in a battle or scroll animation
  {
    can_rightclick = false;  //no bringing up the menu in a battle animation!
  }
  else if (indicator == 3)  //signals that there's an explosion about to happen
  {
    var.logicstate = EXPLODING;
    can_rightclick = false;
  }
    
  if ((can_rightclick) && (mouse_rclicked() == 1))
  {
      var.logicstate = AI_MENU;
  }
  
  temp1 %= 10;  //ignore the indicator information and just get a 1 or 0
  if (temp1 == 1)  //if do_ai() has indicated that it is finished
  {
    var.logicstate = NOTHING_HAPPENING;
    pturn++;  //switch to the next player
    while (player[pturn].playing != 1)
    {
      pturn++;
      if (pturn >= 4) pturn = 0;
    }
    var.first = 1;
  }
}

void nothing_happening()
{
  int t, tx, ty, mx, my;
  _unit *u;
  draw_playerstats(pturn);
  mx = mouse_x;
  my = mouse_y;
  check_scrolling();
  if (mx >= worldmap.offset_x)
  {
    tx = worldmap.scroll_x + (mx - worldmap.offset_x) / MAP_TILE_SIZE;
  }
  else
  {
    tx = worldmap.scroll_x - 1 + (mx - worldmap.offset_x) / MAP_TILE_SIZE;
  }
  if (my >= worldmap.offset_y)
  {
    ty = worldmap.scroll_y + (my - worldmap.offset_y) / MAP_TILE_SIZE;
  }
  else
  {
    ty = worldmap.scroll_y - 1 + (my - worldmap.offset_y) / MAP_TILE_SIZE;
  }
  t = worldmap.tile[tx][ty].unit_here();
  if (player[pturn].controller == AI)
  {  //if the AI turn just started, set the logicstate accordingly
    var.logicstate = AI_TURN;
    return;
  }
  if (t != -1)
  {
    draw_unitstats(&player[t / 100].unit[t % 100]);
  }
  if (key[KEY_SPACE])
  {
    minimap.draw(false);
  }
  else if ((key[KEY_LSHIFT]) || (key[KEY_RSHIFT]))
  {  //draws a unit's attack range
    if (t != -1)
    {
      draw_attackrange(&player[t / 100].unit[t % 100]);
    }
  }
  else if (mouse_clicked() == 1)
  {
    if ((t != -1) && (t / 100 == pturn))
    {  //if one of the player's units is here
      u = &player[pturn].unit[t % 100];
      if (u->ready == 1)
      {  //if a unit is here and ready, select it
        var.unitselected = t % 100;
        var.oldux = u->tilex;
        var.olduy = u->tiley;
        var.oldcapstatus = u->capturing;
        var.unloadstatus = 0;
        var.movedthisturn = 0;
        worldmap.create_limited_pathmap(pturn, u->movetype, u->tilex, u->tiley, u->move + 1);
        var.logicstate = UNIT_SELECTED;
      }
    }
    else if (t == -1)
    {  //if there is no unit here, check for a building that can make units
      if (worldmap.tile[tx][ty].is_unit_producing())
      {
        if (worldmap.tile[tx][ty].owned_by(pturn))
        {
          var.unitmenu = worldmap.tile[tx][ty].building_type();
          var.logicstate = IN_UNIT_BUILD_MENU;
          var.unitx = tx;
          var.unity = ty;
          var.oldmx = mx;
          var.oldmy = my;
        }
      }
    }
  }
  else if ((mouse_rclicked() == 1) || (key[KEY_ESC]))
  {  //if the mouse is right-clicked, bring up the general menu
    var.oldmx = mx;  //save the mouse location to be put back after the menu closes
    var.oldmy = my;
    var.logicstate = IN_GENERAL_MENU;
  }
}

void build_menu()
{
  int t = do_unitmenu(var.unitmenu, var.unitx, var.unity, pturn);
  if (t == 1)  //do_unitmenu should return 1 when a unit has been
  {            //created or if the player cancels the unitmenu
    var.logicstate = NOTHING_HAPPENING;
  }
}

void general_menu()
{
  string s = do_generalmenu();
  if (s != "-")
  {
    if (s == "End Turn")
    {
      pturn++;
      while (player[pturn].playing != 1)
      {
        pturn++;
        if (pturn >= 4) pturn = 0;
      }
      var.first = true;
      var.logicstate = NOTHING_HAPPENING;
    }
    else if (s == "Power")
    {
      player[pturn].powered = 1;
      player[pturn].power = 0;
      do_power();
      var.logicstate = POWER_ANIMATION;
    }
    else if (s == "Quit to Menu")
    {
      pturn = 0;
      var.logicstate = BACK_TO_MAIN_MENU;
      position_mouse(var.oldmx, var.oldmy);
    }
    else if (s == "Options")
    {
      var.logicstate = IN_OPTIONS_MENU;
    }
    else if (s == "Save Game")
    {
      var.logicstate = SAVING_GAME;
    }
    else if (s == "Cancel")
    {
      var.logicstate = NOTHING_HAPPENING;
    }
    position_mouse(var.oldmx, var.oldmy);
  }
}

void unit_moving()
{
  _unit *u = &player[pturn].unit[var.unitselected];
  u->do_movement();
  u->draw();
  if (!u->is_moving())  //if the unit has just stopped moving
  {
    var.oldmx = mouse_x;
    var.oldmy = mouse_y;
    var.logicstate = IN_ACTION_MENU;
  }
}

void unit_selected()
{
  int mx = mouse_x;
  int my = mouse_y;
  int tx, ty, move;
  if (mx >= worldmap.offset_x)
  {
    tx = worldmap.scroll_x + (mx - worldmap.offset_x) / MAP_TILE_SIZE;
  }
  else
  {
    tx = worldmap.scroll_x - 1 + (mx - worldmap.offset_x) / MAP_TILE_SIZE;
  }
  if (my >= worldmap.offset_y)
  {
    ty = worldmap.scroll_y + (my - worldmap.offset_y) / MAP_TILE_SIZE;
  }
  else
  {
    ty = worldmap.scroll_y - 1 + (my - worldmap.offset_y) / MAP_TILE_SIZE;
  }
  int t;
  bool ok;
  _unit *u;
  do_moveselect(pturn, var.unitselected, tx, ty);
  check_scrolling();
  if (mouse_clicked() == 1)
  {
    u = &player[pturn].unit[var.unitselected];
    t = worldmap.tile[tx][ty].unit_here();
    ok = false;
    if ((t != -1) && (t / 100 == pturn))
    {  //if another of the player's units is here
      if (movelist.size() == 0)  //the unit hasn't moved at all, so the unit
      {                          //detected on the tile is just the selected unit
        ok = true;
      }
      else if (player[pturn].unit[t % 100].can_load_unit(u) == 1)
      {  //if a unit is here but can load the selected unit, everything's OK
        ok = true;
      }
      else if (player[pturn].unit[t % 100].type == u->type)
      {  //or if it is the same unit type and is damaged, they can merge
        if (can_merge(u, &player[pturn].unit[t % 100]))
        {
          ok = true;
        }
      }
    }
    else
    {  //there is no unit or an allied unit here, since you can't move onto enemy units
      move = u->move;
      if (move > u->gas)
      {
        move = u->gas;
      }
      if (worldmap.tile[tx][ty].get_step() <= move)
      {  //only have movement if the mouse is on a movable tile
        ok = true;
      }
      if (t != -1)
      {  //if there is an allied unit here
        ok = false;
      }
    }
    if (ok == true)
    {
      if (movelist.size() == 0)  //so do_actionmenu can tell if a unit has been ordered
      {                          //to move, which is important for ranged-attack units
        var.movedthisturn = 0;
      }
      else
      {
        var.movedthisturn = 1;
        u->capturing = -1;  //stops any capture process
        play_moving_sound(u->type);
      }
      u->set_moves(movelist);
      var.logicstate = UNIT_MOVING;
      do_moveselect(-1, -1, -1, -1);  //this resets do_moveselect's static ints
    }
  }
}

void action_menu()
{
  _unit *u = &player[pturn].unit[var.unitselected];
  _unit *temp;
  string s = do_actionmenu(u);
  int x = 0, y = 0;
  static int z = -2;
  if (z == -2)
  {
    z = unit_here_thorough(pturn, u->tilex, u->tiley, var.unitselected);
  }
  if (z != -1)
  {
    temp = &player[pturn].unit[z];
    worldmap.draw_tiles(temp->tilex - worldmap.scroll_x, temp->tiley - worldmap.scroll_y, 1, 1, temp);
  }
  if (s != "-")
  {
    u->ready = 0;
    if (s == "Attack")
    {
			u->ready = 1;  // So the unit isn't in the "unready" shade during the battle animation
      var.logicstate = UNIT_ATTACKING;  // The unit is then marked "unready" in battle.cpp
      mouse_type = MOUSE_TARGET;
    }
    else if (s == "Supply")
    {
      supply_units(u);
    }
    else if (s == "Capture")
    {
      capture_building(u);
    }
    else if (s == "Load")
    {
      player[pturn].unit[z].load_unit(u);
      worldmap.tile[u->tilex][u->tiley].set_unit(pturn, z);  //makes sure unitmap is
      u->exists = 0;                                         //correct for this spot
    }
    else if (s == "Unload")
    {
      var.logicstate = UNIT_UNLOADING;
    }
    else if (s == "Merge")
    {
      merge_units(u, u->tilex, u->tiley);
    }
    else if (s == "Dive")
    {
      u->submerged = 1;
    }
    else if (s == "Surface")
    {
      u->submerged = 0;
    }
    else if (s == "Teleport")
    {
      var.logicstate = UNIT_TELEPORTING;
    }
    else if (s == "Cancel")
    {
      u->ready = 1;
      if (z != -1)
      {
        x = u->tilex;
        y = u->tiley;
      }
      u->set_tiles(var.oldux, var.olduy);
      if (z != -1)
      {
        worldmap.tile[x][y].set_unit(pturn, z);  //if merge or load was canceled, restore unit value
      }
      u->capturing = var.oldcapstatus;
      var.movedthisturn = 0;
    }
    if (var.logicstate == IN_ACTION_MENU)
    {  //if the action does not bring up a new menu or anything
      var.logicstate = NOTHING_HAPPENING;  //go back to waiting for more input
    }
    position_mouse(var.oldmx, var.oldmy);
    z = -2;
  }
}

void unit_attacking()
{
  static bool first = true;
  static vector<_loc> attackables;
  _unit *u = &player[pturn].unit[var.unitselected];
  int tx, ty, z, temp1, temp2;
  int really_cancel;
  int mx = mouse_x;
  int my = mouse_y;
  int damage, dx, dy;
  char damagepercent[5];
  if (first == true)
  {
    attackables = find_attackables(u);
    first = false;
  }
  draw_attackables(attackables);
  check_scrolling();
  if (var.cancel_attack == false)
  {
    tx = (mx + 7 - worldmap.offset_x) / MAP_TILE_SIZE + worldmap.scroll_x;
    ty = (my + 7 - worldmap.offset_y) / MAP_TILE_SIZE + worldmap.scroll_y;
    if (gameoptions.show_damage)
    {
      z = attackable_unit_here(u, tx, ty, true);
      if (z != -1)
      {
        damage = int(total_damage(u, &player[z / 100].unit[z % 100]));
        sprintf(damagepercent, "%-1d%%", damage);
        dx = mx + 14 - worldmap.offset_x;
        dy = my + 14 - worldmap.offset_y;
        buffer_textout_ex(normal, damagepercent, dx, dy, WHITE);
//        buffer_rect(dx - 1, dy, dx + text_length(font, damagepercent), dy + 10, DGREY);
        buffer_rect(dx - 1, dy, dx + normal.Width(damagepercent), dy + 10, DGREY);
      }
    }
    if (mouse_rclicked() == 1)
    {
      var.cancel_attack = true;
    }
    if (mouse_clicked() == 1)
    {  //the (mx + 7) and (my + 7) are because the crosshair's center is 7 pixels away
      z = attackable_unit_here(u, tx, ty, true);
      if (z != -1)
      {
        first = true;
        var.logicstate = IN_BATTLE;
        var.attacker = (pturn * 100) + var.unitselected;
        var.defender = z;
        var.unitselected = -1;
        mouse_type = MOUSE_NORMAL;
      }
    }
  }
  else if (var.cancel_attack == true)
  {
    mouse_type = MOUSE_NORMAL;
    really_cancel = do_cancelattack_menu();
    if (really_cancel == 0)
    {  //if "Continue Attack" has been selected
      mouse_type = MOUSE_NORMAL;
      temp1 = (u->tilex - worldmap.scroll_x) * MAP_TILE_SIZE;
      temp2 = (u->tiley - worldmap.scroll_y) * MAP_TILE_SIZE;
      position_mouse(temp1 + MAP_TILE_SIZE / 2, temp2 + MAP_TILE_SIZE / 2);
      var.cancel_attack = false;
    }
    else if (really_cancel == 1)
    {  //if "Cancel Attack" has been selected
      temp1 = (u->tilex - worldmap.scroll_x) * MAP_TILE_SIZE;
      temp2 = (u->tiley - worldmap.scroll_y) * MAP_TILE_SIZE;
      u->ready = 1;
      u->set_tiles(var.oldux, var.olduy);
      position_mouse(temp1 + MAP_TILE_SIZE / 2, temp2 + MAP_TILE_SIZE / 2);
      var.cancel_attack = false;
      first = true;
      var.logicstate = NOTHING_HAPPENING;
    }  //if it returns -1, an option hasn't been selected yet
  }
}

void unit_unloading()
{
  static bool first = true;
  static bool choosing_unit = true;
  static bool two_units;
  static int number_unloaded;
  static int unloadee;
  static int unloadnum;
  static vector<_loc> locations;
  _unit *u = &player[pturn].unit[var.unitselected];
  _unit *v;
  int tx, ty, temp1, temp2;
  int mx = mouse_x;
  int my = mouse_y;
  int really_cancel;
  if (first == true)
  {
    choosing_unit = true;
    unloadee = -1;
    first = false;
    locations.resize(0);
    locations.reserve(2);
    if ((u->load[0].loaded == 1) && (u->load[1].loaded == 1))
    {  //the lander is the only unit which can load two other units
      two_units = true;
    }
    else
    {
      two_units = false;
    }
  }
  if (choosing_unit == true)
  {
    unloadnum = do_unloadmenu(u);
    if (unloadnum > -1)
    {
      choosing_unit = false;
      if (unloadnum != 2)
      {
        locations = find_unload_locations(u, u->load[unloadnum].type);
        position_mouse(var.oldmx, var.oldmy);
      }
      else
      {  //if unloadnum == 2 then the cancel button has been pressed
        if (number_unloaded == 0)
        {  //if it hasn't unloaded anything, it can return to its original state
          u->set_tiles(var.oldux, var.olduy);
          u->ready = 1;
        }
        first = true;
        number_unloaded = 0;
        var.unitselected = -1;
        var.logicstate = NOTHING_HAPPENING;
      }
    }
  }
  else if (var.cancel_unload == false)
  {
    show_unload_locations(locations);
    if (mouse_rclicked() == 1)
    {
      var.cancel_unload = true;
    }
    if (mouse_clicked() == 1)
    {
      if (mx >= worldmap.offset_x)
      {
        tx = worldmap.scroll_x + (mx - worldmap.offset_x) / MAP_TILE_SIZE;
      }
      else
      {
        tx = worldmap.scroll_x - 1 + (mx - worldmap.offset_x) / MAP_TILE_SIZE;
      }
      if (my >= worldmap.offset_y)
      {
        ty = worldmap.scroll_y + (my - worldmap.offset_y) / MAP_TILE_SIZE;
      }
      else
      {
        ty = worldmap.scroll_y - 1 + (my - worldmap.offset_y) / MAP_TILE_SIZE;
      }
      if (unit_unloadable_here(u->tilex, u->tiley, tx, ty, u->load[unloadnum].type))
      {
        u->load[unloadnum].loaded = 0;
        unloadee = player[pturn].create_unit(u->load[unloadnum].type, tx, ty, pturn);
        v = &player[pturn].unit[unloadee];
        v->gas = u->load[unloadnum].gas;
        v->ammo = u->load[unloadnum].ammo;
        v->health = u->load[unloadnum].health;
        if (u->load[unloadnum].subload.loaded == 1)
        {
          v->load[0].loaded = 1;
          v->load[0].type = u->load[unloadnum].subload.type;
          v->load[0].gas = u->load[unloadnum].subload.gas;
          v->load[0].ammo = u->load[unloadnum].subload.ammo;
          v->load[0].health = u->load[unloadnum].subload.health;
          u->load[unloadnum].subload.loaded = 0;
        }
        number_unloaded++;
        if ((number_unloaded == 1) && (two_units == true))
        {  //if it is a lander, it can unload both units in one turn
          first = true;
          if ((!u->can_unload_unit(0)) && (!u->can_unload_unit(1)))
          {  //but if there is no place to unload a second unit
            u->ready = 0;
            number_unloaded = 0;
            var.logicstate = NOTHING_HAPPENING;
          }
        }
        else
        {
          u->ready = 0;
          first = true;
          number_unloaded = 0;
          var.logicstate = NOTHING_HAPPENING;
        }
      }
    }
  }
  else if (var.cancel_unload == true)
  {
    really_cancel = do_cancelunload_menu();
    if (really_cancel == 0)
    {
      temp1 = (u->tilex - worldmap.scroll_x) * MAP_TILE_SIZE;
      temp2 = (u->tiley - worldmap.scroll_y) * MAP_TILE_SIZE;
      position_mouse(temp1 + MAP_TILE_SIZE / 2, temp2 + MAP_TILE_SIZE / 2);
      var.cancel_unload = false;
    }
    else if (really_cancel == 1)
    {
      temp1 = (u->tilex - worldmap.scroll_x) * MAP_TILE_SIZE;
      temp2 = (u->tiley - worldmap.scroll_y) * MAP_TILE_SIZE;
      position_mouse(temp1 + MAP_TILE_SIZE / 2, temp2 + MAP_TILE_SIZE / 2);
      if (number_unloaded == 0)
      {  //if it hasn't unloaded anything yet, it can return to its original position
        u->set_tiles(var.oldux, var.olduy);
        u->ready = 1;
      }
      else
      {
        u->ready = 0;
      }
      first = true;
      number_unloaded = 0;
      var.cancel_unload = false;
      var.logicstate = NOTHING_HAPPENING;
    }
  }
  check_scrolling();
}

void unit_teleporting()
{
  static bool first = true;
  static bool selecting;
  static int destx, desty, time;
  static float a, inc;
  int really_cancel, t1, t2, t3, t4;
  _unit *u = &player[pturn].unit[var.unitselected];
  _tile *t;
  
  if (first)
  {
    selecting = true;
    destx = -1;
    desty = -1;
    a = 0.5;
    inc = 0.02;
    time = 0;
    first = false;
  }
  
  if (selecting)
  {
    t2 = worldmap.scroll_y - 1;
    if (t2 < 0) t2 = 0;
    while ((t2 < worldmap.scroll_y + YTILES + 1) && (t2 < worldmap.h))
    {
      t1 = worldmap.scroll_x - 1;
      if (t1 < 0) t1 = 0;
      while ((t1 < worldmap.scroll_x + XTILES + 1) && (t1 < worldmap.l))
      {
        if ((worldmap.tile[t1][t2].same_type(6, 0)) && (any_unit_here(t1, t2) == -1))
        {
          t3 = (t1 - worldmap.scroll_x) * MAP_TILE_SIZE;
          t4 = (t2 - worldmap.scroll_y) * MAP_TILE_SIZE;
          buffer_rect(t3 + worldmap.offset_x, t4 + worldmap.offset_y, t3 + MAP_TILE_SIZE + worldmap.offset_x, t4 + MAP_TILE_SIZE + worldmap.offset_y, WHITE, a);
        }
        t1++;
      }
      t2++;
    }
    a += inc;
    if (a >= 1.0) inc = -0.02;
    if (a <= 0.25) inc = 0.02;
  
    if (!var.cancel_teleport)
    {
      if (mouse_clicked() == 1)
      {
        t1 = worldmap.scroll_x + (mouse_x - worldmap.offset_x) / MAP_TILE_SIZE;
        t2 = worldmap.scroll_y + (mouse_y - worldmap.offset_y) / MAP_TILE_SIZE;
        if ((t1 != u->tilex) || (t2 != u->tiley))
        {
          t = &worldmap.tile[t1][t2];
          if (t->same_type(6, 0))  //if this tile is a teleporter
          {
            if (any_unit_here(t1, t2) == -1)
            {
              destx = t1;
              desty = t2;
              selecting = false;
            }
          }
        }
      }
      else if (mouse_rclicked() == 1)
      {
        var.cancel_teleport = true;
      }
    }
    else
    {
      really_cancel = do_cancelteleport_menu();
      if (really_cancel == 0)
      {
        t1 = (u->tilex - worldmap.scroll_x) * MAP_TILE_SIZE;
        t2 = (u->tiley - worldmap.scroll_y) * MAP_TILE_SIZE;
        position_mouse(t1 + MAP_TILE_SIZE / 2, t2 + MAP_TILE_SIZE / 2);
        var.cancel_teleport = false;
      }
      else if (really_cancel == 1)
      {
        t1 = (u->tilex - worldmap.scroll_x) * MAP_TILE_SIZE;
        t2 = (u->tiley - worldmap.scroll_y) * MAP_TILE_SIZE;
        position_mouse(t1 + MAP_TILE_SIZE / 2, t2 + MAP_TILE_SIZE / 2);
        u->ready = 1;
        u->set_tiles(var.oldux, var.olduy);
        var.cancel_teleport = false;
        first = true;
        var.logicstate = NOTHING_HAPPENING;
      }
    }
    check_scrolling();
  }
  else
  {  //teleportation animation
    if (time == 0)
    {
      if (scroll_to_location(u->tilex, u->tiley) == 0)
      {
        time--;
      }
    }
    else if (time == 1)
    {
      t1 = u->tilex * MAP_TILE_SIZE;
      t2 = u->tiley * MAP_TILE_SIZE;
      create_particle(t1 + MAP_TILE_SIZE / 2, t2 + MAP_TILE_SIZE / 2, P_SHOCKWAVE);
      create_particle(t1, t2, P_TELEPORT);
      play_sound(S_TELEPORT);
    }
    else if (time == 9)
    {
      u->exists = 0;
    }
    else if (time == 25)
    {
      if (scroll_to_location(destx, desty) == 0)
      {
        time--;
      }
    }
    else if (time == 26)
    {
      u->set_tiles(destx, desty);
      create_particle(destx * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, desty * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, P_SHOCKWAVE);
      create_particle(destx * MAP_TILE_SIZE, desty * MAP_TILE_SIZE, P_TELEPORT);
      play_sound(S_TELEPORT);
    }
    else if (time == 34)
    {
      u->exists = 1;
    }
    else if (time > 50)
    {
      first = true;
      var.logicstate = NOTHING_HAPPENING;
    }
    time++;
  }
}

void supply_units(_unit *u)
{
  int q;
  int x, y;
  int i = 0;
  while (i < 4)
  {
    switch(i)
    {
      case 0:
        x = u->tilex - 1;
        y = u->tiley;
        break;
      case 1:
        x = u->tilex + 1;
        y = u->tiley;
        break;
      case 2:
        x = u->tilex;
        y = u->tiley - 1;
        break;
      case 3:
        x = u->tilex;
        y = u->tiley + 1;
        break;
    }
    if (worldmap.in_bounds(x, y))
    {
      q = worldmap.tile[x][y].unit_here();
      if ((q != -1) && (q / 100 == u->color))
      {
        player[u->color].unit[q % 100].supply();
      }
    }
    i++;
  }
}

int buildings_owned(int plyr)
{
  int temp1, temp2;
  int num = 0;
  temp1 = 0;
  while (temp1 < worldmap.h)
  {
    temp2 = 0;
    while (temp2 < worldmap.l)
    {
      if (worldmap.tile[temp2][temp1].owned_by(plyr))
      {
        num++;
      }
      temp2++;
    }
    temp1++;
  }
  return num;
}

int unit_here_thorough(int plyr, int tx, int ty, int ignore_n)
{
  int i = 0;
  _unit *u;
  while (i < 50)
  {
    if (i != ignore_n)
    {
      u = &player[plyr].unit[i];
      if (u->exists == 1)
      {
        if ((u->tilex == tx) && (u->tiley == ty))
        {
          return i;
        }
      }
    }
    i++;
  }
  return -1;
}

int rounded_health(float h)
{
  int whole = int(h);
  int part = int((h - float(whole)) * 10);
  if ((whole == 0) && (h > 0))
  {
    return 1;
  }
  else if (whole == 10)
  {
    return 10;
  }
  else
  {
    if (part >= 5)
    {
      return whole + 1;
    }
    else
    {
      return whole;
    }
  }
}

void transform_buildings(int plyr, int plyr2)
{
  int i, j, z;
  _tile *t;
  _unit *u;
  i = 0;
  while (i < worldmap.l)
  {
    j = 0;
    while (j < worldmap.h)
    {
      t = &worldmap.tile[i][j];
      if (t->is_building())
      {
        if (t->owned_by(plyr))
        {
          z = t->unit_here();
          if (z != -1)
          {
            if (z / 100 == plyr2)  //plyr2 unit capping building
            {  //but the building's being transformed into plyr2's already
              u = &player[z / 100].unit[z % 100];
              u->capturing = -1;  //so stop capturing
            }  //(doesn't stop captures of other teams)
          }
          if (t->is_HQ())
          {
            t->change_to_city();
            t->change_owner(plyr2);
          }
          else
          {  //building here
            t->change_owner(plyr2);
          }
        }
      }
      j++;
    }
    i++;
  }
  minimap.create();
}

void repair_units(int plyr)
{
  int i = 0;
  int btype;
  bool rep;
  float oldh;
  _unit *u;
  _tile *t;
  while (i < 50)
  {
    u = &player[plyr].unit[i];
    if (u->exists == 1)
    {
      rep = false;
      t = &worldmap.tile[u->tilex][u->tiley];
      if (t->is_building())
      {
        if (t->owned_by(plyr))
        {
          btype = t->building_type();
          switch(u->basetype)
          {
            case LAND:
              if ((btype == CITY) || (btype == HQ) || (btype == BASE))
              {
                rep = true;
              }
              break;
            case SEA:
              if (btype == PORT)
              {
                rep = true;
              }
              break;
            case AIR:
              if (btype == AIRPORT)
              {
                rep = true;
              }
              break;
          }
        }
      }
      if (rep == true)  //if the unit is on a friendly base
      {
        u->supply();  //resupply the unit
        if (u->health < 10)  //if the unit is damaged, add 2 health but take some cash
        {
          oldh = u->health;
          u->health += 2;
          if (u->health > 10)
          {
            u->health = 10;
          }
          player[plyr].cash -= int((u->health - oldh) / 20 * u->price);
          if (player[plyr].cash < 0)
          {
            player[plyr].cash = 0;
          }
        }
      }
    }
    i++;
  }
}

void play_moving_sound(int utype)
{
  switch(utype)
  {
    case ANTI_AIR:
      play_sound(S_TANKMOVE);
      break;
    case APC:
      play_sound(S_ENGINE);
      break;
    case ARTILLERY:
      play_sound(S_TANKMOVE);
      break;
    case B_COPTER:
      play_sound(S_CHOPPER);
      break;
    case B_SHIP:
      play_sound(S_SEABOAT);
      break;
    case BOMBER:
      play_sound(S_JET);
      break;
    case CRUISER:
      play_sound(S_SEABOAT);
      break;
    case FIGHTER:
      play_sound(S_JET);
      break;
    case INFANTRY:
      play_sound(S_MARCH);
      break;
    case LANDER:
      play_sound(S_SEABOAT);
      break;
    case MD_TANK:
      play_sound(S_TANKMOVE);
      break;
    case MECH:
      play_sound(S_MARCH);
      break;
    case MISSILES:
      play_sound(S_ENGINE);
      break;
    case RECON:
      play_sound(S_ENGINE);
      break;
    case ROCKETS:
      play_sound(S_TANKMOVE);
      break;
    case SUB:
      play_sound(S_SEABOAT);
      break;
    case T_COPTER:
      play_sound(S_CHOPPER);
      break;
    case TANK:
      play_sound(S_TANKMOVE);
      break;
  }
}

int do_powerflash(int pnum)
{
  static bool first = true;
  static short t, stage, textx, texty;
	float m;

  if (first)
  {
    t = 0;
		stage = 0;
		textx = 320 - (big.Width(currentcharacter[pnum]->getpowername()) / 2);
		texty = 240 - (big.Height(currentcharacter[pnum]->getpowername()) / 2);
    first = false;
  }
  
	switch(stage)
	{
		case 0:
			m = 1 + (float(t) / 10);
			buffer_stretch_sprite(currentcharacter[pnum]->picture, 320 - int(t * m/2), 240 - int(t * m/2), int(t * m), int(t * m), 1.0 - (float(t) / 100));
			buffer_rectfill(0, 0, 640, 480, player_color(pnum), float(t) / 100);
			t++;
			if (t >= 100)
			{
				stage++;
				t = 0;
			}
			break;
		case 1:
			t++;
			buffer_rectfill(0, 0, 640, 480, player_color(pnum));
			buffer_textout_ex(big, currentcharacter[pnum]->getpowername(), textx, texty, BLACK, 1 - (float(t) / 75));
			if (t >= 75)
			{
				stage++;
				t = 0;
			}
			break;
		case 2:
      first = true;
      return -1;  //return -1 to end the animation
			break;
  }
  return 1;  //return anything other than -1 to continue animation
}

void decrease_gas(int plyr)
{
  int i = 0;
  while (i < 50)
  {
    if (player[plyr].unit[i].exists == 1)
    {
      if ((player[plyr].unit[i].basetype == AIR) || (player[plyr].unit[i].basetype == SEA))
      {
        player[plyr].unit[i].gas -= 2;
        if (player[plyr].unit[i].submerged == 1)
        {  //submerged subs lose 4 gas per turn instead of 2
          player[plyr].unit[i].gas -= 2;
        }
        if (player[plyr].unit[i].gas <= 0)
        {
          player[plyr].unit[i].gas = 0;
          player[plyr].unit[i].kill();
        }
      }
    }
    i++;
  }
}

void init_explode(int tx, int ty)
{
  _unitexplosion u;
  int i;
  boom.push_back(u);
  i = boom.size() - 1;
  boom[i].exists = 1;
  boom[i].tx = tx;
  boom[i].ty = ty;
  boom[i].frame = 0;
}

void destroy_theplayers_units()
{
  static int i = 0;
  static bool first = true;
  static bool exploding = false;
	char str[20];
  
  if (first)
  {
    i = 0;
    exploding = false;
		sprintf(str, "Player %d Defeated", var.theplayer + 1);
		create_particle(320 - normal.Width(str) / 2, 200, P_FADETEXT, BLACK, str);
    first = false;
  }
  
  if (exploding)
  {
    if (do_explodes() == 1)
    {
      exploding = false;
    }
  }
  else
  {
    if (check_explodes())
    {  //if there was a unit explosion going on already, like from a battle
      exploding = true;
    }
    else if (i == 50)
    {
      first = true;
      var.logicstate = NOTHING_HAPPENING;
    }
    else
    {
      if (player[var.theplayer].unit[i].exists == 1)
      {
        player[var.theplayer].unit[i].kill();
        exploding = true;
      }
      i++;
    }
  }
}

int do_explodes()
{
  static bool first = true;
  static bool scrolling;
  static int n, x, y;
  unsigned int i;
  
  if (first)
  {
    i = 0;
    while (i < boom.size())
    {
      if (boom[i].exists == 1)  //find the first explosion on the list
      {
        n = i;
        i = boom.size();
      }
      i++;
    }
    scrolling = true;
    first = false;
  }
  
  if (scrolling)
  {
    if (scroll_to_location(boom[n].tx, boom[n].ty) == 1)
    {  //if it has finished doing the smooth scroll to the explosion site
      scrolling = false;
      play_sound(S_EXPLOSION);
			worldmap.tile[boom[n].tx][boom[n].ty].set_unit(-1, -1);
      x = (boom[n].tx - worldmap.scroll_x) * MAP_TILE_SIZE + worldmap.offset_x;
      y = (boom[n].ty - worldmap.scroll_y) * MAP_TILE_SIZE + worldmap.offset_y;
    }
  }
  if (!scrolling)
  {
    boom[n].frame += 1.5;
    if (int(boom[n].frame) > 29)
    {
      boom[n].exists = 0;
      first = true;
      return 1;
    }
    else
    {
      create_particle(boom[n].tx * MAP_TILE_SIZE + (MAP_TILE_SIZE / 2), boom[n].ty * MAP_TILE_SIZE + (MAP_TILE_SIZE / 2), 0);
      explode1.draw(int(boom[n].frame), x, y);
    }
  }
  return 0;
}

void do_power()
{
  int i, j, r, n;
  
	n = 0;
	while (n < NUM_POWERS)
	{
		switch(n)
		{
			case PWR_HEAL:
				if (currentcharacter[pturn]->power[n] > 0)
				{
					i = 0;
					while (i < 50)
					{
						player[pturn].unit[i].health += currentcharacter[pturn]->power[n];
						if (player[pturn].unit[i].health > 10)
						{
							player[pturn].unit[i].health = 10;
						}
						i++;
					}
				}
				break;
			case PWR_DAMAGE:
				if (currentcharacter[pturn]->power[n] > 0)
				{
      		j = 0;
      		while (j < 4)
      		{
		        if ((player[j].playing == 1) && (j != pturn))
        		{
		          if (player[j].team != player[pturn].team)
          		{  //if this player isn't on the powered player's team
		            i = 0;
            		while (i < 50)
            		{  //start dealing damage
		              if (player[j].unit[i].exists == 1)
              		{
		                player[j].unit[i].health -= currentcharacter[pturn]->power[n];
                		if (player[j].unit[i].health <= 0)
                		{
		                  player[j].unit[i].health = 0.01;  //any health below this is counted as "dead"
                		}
              		}
              		i++;
            		}
          		}
        		}
        		j++;
      		}
				}
      	break;
			case PWR_RANDKILL:
				if (currentcharacter[pturn]->power[n] > 0)
				{
		      i = 0;
      		while (i < 4)
      		{
		        if ((player[i].playing == 1) && (i != pturn))
        		{
		          if (player[i].team != player[pturn].team)
          		{  //don't count mission-critical units
								j = 0;
								while (j < 50)
								{
									r = rand()%100;
									if (r < 10 * currentcharacter[pturn]->power[n])
									{
										player[i].unit[j].kill();
									}
									j++;
								}
          		}
        		}
        		i++;
      		}
				}
      	break;
		}
		n++;
  }
}

int secure_base(int plyr)
{
  int x, y, u;
  y = 0;
  while (y < worldmap.h)
  {
    x = 0;
    while (x < worldmap.l)
    {
      if (worldmap.tile[x][y].is_unit_producing())
      {
        if (worldmap.tile[x][y].owned_by(plyr))
        {  //if it belongs to the player
          u = worldmap.tile[x][y].unit_here();
          if ((u == -1) || (u / 100 == plyr) || (player[u / 100].team == player[plyr].team))
          {  //there is no unit here or a unit that belongs to this player or an ally
            return 1;
          }
        }
      }
      x++;
    }
    y++;
  }
  return 0;
}

void capture_building(_unit* u)
{
  int z;
  if (u->capturing == -1)
  {  //just started a capture
    u->capturing = 20;
    u->capturing -= rounded_health(u->health);
  }
  else  //already in the process of capturing
  {
    u->capturing -= rounded_health(u->health);
    if (u->capturing <= 0)
    {  //if the building has been captured
      u->capturing = -1;
      if (worldmap.tile[u->tilex][u->tiley].is_HQ())
      {  //if a player's HQ was captured
        z = worldmap.tile[u->tilex][u->tiley].owner();
        transform_buildings(z, u->color);  //captured player's buildings go to the capturer
        var.logicstate = PLAYER_DEFEATED;
        var.theplayer = z;
        player[z].playing = 0;
      }
      else
      {
        worldmap.tile[u->tilex][u->tiley].change_owner(u->color);
      }
      minimap.create();
    }
  }
}

bool can_merge(_unit *a, _unit *b)
{
  int numloaded = 0;
  if ((a->health < 10) || (b->health < 10))
  {
    if (a->load[0].loaded == 1)
    {
      numloaded++;
    }
    if (a->load[1].loaded == 1)
    {
      numloaded++;
    }
    if (b->load[0].loaded == 1)
    {
      numloaded++;
    }
    if (b->load[1].loaded == 1)
    {
      numloaded++;
    }
    if (numloaded == 0)
    {
      return true;
    }
    if (numloaded == 1)
    {
      if ((a->type == APC) || (a->type == LANDER) || (a->type == T_COPTER))
      {
        return true;
      }
    }
    if (numloaded == 2)
    {
      if (a->type == LANDER)
      {
        return true;
      }
    }
  }
  return false;
}

void merge_units(_unit* merger, int tx, int ty)
{
  int u = unit_here_thorough(merger->color, tx, ty, merger->number);
  _unit* mergee = &player[merger->color].unit[u];
  merger->gas += mergee->gas;
  if (merger->gas > 99)
  {
    merger->gas = 99;
  }
  merger->ammo += mergee->ammo;
  if (merger->ammo > 99)
  {
    merger->ammo = 99;
  }
  merger->health += mergee->health;
  if (merger->health > 10)
  {
    merger->health = 10;
  }
  merger->capturing = mergee->capturing;
  if (mergee->load[0].loaded == 1)
  {
    if (merger->load[0].loaded == 0)
    {
      merger->load[0] = mergee->load[0];
    }
    else
    {
      merger->load[1] = mergee->load[0];
    }
  }
  if (mergee->load[1].loaded == 1)
  {
    if (merger->load[0].loaded == 0)
    {
      merger->load[0] = mergee->load[1];
    }
    else
    {
      merger->load[1] = mergee->load[1];
    }
  }
  worldmap.tile[tx][ty].set_unit(merger->color, merger->number);
  mergee->exists = 0;
}

bool check_explodes()
{
  bool emptyboom = true;
  int temp1, temp2;
  if ((var.logicstate != EXPLODING) && (var.logicstate != IN_BATTLE))
  {  //if it's not in the middle of an explosion animation
    temp1 = 0;
    temp2 = boom.size();
    while (temp1 < temp2)
    {
      if (boom[temp1].exists == 1)  //check to see if it should be
      {
        emptyboom = false;
      }
      temp1++;
    }
    if (emptyboom)
    {  //if there aren't any existing explosions left
      boom.resize(0);  //get rid of all the finished explosions
    }
  }
  return !emptyboom;
}

void debug_savegame()
{
  ofstream savefile("saves/gamedebug.sav");
  if (!(savefile.bad()))
  {
    savefile << "Debuggery\n" << worldmap.l << "\n" << worldmap.h << "\n";

		save_map_and_players(&savefile);
		
    savefile << "pturn " << pturn << "\n" << gameoptions.funding << "\n";
    savefile << gameoptions.show_damage << "\n" << gameoptions.time << "\n";
    savefile << var.time << "\n" << worldmap.get_name().c_str();
		
		save_currentcharacters("saves/gamedebug.sav");
  }
  savefile.close();
}

void save_map_and_players(ofstream *savefile)
{
	int o, p;
	_tile *tile;

  o = 0;
  while (o < worldmap.h)
  {
    p = 0;
    while (p < worldmap.l)
    {
      tile = &worldmap.tile[p][o];
      *savefile << ((tile->get_set() * 100) + tile->get_number());
      if (p != worldmap.l - 1)
      {
        *savefile << " ";
      }
      p++;
    }
    *savefile << "\n";
    o++;
  }

  o = 0;
  while (o < 4)
  {
    *savefile << "playing " << player[o].playing << "\n";
    *savefile << "everplaying " << player[o].everplaying << "\n";
    if (player[o].everplaying == 1)
    {
      *savefile << "number " << player[o].number << "\n";
      *savefile << "cash " << player[o].cash << "\n";
      *savefile << "power " << player[o].power << "\n";
      *savefile << "controller " << player[o].controller << "\n";
      *savefile << "powered " << player[o].powered << "\n";
      *savefile << "units " << player[o].units_in_play() << "\n";
      *savefile << "team " << player[o].team << "\n";
      *savefile << "tookturn " << player[o].tookturn << "\n";
    }
    p = 0;
    if (player[o].playing != 1)
    {
      p = 50;
    }
    while (p < 50)
    {
      if (player[o].unit[p].exists == 1)
      {
        *savefile << "unittype " << player[o].unit[p].type << "\n";
        *savefile << "unittilex " << player[o].unit[p].tilex << "\n";
        *savefile << "unittiley " << player[o].unit[p].tiley << "\n";
        *savefile << "unithealth " << player[o].unit[p].health << "\n";
        *savefile << "unitammo " << player[o].unit[p].ammo << "\n";
        *savefile << "unitgas " << player[o].unit[p].gas << "\n";
        *savefile << "unitready " << player[o].unit[p].ready << "\n";
        *savefile << "unitcapturing " << player[o].unit[p].capturing << "\n";
        *savefile << "unitsubmerged " << player[o].unit[p].submerged << "\n";
        *savefile << "unitload0loaded " << player[o].unit[p].load[0].loaded << "\n";
        *savefile << "unitload0type " << player[o].unit[p].load[0].type << "\n";
        *savefile << "unitload0health " << player[o].unit[p].load[0].health << "\n";
        *savefile << "unitload0ammo " << player[o].unit[p].load[0].ammo << "\n";
        *savefile << "unitload0gas " << player[o].unit[p].load[0].gas << "\n";
        *savefile << "unitload0subloaded " << player[o].unit[p].load[0].subload.loaded << "\n";
        *savefile << "unitload0subtype " << player[o].unit[p].load[0].subload.type << "\n";
        *savefile << "unitload0subhealth " << player[o].unit[p].load[0].subload.health << "\n";
        *savefile << "unitload0subammo " << player[o].unit[p].load[0].subload.ammo << "\n";
        *savefile << "unitload0subgas " << player[o].unit[p].load[0].subload.gas << "\n";
        *savefile << "unitload1loaded " << player[o].unit[p].load[1].loaded << "\n";
        *savefile << "unitload1type " << player[o].unit[p].load[1].type << "\n";
        *savefile << "unitload1health " << player[o].unit[p].load[1].health << "\n";
        *savefile << "unitload1ammo " << player[o].unit[p].load[1].ammo << "\n";
        *savefile << "unitload1gas " << player[o].unit[p].load[1].gas << "\n";
        *savefile << "unitload1subloaded " << player[o].unit[p].load[1].subload.loaded << "\n";
        *savefile << "unitload1subtype " << player[o].unit[p].load[1].subload.type << "\n";
        *savefile << "unitload1subhealth " << player[o].unit[p].load[1].subload.health << "\n";
        *savefile << "unitload1subammo " << player[o].unit[p].load[1].subload.ammo << "\n";
        *savefile << "unitload1subgas " << player[o].unit[p].load[1].subload.gas << "\n";
      }
      p++;
    }
    o++;
  }
}
