// [-----] [      ] [---] [--v--] [---] [-----]
// |       |\    /| |   |    |    |   | |
// |       | \  / | |   |    |    |   | |
// >----   |  \/  | [---]    |    [\--] >----
// |       |      | |        |    | \   |
// |       |      | |        |    |  \  |
// [-----] []    [] []    [--^--] [] [] [-----]
// 
// [-----] []      []      [-----] [-----] [---] [-----]
// |     | |       |       |       |       |   | |     |
// |     | |       |       |       |       |   | |     |
// >-----< |       |       >----   | <---] [\--] |     |
// |     | |       |       |       |     | | \   |     |
// |     | |       |       |       |     | |  \  |     |
// []   [] [-----] [-----] [-----] [-----] [] [] [-----]
// 
//     /| |\   |    /  /| |\    |  /-- /---
//    / | | \  |   /  / | | \   | /    |
//   /--| |  | |  /  /--| |  \  | |    |--
//  /   | | /  | /  /   | |   \ | \    |
// /    | |/   |/  /    | |    \|  \-- \---
//
//    BY KENT DEVILLAFRANCA


#include "empire.h"

volatile int counter;
char msg[30];
int loaded_game;
int gamestatus;
int dirtyrects;
int scroll_x;
int scroll_y;
int dovsync;
int dodoublebuffer;
int mspeed;
int volume;
int aiprofile;

extern _player player[4];

_character character[8];
vector<_dirtyrect> dirty;

BITMAP *back_buffer;
BITMAP *sprite_buffer;
BITMAP *mouse_buffer;
BITMAP *mouse_bitmap;
BITMAP *double_buffer;
BITMAP *unittemp;
BITMAP *player_bitmap[8];
DATAFILE *graphics;
DATAFILE *units;
DATAFILE *sounds;
DATAFILE *explosions;
DATAFILE *p[4];
DATAFILE *tiles;
DATAFILE *mouse;
DATAFILE *title;
DATAFILE *land;
DATAFILE *river;
DATAFILE *sea;
DATAFILE *shoal;
DATAFILE *buildings;
DATAFILE *mapunits;
DATAFILE *darkunits;
DATAFILE *powered_overlay;

extern void draw_tiles(int scrollx, int scrolly, int editing);
extern void draw_tile(int set, int pic, int x, int y);
extern void animate_units(int forced);
void draw_dirty();

int logic();
int menu();
int mapedit();
int show_winner();
void clear_unitmap();
void clear_dirty_rects();
void trim_dirty_rect_to_screen(int i);
void sort_dirty_rects();
void mergesort_dirty_rects(int min, int max);
void save_debug_info();
void save_pathmap_info();
void save_unitmap_info();

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

