#include "empire.h"

const int INTRO = -10;
const int FIRST = -11;
const int LOAD = -12;
const int OPTIONS = -13;
const int GAME_OPTIONS = -14;
const int GAME_LOAD = -15;

int numplayers;

extern int dovsync;
extern int mspeed;
extern int volume;
extern int dodoublebuffer;

_button start[5];
_button pselect[6];
_button back;
_button ok;
_button plyr[8];
_button opt[10];

_player player[4];

DATAFILE *glb;
extern void draw_minimap(int x, int y, string file);
extern void clear_unitmap();

void description(int c);
void list_players(int numplayers, int selected);
void load_custom_ai(string mname);
int do_first();
int do_load();
int do_options();
int do_gameoptions();
int do_gameload();

int is_beach(int x, int y);
int beach_already_listed(int x, int y);
extern int get_set(int mapdat);
extern int building_here(int tx, int ty);
void get_connected_beaches();
void add_surrounding_beaches(int bnum, int x, int y);

vector<_connectedlocs> beaches;

int menu()
{
  glb = (DATAFILE *)graphics[2].dat;
  static int menunum = INTRO;
  int t;
  switch (menunum)
  {
    case INTRO:
      clear(back_buffer);
      blit((BITMAP *)glb[0].dat, back_buffer, 0, 0, 95, 20, 450, 450);
      masked_blit((BITMAP *)glb[1].dat, back_buffer, 0, 0, 58, 0, 524, 128);
      create_dirty(BACK, 58, 5, 524, 128);
      create_dirty(BACK, 95, 15, 450, 450);
      menunum = FIRST;
      break;
    case FIRST:
      menunum = do_first();
      break;
    case LOAD:
      menunum = do_load();
      break;
    case OPTIONS:
      menunum = do_options();
      break;
    case MAPEDIT:
      menunum = INTRO;
      return MAPEDIT;
      break;
    case GAME_OPTIONS:
      menunum = do_gameoptions();
      break;
    case GAME_LOAD:
      menunum = do_gameload();
      break;
    case QUIT:
      return QUIT;
      break;
    default:        //default cases would lead out of the menu, so
      t = menunum;  //the menu has to open in INTRO next time
      menunum = INTRO;
      return t;
      break;
  }
  return MENU;
}





int do_first()
{
  static int drawbox = 1;
  int moved = mouse_moved();
  if (drawbox == 1)
  {
    clear_to_color(back_buffer, BLACK);
    blit((BITMAP *)glb[0].dat, back_buffer, 0, 0, 95, 20, 450, 450);
    masked_blit((BITMAP *)glb[1].dat, back_buffer, 0, 0, 58, 0, 524, 128);
    start[0].init(270, 150, 100, 20, "Start");
    start[0].draw(back_buffer);
    start[1].init(270, 180, 100, 20, "Load Game");
    start[1].draw(back_buffer);
    start[2].init(270, 240, 100, 20, "Quit");
    start[2].draw(back_buffer);
    start[3].init(270, 300, 100, 20, "Map Editor");
    start[3].draw(back_buffer);
    start[4].init(270, 350, 100, 20, "Options");
    start[4].draw(back_buffer);
    create_dirty(BACK, 0, 0, 640, 480);
    aiprofile = 0;  //reset the AI profile to the default
    moved = 1;
    drawbox = 0;
  }
  start[0].check(back_buffer, moved);
  start[1].check(back_buffer, moved);
  start[2].check(back_buffer, moved);
  start[3].check(back_buffer, moved);
  start[4].check(back_buffer, moved);
  if (start[0].clicked() == 1)
  {
    clear(back_buffer);
    create_dirty(BACK, 0, 0, 640, 480);
    drawbox = 1;
    return LOAD;
  }
  if (start[1].clicked() == 1)
  {
    drawbox = 1;
    return GAME_LOAD;
  }
  if ((start[2].clicked() == 1) || (key[KEY_ESC]))
  {
    drawbox = 1;
    return QUIT;
  }
  if (start[3].clicked() == 1)
  {
    drawbox = 1;
    return MAPEDIT;
  }
  if (start[4].clicked() == 1)
  {
    drawbox = 1;
    return GAME_OPTIONS;
  }
  if (moved == 1)
  {
    draw_mouse();
  }
  return FIRST;
}





