void GameLoaderC3Map::Impl::loadCity(std::fstream& f, CityPtr oCity)
{
  Tilemap& oTilemap = oCity->getTilemap();

  /* get number of city */

  f.seekg(kLocation, std::ios::beg);
  unsigned int location=0;
  f.read((char*)&location, 1);
  StringHelper::debug( 0xff, "Location of city is %d", (int)(location+1) );

  std::string cityName = "";
  switch( location+1 ) {
    case 1: case 29: cityName = "Lugdunum"; break;
    case 2: cityName = "Corinthus"; break;
    case 3: case 37: cityName = "Londinium"; break;
    case 4: case 13: case 28: cityName = "Mediolanum"; break;
    case 5: case 40: cityName = "Lindum"; break;
    case 6: cityName = "Toletum"; break;
    case 7: case 33: cityName = "Valentia"; break;
    case 8: case 35: cityName = "Caesarea"; break;
    case 9: case 30: cityName = "Carthago"; break;
    case 10: cityName = "Cyrene"; break;
    case 11: case 15: case 25: cityName = "Tarraco"; break;
    case 12: cityName = "Hierosolyma"; break;
    case 14: case 26: cityName = "Syracusae"; break;
    case 16: case 31: cityName = "Tarsus"; break;
    case 17: case 32: cityName = "Tingis"; break;
    case 18: cityName = "Augusta Trevorum"; break;
    case 19: cityName = "Carthago Nova"; break;
    case 20: cityName = "Leptis Magna"; break;
    case 21: cityName = "Athenae"; break;
    case 22: cityName = "Brundisium"; break;
    case 23: cityName = "Capua"; break;
    case 24: cityName = "Tarentum"; break;
    case 27: cityName = "Miletus"; break;
    case 34: cityName = "Lutetia"; break;
    case 36: cityName = "Sarmizegetusa"; break;
    case 38: cityName = "Damascus"; break;
    case 39: cityName = "Massilia"; break;
  }

  oCity->setName( cityName );

  f.seekg(kSize, std::ios::beg);

  int size;  // 32bits
  int size_2;
  f.read((char*)&size,   4);
  f.read((char*)&size_2, 4);
  StringHelper::debug( 0xff, "Map size is %d", size );

  if (size != size_2)
  {
    THROW("Horisontal and vertical map sizes are different!");
  }

  oTilemap.resize(size);

  // need to rewrite better
  ScopedPtr<short> pGraphicGrid( new short[26244] );
  ScopedPtr<unsigned char> pEdgeGrid( new unsigned char[26244] );
  ScopedPtr<short> pTerrainGrid( new short[26244] );
  ScopedPtr<unsigned char> pRndmTerGrid( new unsigned char[26244] );
  ScopedPtr<unsigned char> pRandomGrid( new unsigned char[26244] );
  ScopedPtr<unsigned char> pZeroGrid( new unsigned char[26244] );
  
  if( pGraphicGrid.isNull() || pEdgeGrid.isNull() || pTerrainGrid.isNull() ||
      pRndmTerGrid.isNull() || pRandomGrid.isNull() || pZeroGrid.isNull() )
  {
    THROW("NOT ENOUGH MEMORY!!!! FATAL");
  }  
  
  // here also make copy of original arrays in memory

  f.seekg(kGraphicGrid, std::ios::beg);
  f.read((char*)pGraphicGrid.data(), 52488);
  f.seekg(kEdgeGrid, std::ios::beg);
  f.read((char*)pEdgeGrid.data(), 26244);
  f.seekg(kTerrainGrid, std::ios::beg);
  f.read((char*)pTerrainGrid.data(), 52488);
  f.seekg(kRndmTerGrid, std::ios::beg);
  f.read((char*)pRndmTerGrid.data(), 26244);
  f.seekg(kRandomGrid, std::ios::beg);
  f.read((char*)pRandomGrid.data(), 26244);
  f.seekg(kZeroGrid, std::ios::beg);
  f.read((char*)pZeroGrid.data(), 26244);

  std::map< int, std::map< int, unsigned char > > edgeData;

  // loads the graphics map
  int border_size = (162 - size) / 2;

  for (int itA = 0; itA < size; ++itA)
  {
    for (int itB = 0; itB < size; ++itB)
    {
      int i = itB;
      int j = size - itA - 1;

      int index = 162 * (border_size + itA) + border_size + itB;  

      Tile& tile = oTilemap.at(i, j);
      tile.setPicture( TileHelper::convId2PicName( pGraphicGrid.data()[index] ) );
      tile.setOriginalImgId( pGraphicGrid.data()[index] );

      edgeData[ i ][ j ] =  pEdgeGrid.data()[index];
      TileHelper::decode( tile, pTerrainGrid.data()[index] );
    }    
  }

  for (int i = 0; i < size; ++i)
  {
    for (int j = 0; j < size; ++j)
    {
      unsigned char ed = edgeData[ i ][ j ];
      if( ed == 0x00)
      {
        int size = 1;

	      {
	        int dj;
	        try
	        {	
	          // find size, 5 is maximal size for building
	          for (dj = 0; dj < 5; ++dj)
	          {
							int edd = edgeData[ i ][ j - dj ];
	            // find bottom left corner
							if (edd == 8 * dj + 0x40)
	            {
	              size = dj + 1;
	              break;
	            }
	          }
	        }
	        catch(...)
	        {
	          size = dj + 1;
	        }
	      }
	
        StringHelper::debug( 0xff, "Multi-tile x %d at (%d,%d)", size, i, j );
	      	
	      Tile& master = oTilemap.at(i, j - size + 1);
      	
        StringHelper::debug( 0xff, "Master will be at (%d,%d)", master.getI(), master.getJ() );
      	
	      for (int di = 0; di < size; ++di)
        {
	        for (int dj = 0; dj < size; ++dj)
	        {
	            oTilemap.at(master.getI() + di, master.getJ() + dj).setMasterTile(&master);
	        }
        }
    	
        StringHelper::debug( 0xff, " decoding " );
      }
      
      // Check if it is building and type of building
      //if (ttile.getMasterTile() == NULL)
      decodeTerrain( oTilemap.at( i, j ), oCity );
    }
  }
}
void ScenarioMapLoader::Impl::loadMap(std::fstream& f, Scenario& oScenario)
{
  CityPtr oCity = oScenario.getCity();
  Tilemap& oTilemap = oCity->getTilemap();

  /* get number of city */

  f.seekg(kLocation, std::ios::beg);
  unsigned int location=0;
  f.read((char*)&location, 1);
  StringHelper::debug( 0xff, "Location of city is %d", (int)(location+1) );

  std::string cityName = "";
  switch( location+1 ) {
    case 1: case 29: cityName = "Lugdunum"; break;
    case 2: cityName = "Corinthus"; break;
    case 3: case 37: cityName = "Londinium"; break;
    case 4: case 13: case 28: cityName = "Mediolanum"; break;
    case 5: case 40: cityName = "Lindum"; break;
    case 6: cityName = "Toletum"; break;
    case 7: case 33: cityName = "Valentia"; break;
    case 8: case 35: cityName = "Caesarea"; break;
    case 9: case 30: cityName = "Carthago"; break;
    case 10: cityName = "Cyrene"; break;
    case 11: case 15: case 25: cityName = "Tarraco"; break;
    case 12: cityName = "Hierosolyma"; break;
    case 14: case 26: cityName = "Syracusae"; break;
    case 16: case 31: cityName = "Tarsus"; break;
    case 17: case 32: cityName = "Tingis"; break;
    case 18: cityName = "Augusta Trevorum"; break;
    case 19: cityName = "Carthago Nova"; break;
    case 20: cityName = "Leptis Magna"; break;
    case 21: cityName = "Athenae"; break;
    case 22: cityName = "Brundisium"; break;
    case 23: cityName = "Capua"; break;
    case 24: cityName = "Tarentum"; break;
    case 27: cityName = "Miletus"; break;
    case 34: cityName = "Lutetia"; break;
    case 36: cityName = "Sarmizegetusa"; break;
    case 38: cityName = "Damascus"; break;
    case 39: cityName = "Massilia"; break;
  }

  oCity->setName( cityName );

  f.seekg(kSize, std::ios::beg);

  int size;  // 32bits
  int size_2;
  f.read((char*)&size,   4);
  f.read((char*)&size_2, 4);
  StringHelper::debug( 0xff, "Map size is %d", size );

  if (size != size_2)
  {
    THROW("Horisontal and vertical map sizes are different!");
  }

  oTilemap.init(size);

  // need to rewrite better
  short int     *pGraphicGrid = (short int     *)malloc(52488);
  unsigned char *pEdgeGrid    = (unsigned char *)malloc(26244);
  short int     *pTerrainGrid = (short int     *)malloc(52488);
  unsigned char *pRndmTerGrid = (unsigned char *)malloc(26244);
  unsigned char *pRandomGrid  = (unsigned char *)malloc(26244);
  unsigned char *pZeroGrid    = (unsigned char *)malloc(26244);
  
  if( pGraphicGrid == NULL || pEdgeGrid == NULL || pTerrainGrid == NULL ||
      pRndmTerGrid == NULL || pRandomGrid == NULL || pZeroGrid == NULL )
  {
    THROW("NOT ENOUGH MEMORY!!!! FATAL");
  }  
  
  // here also make copy of original arrays in memory

  f.seekg(kGraphicGrid, std::ios::beg);
  f.read((char*)pGraphicGrid, 52488);
  f.seekg(kEdgeGrid, std::ios::beg);
  f.read((char*)pEdgeGrid, 26244);
  f.seekg(kTerrainGrid, std::ios::beg);
  f.read((char*)pTerrainGrid, 52488);
  f.seekg(kRndmTerGrid, std::ios::beg);
  f.read((char*)pRndmTerGrid, 26244);
  f.seekg(kRandomGrid, std::ios::beg);
  f.read((char*)pRandomGrid, 26244);
  f.seekg(kZeroGrid, std::ios::beg);
  f.read((char*)pZeroGrid, 26244);

  // loads the graphics map
  int border_size = (162 - size) / 2;

  for (int itA = 0; itA < size; ++itA)
  {
    for (int itB = 0; itB < size; ++itB)
    {
      int i = itB;
      int j = size - itA - 1;

      int index = 162 * (border_size + itA) + border_size + itB;

      TerrainTile terrain(pGraphicGrid[index],
			  pEdgeGrid[index],
			  pTerrainGrid[index],
			  pRndmTerGrid[index],
			  pRandomGrid[index],
			  pZeroGrid[index]
			  );      
      
      Tile& tile = oTilemap.at(i, j);
      Picture& pic = Picture::load( TerrainTileHelper::convId2PicName( pGraphicGrid[index] ) );
      tile.setPicture( &pic );
      
      tile.getTerrain() = terrain; // what happens here?
    }    
  }

  for (int i = 0; i < size; ++i)
  {
    for (int j = 0; j < size; ++j)
    {
      Tile& tile = oTilemap.at(i, j);
      TerrainTile& terrain = tile.getTerrain();

      if (terrain.getEdgeData()==0x00)
      {
        int size = 1;

	      {
	        int dj;
	        try
	        {	
	          // find size, 5 is maximal size for building
	          for (dj = 0; dj < 5; ++dj)
	          {
	            int edge = oTilemap.at(i, j - dj).getTerrain().getEdgeData();
	            // find bottom left corner
	            if (edge == 8 * dj + 0x40)
	            {
	              size = dj + 1;
	              break;
	            }
	          }
	        }
	        catch(...)
	        {
	          size = dj + 1;
	        }
	      }
	
        StringHelper::debug( 0xff, "Multi-tile x %d at (%d,%d)", size, i, j );
	
	      bool bBad = false;
	
	      //Str << "probing ";
      	
         /* for (int di = 0; di < size && !bBad; ++di)
        {
	        for (int dj = 0; dj < size && !bBad; ++dj)
	        {
	          //std::cout << i - di << "," << j - dj << " ";
	          try
	          {
	            int edge = oTilemap.at(i - di, j - dj).getTerrain().getEdgeData();
	          }
	          catch(...)
	          {
      	      
	          }
      //	    if (edge != 8 * dj + di && edge != 8 * dj + 0x40)
      //	      bBad = true;
	        }
        }*/
	
	//std::cout << std::endl;
	
	      if (bBad)
	        THROW ("ERROR in multi-tiles!!!");
      	
	      Tile& master = oTilemap.at(i, j - size + 1);
      	
        StringHelper::debug( 0xff, "Master will be at (%d,%d)", master.getI(), master.getJ() );
      	
	      for (int di = 0; di < size; ++di)
        {
	        for (int dj = 0; dj < size; ++dj)
	        {
	            oTilemap.at(master.getI() + di, master.getJ() + dj).setMasterTile(&master);
	        }
        }
    	
        StringHelper::debug( 0xff, " decoding " );
      }
      
      TilePos pos( i, j );

      Tile &ttile = oTilemap.at( pos );

      LandOverlayPtr overlay = ttile.getTerrain().getOverlay();

      // Check if it is building and type of building
      //if (ttile.getMasterTile() == NULL)
      decodeTerrain(ttile, oCity );
    }
  }
}