int main()
{
  int defaultgfx = 0;
  int modestried = 0;
  int goodmode = 0;
  int i = 0;
  char na[30];
  srand(time(NULL));
  set_color_depth(24);
  LOCK_VARIABLE(counter);
  LOCK_FUNCTION(timer_handler);
  LOCK_VARIABLE(fps_counter);
  LOCK_FUNCTION(fps_handler);
  allegro_init();
  install_keyboard();
  install_timer();
  install_mouse();
  install_int_ex(timer_handler, BPS_TO_TIMER(50));
  ifstream opt("empire.ini");
  if (opt.bad())
  {
    dovsync = 0;
    mspeed = 2;
    volume = 192;
    defaultgfx = 0;
    dodoublebuffer = 0;
  }
  else
  {
    opt >> dovsync;
    opt >> mspeed;
    opt >> volume;
    opt >> defaultgfx;
    opt >> dodoublebuffer;
  }
  ifstream landai("ai/land.txt");
  if (landai.bad())
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to open ai/land.txt\n%s\n", allegro_error);
    return 1; 
  }
  else
  {
    i = 0;
    while (i < 18)
    {
      landai >> na >> na >> build[LAND][i].weight >> na >> build[LAND][i].limit;
      i++;
    }
  }
  ifstream seaai("ai/sea.txt");
  if (seaai.bad())
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to open ai/sea.txt\n%s\n", allegro_error);
    return 1; 
  }
  else
  {
    i = 0;
    while (i < 18)
    {
      seaai >> na >> na >> build[SEA][i].weight >> na >> build[SEA][i].limit;
      i++;
    }
  }
  ifstream airai("ai/air.txt");
  if (airai.bad())
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to open ai/air.txt\n%s\n", allegro_error);
    return 1; 
  }
  else
  {
    i = 0;
    while (i < 18)
    {
      airai >> na >> na >> build[AIR][i].weight >> na >> build[AIR][i].limit;
      i++;
    }
  }  
  while ((modestried < 4) && (goodmode == 0))
  {
    if (defaultgfx == 0)
    {
      if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0) != 0)
      {
        defaultgfx = 1;
      }
      else
      {
        goodmode = 1;
      }
      modestried++;
    }
    if (defaultgfx == 1)
    {
      set_color_depth(15);
      if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0) != 0)
      {
        defaultgfx = 2;
      }
      else
      {
        goodmode = 1;
      }
      modestried++;
    }
    if (defaultgfx == 2)
    {
      set_color_depth(16);
      if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0) != 0)
      {
        defaultgfx = 3;
      }
      else
      {
        goodmode = 1;
      }
      modestried++;
    }
    if (defaultgfx == 3)
    {
      set_color_depth(32);
      if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0) != 0)
      {
        defaultgfx = 0;
      }
      else
      {
        goodmode = 1;
      }
      modestried++;
    }
  }
  if (goodmode == 0)
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
    return 1;
  }
  textout(screen, font, "LOADING...", 5, 5, WHITE);
  if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL) != 0)
  {
    allegro_message("Error initialising sound\n%s\n", allegro_error);
    install_sound(DIGI_NONE, MIDI_NONE, NULL);
  }
  graphics = load_datafile("empire.dat");
  if (!graphics)
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to load empire.dat\n%s\n", allegro_error);
    return 1;
  }
  tiles = (DATAFILE *)graphics[0].dat;
  land = (DATAFILE *)tiles[0].dat;
  river = (DATAFILE *)tiles[1].dat;
  sea = (DATAFILE *)tiles[2].dat;
  shoal = (DATAFILE *)tiles[3].dat;
  buildings = (DATAFILE *)tiles[4].dat;
  mapunits = (DATAFILE *)tiles[5].dat;
  darkunits = (DATAFILE *)tiles[6].dat;
  mouse = (DATAFILE *)graphics[1].dat;
  title = (DATAFILE *)graphics[2].dat;
  explosions = (DATAFILE *)graphics[4].dat;
  units = load_datafile("units.dat");
  if (!units)
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to load units.dat\n%s\n", allegro_error);
    return 1;
  }
  p[0] = (DATAFILE *)units[0].dat;
  p[1] = (DATAFILE *)units[1].dat;
  p[2] = (DATAFILE *)units[2].dat;
  p[3] = (DATAFILE *)units[3].dat;
  powered_overlay = (DATAFILE *)units[5].dat;
  sounds = load_datafile("empfx.dat");
  if (!sounds)
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to load empfx.dat\n%s\n", allegro_error);
    return 1;
  }  
  ifstream playerdat("players.dat");
  if (playerdat.bad())
  {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Unable to load players.dat\n%s\n", allegro_error);
    return 1;
  }
  string a[8], b[8], c[8], d[8], e[8], f[8];
  i = 0;
  while (i < 8)
  {
    getline(playerdat, a[i]);
    getline(playerdat, b[i]);
    getline(playerdat, c[i]);
    getline(playerdat, d[i]);
    getline(playerdat, e[i]);
    getline(playerdat, f[i]);
    i++;
  }
  playerdat.close();
  char blah[3];
  string thepath;
  BITMAP *temp[8];
  PALETTE q;
  i = 0;
  while (i < 8)
  {
    thepath = "player";
    sprintf(blah, "%-1d", i + 1);
    thepath += blah;
    thepath += ".bmp";
    temp[i] = load_bitmap(thepath.c_str(), q);
    if (!temp[i])
    {
      temp[i] = create_bitmap(80, 80);
      clear_to_color(temp[i], LGREY);
    }
    character[i].create(a[i], b[i], int(strtol(c[i].c_str(), NULL, 10)), int(strtol(d[i].c_str(), NULL, 10)), int(strtol(e[i].c_str(), NULL, 10)), f[i], temp[i]);
    i++;
  }
  i = 0;
  while (i < 8)
  {
    destroy_bitmap(temp[i]);
    i++;
  }
  BITMAP *tempbmp = create_bitmap(640, 480);
  set_volume(volume, volume);
  set_mouse_speed(mspeed, mspeed);
  back_buffer = create_bitmap(640, 480);
  sprite_buffer = create_bitmap(640, 480);
  mouse_buffer = create_bitmap(640, 480);
  double_buffer = create_bitmap(640, 480);
  mouse_bitmap = (BITMAP *)mouse[0].dat;
  clear_to_color(back_buffer, BLACK);
  clear_to_color(sprite_buffer, TRANS);
  clear_to_color(mouse_buffer, TRANS);
  clear_to_color(double_buffer, BLACK);
  unittemp = create_bitmap(40, 40);
  set_trans_blender(192, 192, 192, 192);
  gamestatus = MENU;
  counter = 0;
  dirtyrects = 0;
  scroll_x = 0;
  scroll_y = 0;
  while (gamestatus != QUIT)
  {
    while (counter > 0)
    {
      if (key[KEY_B])
      {
        gamestatus = QUIT;
      }
      switch(gamestatus)
      {
        case MENU:
          gamestatus = menu();
          break;
        case LOGIC:
          gamestatus = logic();
          break;
        case GAMEOVER:
          gamestatus = show_winner();
          break;
        case MAPEDIT:
          gamestatus = mapedit();
          break;
      }
      counter--;
    }
    if (key[KEY_R])
    {  //completely refreshes the screen
      clear_dirty_rects();
      create_dirty(BACK, 0, 0, 640, 480);
      create_dirty(SPRITE, 0, 0, 640, 480);
      draw_mouse();
    }
    if (dirty.size() > 40)
    {  //if there's more than 40 dirty rectangles, just redraw everything
      clear_dirty_rects();
      create_dirty(BACK, 0, 0, 640, 480);
      create_dirty(SPRITE, 0, 0, 640, 480);
      draw_mouse();
    }
    sort_dirty_rects();
    if (dovsync == 1)
    {
      vsync();
    }    
    draw_dirty();
    if (key[KEY_F12])
    {
      blit(back_buffer, tempbmp, 0, 0, 0, 0, 640, 480);
      masked_blit(sprite_buffer, tempbmp, 0, 0, 0, 0, 640, 480);
      masked_blit(mouse_buffer, tempbmp, 0, 0, 0, 0, 640, 480);
      save_bitmap("scrngrab.bmp", tempbmp, NULL);
    }
    if (key[KEY_D])
    {
      save_debug_info();
    }
    if (key[KEY_P])
    {
      save_pathmap_info();
    }
    if (key[KEY_U])
    {
      save_unitmap_info();
    }
    yield_timeslice();
  }
  i = 0;
  while (i < 8)
  {
    character[i].destroy();
    i++;
  }
  ofstream settings("empire.ini");
  if (!(settings.bad()))
  {
    settings << dovsync << "\n" << mspeed << "\n" << volume << "\n" << defaultgfx << "\n" << dodoublebuffer;
    settings.close();
  }
  destroy_bitmap(back_buffer);
  destroy_bitmap(sprite_buffer);
  destroy_bitmap(mouse_buffer);
  destroy_bitmap(double_buffer);
  destroy_bitmap(tempbmp);
  destroy_bitmap(unittemp);
  unload_datafile(graphics);
  unload_datafile(units);
  unload_datafile(sounds);
  allegro_exit();
  return 0;
}
END_OF_MAIN();