int do_load()
{
  static int drawfirst = 1;
  static int mapok = 1;
  static int highlighted = -1;
  static int delay = 0;
  static int lscroll = 0;
  static int mapnum;
  int moved = mouse_moved();
  int a, b, c, d;
  int i;
  int j;
  int ok;
  int mx;
  int my;
  int sel;
  char p[30] = "";
  string name;
  static string n[50];
  if (drawfirst == 1)
  {
    blit((BITMAP *)glb[11].dat, back_buffer, 0, 0, 0, 0, 640, 480);
    text_mode(-1);
    textout_centre(back_buffer, (FONT *)glb[2].dat, "SELECT THE BATTLEGROUND", 320, 410, BLACK);
    text_mode(0);
    ifstream map("maps/maplist.txt");
    if (map.bad())
    {
      textout(back_buffer, font, "Unable to load 'maplist.txt'", 5, 5, RED);
      mapok = 0;
    }
    i = 0;
    while (i < 50)
    {
      n[i] = "";
      i++;
    }
    opt[0].init(10, 455, 100, 20, "Back");
    opt[0].draw(back_buffer);
    rect(back_buffer, 195, 55, 370, 385, LGREY);
    rectfill(back_buffer, 196, 56, 369, 384, BLACK);
    if (mapok == 1)
    {
      i = 0;
      while (!map.eof())
      {
        getline(map, n[i]);
        sprintf(p, n[i].c_str());    //
        a = strlen(p) - 1;           //
        b = 0;                       //
        while (b < 4)                //
        {                            // this code removes the ".map"
          p[a] = '\0';               // from the end of the name
          a--;                       //
          b++;                       //
        }                            //
        n[i] = p;                    //
        i++;
      }
      if (i > 22)  //if the list will go beyond the load box
      {
        opt[1].init(195, 390, 85, 20, "Up");
        opt[1].draw(back_buffer);
        opt[2].init(285, 390, 85, 20, "Down");
        opt[2].draw(back_buffer);
      }
      mapnum = i;
      i = lscroll;
      while (i < lscroll + 22)
      {
        textout(back_buffer, font, n[i].c_str(), 200, 59 + (15 * (i - lscroll)), WHITE);
        i++;
      }
    }
    create_dirty(BACK, 0, 0, 640, 480);
    moved = 1;
    drawfirst = 0;
  }
  opt[0].check(back_buffer, moved);
  if (mapnum > 22)
  {
    opt[1].check(back_buffer, moved);
    opt[2].check(back_buffer, moved);
    if (opt[1].clicked() == 1)
    {
      if (lscroll > 0)
      {
        lscroll--;
        drawfirst = 1;
      }
    }
    if (opt[2].clicked() == 1)
    {
      if (lscroll + 22 < mapnum)
      {
        lscroll++;
        drawfirst = 1;
      }
    }
  }
  if (opt[0].clicked() == 1)
  {
    clear(back_buffer);
    drawfirst = 1;
    highlighted = -1;
    lscroll = 0;
    return FIRST;
  }
  mx = mouse_x;
  my = mouse_y;
  if ((mx > 200) && (mx < 370))
  {
    if ((my > 55) && (my < 385))
    {
      sel = (my - 55) / 15 + lscroll;
      if ((sel != highlighted) && (n[sel].c_str() != ""))
      {
        strcat(p, "maps/");
        strcat(p, n[sel].c_str());
        strcat(p, ".map");
        ifstream m(p);
        ok = 1;
        if (m.bad())
        {
          ok = 0;
          m.close();
        }
        if (ok == 1)
        {
          m >> a >> b >> c;
          m.close();
          rectfill(back_buffer, 391, 146, 614, 384, BLACK);
          rect(back_buffer, 390, 145, 615, 385, VDGREY);
          textout(back_buffer, font, n[sel].c_str(), 400, 150, WHITE);
          textprintf(back_buffer, font, 400, 160, WHITE, "%-1d Players", c);
          create_dirty(BACK, 390, 145, 230, 241);
          draw_minimap(400, 175, p);
          highlighted = sel;
        }
      }
      if (mouse_b & 1)
      {
        strcat(p, "maps/");
        strcat(p, n[sel].c_str());
        strcat(p, ".map");
        ok = 1;
        ifstream m(p);
        if (m.bad())
        {
          ok = 0;
        }
        if (ok == 1)
        {
          sprintf(mapname, n[sel].c_str());
          m >> l >> h >> numplayers;
          i = 0;
          while (i < numplayers)
          {  //initialize all players participating in this game
            player[i].playing = 1;
            player[i].cash = 0;
            player[i].power = 0;
            i++;
          }
          while (i < 4)
          {  //make sure the other players aren't in the game
            player[i].playing = 0;
            i++;
          }
          i = 0;
          while (i < h)
          {
            j = 0;
            while (j < l)
            {
              m >> map[j][i];
              j++;
            }
            i++;
          }
          player[0].clear_units();  //get rid of any previous unit settings
          player[1].clear_units();
          player[2].clear_units();
          player[3].clear_units();
          player[0].powered = 0;
          player[1].powered = 0;
          player[2].powered = 0;
          player[3].powered = 0;
          clear_unitmap();
          i = 0;
          while (i < 50 * numplayers)  //loading any placed units
          {
            m >> a;
            if (a != -1)  //if there is a saved unit for this i
            {
              m >> b >> c >> d;
              j = player[d].create_unit(c, a, b, d);
            }
            else  //if a reads -1, there are no more saved units
            {
              i = 50 * numplayers;
            }
            i++;
          }
          m >> aiprofile;
          name = mapname;  //load_custom_ai takes a string, so set string name to mapname
          load_custom_ai(name);
          lscroll = 0;
          drawfirst = 1;
          highlighted = -1;
          get_connected_beaches();
          return OPTIONS;
        }
      }
    }
  }
  if (delay > 0)
  {
    delay--;
  }
  if (moved == 1)
  {
    draw_mouse();
  }
  return LOAD;
}