void create_dirty(int buffnum, int x, int y, int w, int h)
{
  int z;
  dirty.push_back();
  z = dirty.size();
  z--;
  dirty[z].x = x;
  dirty[z].y = y;
  dirty[z].w = w;
  dirty[z].h = h;
  dirty[z].buffer = buffnum;
}





void draw_dirty()
{
  int i;  //dirty rects are sorted so they are drawn in this order:
  i = 0;  //back buffer, sprite buffer, mouse buffer
  while (i < dirty.size())
  {
    trim_dirty_rect_to_screen(i);
    if ((dirty[i].w > 1) || (dirty[i].h > 1))
    {
      if (dirty[i].buffer == BACK)
      {
        if (dodoublebuffer == 1)
        {
          blit(back_buffer, double_buffer, dirty[i].x, dirty[i].y, dirty[i].x, dirty[i].y, dirty[i].w, dirty[i].h);
        }
        else
        {
          blit(back_buffer, screen, dirty[i].x, dirty[i].y, dirty[i].x, dirty[i].y, dirty[i].w, dirty[i].h);
        }
      }
      else if (dirty[i].buffer == SPRITE)
      {
        if (dodoublebuffer == 1)
        {
          masked_blit(sprite_buffer, double_buffer, dirty[i].x, dirty[i].y, dirty[i].x, dirty[i].y, dirty[i].w, dirty[i].h);
        }
        else
        {
          masked_blit(sprite_buffer, screen, dirty[i].x, dirty[i].y, dirty[i].x, dirty[i].y, dirty[i].w, dirty[i].h);
        }
      }
      else if (dirty[i].buffer == MOUSE)
      {
        if (dodoublebuffer == 1)
        {
          masked_blit(mouse_buffer, double_buffer, dirty[i].x, dirty[i].y, dirty[i].x, dirty[i].y, dirty[i].w, dirty[i].h);
        }
        else
        {
          masked_blit(mouse_buffer, screen, dirty[i].x, dirty[i].y, dirty[i].x, dirty[i].y, dirty[i].w, dirty[i].h);
        }
      }
    }
    else if ((dirty[i].w == 1) && (dirty[i].h == 1))
    {
      if (dirty[i].buffer == BACK)
      {
        if (dodoublebuffer == 1)
        {
          putpixel(double_buffer, dirty[i].x, dirty[i].y, getpixel(back_buffer, dirty[i].x, dirty[i].y));
        }
        else
        {
          putpixel(screen, dirty[i].x, dirty[i].y, getpixel(back_buffer, dirty[i].x, dirty[i].y));
        }
      }
      else if (dirty[i].buffer == SPRITE)
      {
        if (getpixel(sprite_buffer, dirty[i].x, dirty[i].y) != TRANS)
        {
          if (dodoublebuffer == 1)
          {
            putpixel(double_buffer, dirty[i].x, dirty[i].y, getpixel(sprite_buffer, dirty[i].x, dirty[i].y));
          }
          else
          {
            putpixel(screen, dirty[i].x, dirty[i].y, getpixel(sprite_buffer, dirty[i].x, dirty[i].y));
          }
        }
      }
      else if (dirty[i].buffer == MOUSE)
      {
        if (dodoublebuffer == 1)
        {
          putpixel(double_buffer, dirty[i].x, dirty[i].y, getpixel(mouse_buffer, dirty[i].x, dirty[i].y));
        }
        else
        {
          putpixel(screen, dirty[i].x, dirty[i].y, getpixel(mouse_buffer, dirty[i].x, dirty[i].y));
        }
      }
    }
    i++;
  }
  if (dodoublebuffer == 1)
  {
    blit(double_buffer, screen, 0, 0, 0, 0, 640, 480);
  }
  dirty.clear();
}





int mouse_moved()
{
  static int mx = 0;
  static int my = 0;
  if ((mx != mouse_x) || (my != mouse_y))
  {
    mx = mouse_x;
    my = mouse_y;
    return 1;
  }
  return 0;
}





int mouse_clicked()
{
  static int mousedown = 0;
  if (mouse_b & 1)
  {
    mousedown = 1;
  }
  else
  {
    if (mousedown == 1)
    {
      mousedown = 0;
      return 1;
    }
  }
  return 0;
}





int mouse_rclicked()
{
  static int mousedown = 0;
  if (mouse_b & 2)
  {
    mousedown = 1;
  }
  else
  {
    if (mousedown == 1)
    {
      mousedown = 0;
      return 1;
    }
  }
  return 0;
}





void draw_mouse()
{
  static int old_mouse_x = 0;
  static int old_mouse_y = 0;
  rectfill(mouse_buffer, old_mouse_x, old_mouse_y, old_mouse_x + 15, old_mouse_y + 15, TRANS);
  create_dirty(BACK, old_mouse_x, old_mouse_y, 15, 15);   //restore the buffers the
  create_dirty(SPRITE, old_mouse_x, old_mouse_y, 15, 15); //mouse previously covered
  old_mouse_x = mouse_x;
  old_mouse_y = mouse_y;
  draw_sprite(mouse_buffer, mouse_bitmap, old_mouse_x, old_mouse_y);
  create_dirty(MOUSE, old_mouse_x, old_mouse_y, 15, 15);
}