int do_options()
{
  static int pselect = 0;
  static int drawfirst = 1;
  int selected = 0;
  int over[10];
  int i = 0;
  int j = 0;
  char m[15];
  int moved = mouse_moved();
  if (drawfirst == 1)
  {
    clear(back_buffer);
    back.init(560, 460, 80, 20, "Back");
    back.draw(back_buffer);
    i = 0;
    while (i < 4)
    {
      player[i].number = -1;
      player[i].playing = 1;
      i++;
    }
    list_players(numplayers, pselect);
    while (j < 2)
    {
      i = 0;
      while (i < 4)
      {
        plyr[i + (4 * j)].init(110 + (85 * i), 315 + (85 * j), 80, 80, "", character[i + (4 * j)].picture);
        plyr[i + (4 * j)].draw(back_buffer);
        over[i + (4 * j)] = 0;
        i++;
      }
      j++;
    }
    i = 0;
    while (i < numplayers)
    {
      opt[i].init(400, 40 + (40 * i), 80, 20, "Human");
      opt[i].draw(back_buffer);
      i++;
    }
    drawfirst = 0;
    moved = 1;
    create_dirty(BACK, 0, 0, 640, 480);
  }
  back.check(back_buffer, moved);
  i = 0;
  while (i < numplayers)
  {
    if (player[i].playing == 1)
    {
      opt[i].check(back_buffer, moved);
      if (opt[i].clicked() == 1)
      {
        if (opt[i].text == "Human")
        {
          opt[i].init(400, 40 + (40 * i), 80, 20, "AI");
          opt[i].draw(back_buffer);
        }
        else if (opt[i].text == "AI")
        {
          opt[i].init(400, 40 + (40 * i), 80, 20, "Human");
          opt[i].draw(back_buffer);
        }
      }
    }
    i++;
  }
  if (back.clicked() == 1)
  {
    clear(back_buffer);
    create_dirty(BACK, 0, 0, 640, 480);
    pselect = 0;
    drawfirst = 1;
    return LOAD;
  }
  if (pselect >= numplayers)
  {
    ok.check(back_buffer, moved);
    if (ok.clicked() == 1)
    {
      clear(back_buffer);
      create_dirty(BACK, 0, 0, 640, 480);
      pselect = 0;
      drawfirst = 1;
      i = 0;
      while (i < 4)  //set whether players 3 and four are actually in the game
      {
        if (i < numplayers)
        {
          player[i].playing = 1;
          if (opt[i].text == "Human")
          {
            player[i].controller = HUMAN;
          }
          else
          {
            player[i].controller = AI;
          }
        }
        else
        {
          player[i].playing = 0;
        }
        i++;
      }
      pturn = 0;  //make player 1 start first
      loaded_game = 0;  //the game was not loaded from a saved file
      very_first_turn = 1;
      return LOGIC;
    }
    description(-2);
  }
  else
  {
    selected = 0;
    i = 0;
    while (i < 8)
    {
      if (plyr[i].mouseover() == 1)
      {
        description(i);
        selected = 1;
      }
      if (plyr[i].clicked() == 1)
      {
        player[pselect].number = i;
        pselect++;
        if (pselect >= numplayers)
        {
          ok.init(545, 400, 95, 30, "OK");
          ok.draw(back_buffer);
        }
        list_players(numplayers, pselect);
      }
      i++;
    }
    if (selected == 0)
    {
      description(-1);
    }
  }
  if (moved == 1)
  {
    draw_mouse();
  }
  return OPTIONS;
}

void description(int c)
{
  static int old = 100;
  string n, m, s, w, p, d;
  if (old != c)
  {
    if ((c > -1) && (c < 8))
    {
      n = character[c].name;
      m = character[c].description;
      s = "Strength: ";
      switch(character[c].strength)
      {
        case 0:
          s += "Direct Attacks";
          break;
        case 1:
          s += "Ranged Attacks";
          break;
        case 2:
          s += "Land Units";
          break;
        case 3:
          s += "Air Units";
          break;
        case 4:
          s += "Sea Units";
          break;
        case 5:
          s += "None";
          break;
      }
      w = "Weakness: ";
      switch(character[c].weakness)
      {
        case 0:
          w += "Direct Attacks";
          break;
        case 1:
          w += "Ranged Attacks";
          break;
        case 2:
          w += "Land Units";
          break;
        case 3:
          w += "Air Units";
          break;
        case 4:
          w += "Sea Units";
          break;
        case 5:
          w += "None";
          break;
      }
      p = "Power: ";
      p += character[c].powername;
      d = "";
      switch(character[c].power)
      {
        case 0:
          d += "(Units gain 2 health)";
          break;
        case 1:
          d += "(More powerful direct attacks)";
          break;
        case 2:
          d += "(More powerful ranged attacks)";
          break;
        case 3:
          d += "(Deals 1 damage to each enemy unit)";
          break;
        case 4:
          d += "(Refreshes non-infantry units, but all units are weaker)";
          break;
        case 5:
          d += "(Kills 1/5 random enemy units)";
          break;
        case 6:
          d += "(Attacking ranged units have a 75% chance of firing twice)";
          break;
      }
    }
    else
    {
      n = "";
      m = "";
      p = "";
    }
    rectfill(back_buffer, 0, 240, 640, 314, BLACK);
    textout_centre(back_buffer, font, n.c_str(), 320, 242, WHITE);
    textout_centre(back_buffer, font, m.c_str(), 320, 252, WHITE);
    textout_centre(back_buffer, font, s.c_str(), 320, 272, GREEN);
    textout_centre(back_buffer, font, w.c_str(), 320, 282, RED);
    textout_centre(back_buffer, font, p.c_str(), 320, 292, WHITE);
    textout_centre(back_buffer, font, d.c_str(), 320, 302, LGREY);
    create_dirty(BACK, 0, 240, 640, 74);
    old = c;
  }
}