void clear_unitmap()
{
  int i = 0;
  int j;
  while (i < 50)
  {
    j = 0;
    while (j < 50)
    {
      unitmap[j][i] = -1;
      j++;
    }
    i++;
  }
}





void clear_dirty_rects()
{
  dirty.clear();
}





void trim_dirty_rect_to_screen(int i)
{
  if (dirty[i].x < 0)
  {
    dirty[i].w += dirty[i].x;
    dirty[i].x = 0;
  }
  if (dirty[i].y < 0)
  {
    dirty[i].h += dirty[i].y;
    dirty[i].y = 0;
  }
  if (dirty[i].x + dirty[i].w > 639)
  {
    dirty[i].w += 639 - (dirty[i].x + dirty[i].w);
  }
  else if (dirty[i].x + dirty[i].w < 0)
  {
    dirty[i].w = 0;  //keep it from being drawn if not on screen
  }
  if (dirty[i].y + dirty[i].h > 479)
  {
    dirty[i].h += 479 - (dirty[i].y + dirty[i].h);
  }
  else if (dirty[i].y + dirty[i].h < 0)
  {
    dirty[i].h = 0;
  }
}





void sort_dirty_rects()
{
  if (dirty.size() > 0)
  {
    mergesort_dirty_rects(0, dirty.size() - 1);
  }
}





void mergesort_dirty_rects(int min, int max)
{
  vector<_dirtyrect> temp;
  int left, right, size, i, pivot, a, b;
  size = max - min + 1;
  pivot = (min + max) / 2;
  temp.clear();
  if (min == max)
  {
    return;
  }
  mergesort_dirty_rects(min, pivot);
  mergesort_dirty_rects(pivot + 1, max);
  i = 0;
  while (i < size)
  {
    temp.push_back(dirty[min + i]);
    i++;
  }
  left = 0;
  right = pivot - min + 1;
  i = 0;
  while (i < size)
  {
    if (right <= max - min)
    {
      if (left <= pivot - min)
      {
        a = temp[left].buffer;
		b = temp[right].buffer;
        if (a > b)
        {
          dirty[i + min] = temp[right];
          right++;
        }
        else
        {
          dirty[i + min] = temp[left];
          left++;
        }
      }
      else
      {
        dirty[i + min] = temp[right];
        right++;
      }
    }
    else
    {
      dirty[i + min] = temp[left];
      left++;
    }
    i++;
  }
}





int show_winner()
{
  DATAFILE *glb = (DATAFILE *)graphics[2].dat;
  static int first = -20;
  static int color;
  int winner;
  int i;
  if (first < 1)
  {
    animate_units(0);  //let the units finish up any remaining actions
    first++;
  }
  else if (first < 50)
  {
    if (first % 2 == 0)
    {
      create_dirty(BACK, 0, 0, 640, 480);
    }
    first++;
  }
  else if (first == 50)
  {
    i = 0;
    while (i < 4)
    {
      if (player[i].playing == 1)
      {  //by this time, only one player will be left playing
        winner = i;
        i = 4;
      }
      i++;
    }
    switch(winner)
    {
      case 0:
        color = RED;
        break;
      case 1:
        color = BLUE;
        break;
      case 2:
        color = DGREEN;
        break;
      case 3:
        color = DYELLOW;
        break;
    }
    text_mode(-1);
    textprintf_centre(back_buffer, (FONT *)glb[2].dat, 319, 230, WHITE, "Player %-1d Wins!", winner + 1);
    textprintf_centre(back_buffer, (FONT *)glb[2].dat, 321, 230, WHITE, "Player %-1d Wins!", winner + 1);
    textprintf_centre(back_buffer, (FONT *)glb[2].dat, 320, 230, color, "Player %-1d Wins!", winner + 1);
    textout_centre(back_buffer, font, "Press Enter", 320, 400, BLACK);
    text_mode(0);
    rectfill(sprite_buffer, 0, 0, 640, 480, TRANS);
    create_dirty(BACK, 0, 0, 640, 480);
    play_sound(VICTORY);
    first = 51;
  }
  else if (key[KEY_ENTER])
  {
    set_mouse_range(0, 0, 639, 479);
    position_mouse(320, 240);
    first = -20;
    return MENU;
  }
  return GAMEOVER;
}

void play_sound(int soundtype)
{
  play_sample((SAMPLE *)sounds[soundtype].dat, volume, 128, 1000, FALSE);
}

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

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

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