void list_players(int numplayers, int selected)
{
  int i = 0;
  char m[15];
  while (i < numplayers)
  {
    text_mode(-1);
    sprintf(m, "Player %-1d", i + 1);
    rectfill(back_buffer, 7, 42 + (40 * i), 103, 58 + (40 * i), BLACK);
    rect(back_buffer, 5, 40 + (40 * i), 105, 60 + (40 * i), DGREY);
    rectfill(back_buffer, 7, 42 + (40 * i), 103, 58 + (40 * i), GREY);
    if (i == selected)
    {
      textout_centre(back_buffer, font, m, 55, 46 + (40 * i), RED);
    }
    else
    {
      textout_centre(back_buffer, font, m, 55, 46 + (40 * i), BLACK);
    }
    create_dirty(BACK, 5, 40 + (40 * i), 100, 20);
    text_mode(0);
    if ((player[i].number > -1) && (player[i].number < 8))
    {
      textout(back_buffer, font, character[player[i].number].name.c_str(), 115, 47 + (40 * i), WHITE);
    }
    create_dirty(BACK, 115, 47 + (40 * i), 120, 20);
    i++;
  }
}

int do_gameoptions()
{
  static int first = 1;
  int moved = mouse_moved();
  static int c;
  static _button back;
  static _button sync;
  static _button buf;
  static _button speed[2];
  static _button vol[2];
  static _button testsound;
  if (first == 1)
  {
    blit((BITMAP*)glb[8].dat, back_buffer, 0, 0, 0, 0, 640, 480);
    c = getpixel(back_buffer, 10, 200);  //get the background color
    back.init(560, 460, 80, 20, "Back");
    if (dovsync == 0)
    {
      sync.init(270, 270, 100, 20, "Vsync: OFF");
    }
    else
    {
      sync.init(270, 270, 100, 20, "Vsync: ON");
    }
    if (dodoublebuffer == 0)
    {
      buf.init(200, 300, 240, 20, "Double buffering: OFF");
    }
    else
    {
      buf.init(200, 300, 240, 20, "Double buffering: ON");
    }
    text_mode(-1);
    textout_centre(back_buffer, font, "Sound Volume", 320, 180, WHITE);
    textprintf_centre(back_buffer, font, 320, 200, WHITE, "%-1d", volume);
    vol[0].init(260, 190, 30, 20, "<");
    vol[1].init(350, 190, 30, 20, ">");
    testsound.init(270, 215, 100, 20, "Test");
    textout_centre(back_buffer, font, "Mouse Speed (Higher value means slower mouse)", 320, 350, WHITE);
    textprintf_centre(back_buffer, font, 320, 380, WHITE, "%-1d", mspeed);
    speed[0].init(270, 370, 30, 20, "<");
    speed[1].init(340, 370, 30, 20, ">");
    text_mode(0);
    back.draw(back_buffer);
    sync.draw(back_buffer);
    buf.draw(back_buffer);
    vol[0].draw(back_buffer);
    vol[1].draw(back_buffer);
    testsound.draw(back_buffer);
    speed[0].draw(back_buffer);
    speed[1].draw(back_buffer);
    create_dirty(BACK, 0, 0, 640, 480);
    moved = 1;
    first = 0;
  }
  back.check(back_buffer, moved);
  sync.check(back_buffer, moved);
  buf.check(back_buffer, moved);
  vol[0].check(back_buffer, moved);
  vol[1].check(back_buffer, moved);
  testsound.check(back_buffer, moved);
  speed[0].check(back_buffer, moved);
  speed[1].check(back_buffer, moved);
  if (sync.clicked() == 1)
  {
    if (dovsync == 0)
    {
      dovsync = 1;
      sync.init(270, 270, 100, 20, "Vsync: ON");
      sync.draw(back_buffer);
    }
    else
    {
      dovsync = 0;
      sync.init(270, 270, 100, 20, "Vsync: OFF");
      sync.draw(back_buffer);
    }
  }
  if (buf.clicked() == 1)
  {
    if (dodoublebuffer == 0)
    {
      dodoublebuffer = 1;
      buf.init(200, 300, 240, 20, "Double buffering: ON");
      buf.draw(back_buffer);
      create_dirty(BACK, 0, 0, 640, 480);
      moved = 1;
    }
    else
    {
      dodoublebuffer = 0;
      buf.init(200, 300, 240, 20, "Double buffering: OFF");
      buf.draw(back_buffer);
    }
  }
  if (testsound.clicked() == 1)
  {
    play_sound(rand()%11);
  }
  if (vol[0].mousedown() == 1)
  {
    if (volume > 0) volume--;
    set_volume(volume, volume);
    rectfill(back_buffer, 301, 200, 339, 210, c);
    text_mode(-1);
    textprintf_centre(back_buffer, font, 320, 200, WHITE, "%-1d", volume);
    text_mode(0);
    create_dirty(BACK, 300, 199, 40, 10);
  }
  if (vol[1].mousedown() == 1)
  {
    if (volume < 255) volume++;
    set_volume(volume, volume);
    rectfill(back_buffer, 301, 200, 339, 210, c);
    text_mode(-1);
    textprintf_centre(back_buffer, font, 320, 200, WHITE, "%-1d", volume);
    text_mode(0);
    create_dirty(BACK, 300, 199, 40, 10);
  }
  if (speed[0].clicked() == 1)
  {
    if (mspeed > 1) mspeed--;
    set_mouse_speed(mspeed, mspeed);
    rectfill(back_buffer, 301, 360, 339, 410, c);
    text_mode(-1);
    textprintf_centre(back_buffer, font, 320, 380, WHITE, "%-1d", mspeed);
    text_mode(0);
    create_dirty(BACK, 310, 379, 20, 10);
  }
  if (speed[1].clicked() == 1)
  {
    if (mspeed < 9) mspeed++;
    set_mouse_speed(mspeed, mspeed);
    rectfill(back_buffer, 301, 360, 339, 410, c);
    text_mode(-1);
    textprintf_centre(back_buffer, font, 320, 380, WHITE, "%-1d", mspeed);
    text_mode(0);
    create_dirty(BACK, 310, 379, 20, 10);
  }
  if (back.clicked() == 1)
  {
    first = 1;
    return FIRST;
  }
  if (moved == 1)
  {
    draw_mouse();
  }
  return GAME_OPTIONS;
}

int do_gameload()
{
  int i, o, p, num, safety;
  int type, tilex, tiley, ammo, gas, ready, capturing, unum;
  float health;
  int moved = mouse_moved();
  int thechoice = -1;
  char text[10];
  char d[30];
  char t[35];
  string mname;
  static int first = 1;
  static _button choice[10];
  static _button delsave[9];
  char path[10];
  if (first == 1)
  {
    blit((BITMAP *)glb[9].dat, back_buffer, 0, 0, 0, 0, 640, 480);
    blit((BITMAP *)glb[10].dat, back_buffer, 0, 0, 0, 0, 302, 49);
    o = 0;
    while (o < 9)
    {
      sprintf(path, "game%-1d.sav", o);
      ifstream n(path);
      if (n.bad())
      {
        choice[o].init(210, 80 + (o * 35), 140, 20, "Empty");
      }
      else
      {
        n >> text;
        choice[o].init(210, 80 + (o * 35), 140, 20, text);
      }
      choice[o].draw(back_buffer);
      delsave[o].init(375, 82 + (o * 35), 80, 16, "Delete");
      delsave[o].draw(back_buffer);
      o++;
    }
    moved = 1;
    choice[9].init(250, 455, 140, 20, "Back");
    choice[9].draw(back_buffer);
    create_dirty(BACK, 0, 0, 640, 480);
    first = 0;
  }
  i = 0;
  while (i < 10)
  {
    choice[i].check(back_buffer, moved);
    if (choice[i].clicked() == 1)
    {
      thechoice = i;
    }
    if (i < 9)
    {
      delsave[i].check(back_buffer, moved);
      if (delsave[i].clicked() == 1)
      {  //if the delete option was chosen for this save file
        sprintf(path, "game%-1d.sav", i);
        delete_file(path);
        choice[i].init(210, 80 + (i * 35), 140, 20, "Empty");
        choice[i].draw(back_buffer);
      }
    }
    i++;
  }
  if ((thechoice != -1) && (thechoice != 9))
  {
    sprintf(path, "game%-1d.sav", thechoice);
    ifstream savefile(path);
    if (!(savefile.bad()))
    {
      savefile >> d >> l >> h;
      o = 0;
      while (o < h)
      {
        p = 0;
        while (p < l)
        {
          savefile >> map[p][o];
          p++;
        }
        o++;
      }
      clear_unitmap();
      safety = 0;
      o = 0;
      while (o < 4)
      {
        player[o].clear_units();
        savefile >> d >> player[o].playing;
        if (player[o].playing == 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;
          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;
            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;
            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;
            savefile >> d >> player[o].unit[num].moving_towards;
            p++;
          }
        }
        o++;
      }
      savefile >> d >> pturn >> aiprofile;
      getline(savefile, mname);  //this first one makes mname empty for some reason
      getline(savefile, mname);  //so I have to call it again to actually get the line
      sprintf(mapname, mname.c_str());
      load_custom_ai(mname);
      loaded_game = 1;  //the game has been loaded from a file
      first = 1;
      get_connected_beaches();
      very_first_turn == 1;
      return LOGIC;
    }
  }
  else if (thechoice == 9)
  {
    first = 1;
    return FIRST;
  }
  if (moved == 1)
  {
    draw_mouse();
  }
  return GAME_LOAD;
}

void load_custom_ai(string mname)
{
  int i;
  char na[30];
  mname = "ai/" + mname;
  mname += ".txt";  //mname ends up being 'ai/<name of map>.txt'
  ifstream customai(mname.c_str());
  if (!(customai.bad()))
  {  //if a custom ai profile was found for this map
    aiprofile = CUSTOM;  //set aiprofile to use the custom profile
    i = 0;
    while (i < 18)  //then read in the custom ai profile from
    {               //the text file that was specified by mname
      customai >> na >> na >> build[CUSTOM][i].weight >> na >> build[CUSTOM][i].limit;
      i++;
    }
  }
}

void get_connected_beaches()
{
  int x, y, z;
  _loc d;
  beaches.clear();
  beaches.reserve(5);
  y = 0;
  while (y < h)
  {
    x = 0;
    while (x < l)
    {
      if (is_beach(x, y) == 1)
      {
        if (beach_already_listed(x, y) == 0)
        {
          d.x = x;
          d.y = y;
          beaches.push_back();
          beaches[beaches.size() - 1].loc.reserve(10);
          beaches[beaches.size() - 1].loc.push_back(d);
          add_surrounding_beaches(beaches.size() - 1, x, y);
        }
      }
      x++;
    }
    y++;
  }
}

void add_surrounding_beaches(int bnum, int x, int y)
{
  _loc d;
  if (x - 1 > -1)
  {
    if (is_beach(x - 1, y) == 1)
    {
      if (beach_already_listed(x - 1, y) == 0)
      {
        d.x = x - 1;
        d.y = y;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x - 1, y);
      }
    }
  }
  if (x + 1 < l)
  {
    if (is_beach(x + 1, y) == 1)
    {
      if (beach_already_listed(x + 1, y) == 0)
      {
        d.x = x + 1;
        d.y = y;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x + 1, y);
      }
    }
  }
  if (y - 1 > -1)
  {
    if (is_beach(x, y - 1) == 1)
    {
      if (beach_already_listed(x, y - 1) == 0)
      {
        d.x = x;
        d.y = y - 1;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x, y - 1);
      }
    }
  }
  if (y + 1 < h)
  {
    if (is_beach(x, y + 1) == 1)
    {
      if (beach_already_listed(x, y + 1) == 0)
      {
        d.x = x;
        d.y = y + 1;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x, y + 1);
      }
    }
  }  
}

int is_beach(int x, int y)
{
  int z;
  if (get_set(map[x][y]) == 3)
  {  //3 is the set for beaches (called shoals in mapedit)
    return 1;
  }
  z = building_here(x, y);
  if (z != -1)
  {
    z -= 4;  //get rid of capitals
    if (z / 5 == 3)  //if it's a port, they also count
    {
      return 1;
    }
  }
  return 0;
}

int beach_already_listed(int x, int y)
{
  int i, j;
  _loc d;
  d.x = x;
  d.y = y;
  i = 0;
  while (i < beaches.size())
  {
    j = 0;
    while (j < beaches[i].loc.size())
    {
      if ((d.x == beaches[i].loc[j].x) && (d.y == beaches[i].loc[j].y))
      {
        return 1;
      }
      j++;
    }
    i++;
  }
  return 0;
}
