// Path: core/src/com/galvarez/ttw/model/data/Empire.java
// public final class Empire extends Component {
// 
//   private static final AtomicInteger COUNTER = new AtomicInteger(0);
// 
//   public final int id;
// 
//   public final Color color;
// 
//   public final Color backColor;
// 
//   public final Culture culture;
// 
//   private final boolean computer;
// 
//   public Empire(Color color, Culture culture, boolean computer) {
//     this.id = COUNTER.getAndIncrement();
//     this.color = color;
//     this.backColor = Colors.contrast(color);
//     this.culture = culture;
//     this.computer = computer;
//   }
// 
//   public boolean isComputerControlled() {
//     return computer;
//   }
// 
//   public Color getColor() {
//     return color;
//   }
// 
//   public Culture getCulture() {
//     return culture;
//   }
// 
//   public String newCityName() {
//     return culture.newCityName();
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (obj == this)
//       return true;
//     else if (obj instanceof Empire)
//       return id == ((Empire) obj).id;
//     else
//       return false;
//   }
// 
//   @Override
//   public int hashCode() {
//     return id;
//   }
// 
//   @Override
//   public String toString() {
//     return culture.name + "(ia=" + computer + ")";
//   }
// 
// }
// 
// Path: core/src/com/galvarez/ttw/utils/MyMath.java
// public class MyMath {
// 	public static int min(int a, int b) {
// 		if (a < b) return a;
// 		return b;
// 	}
// 	
// 	public static int min(int a, int b, int c) {
// 		if (min(a,b) < c) return min(a,b);
// 		return c;
// 	}
// 	
// 	public static int max(int a, int b) {
// 		if (a > b) return a;
// 		return b;
// 	}
// 	
// 	public static int pow(int a, int b) {
// 		if (b > 1) return a*pow(a,b-1);
// 		else return a;
// 	}
// }


import java.util.Collection;
import com.artemis.Entity;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
import com.galvarez.ttw.model.data.Empire;
import com.galvarez.ttw.utils.MyMath;
package com.galvarez.ttw.model.map;



public final class GameMap {

  public final Terrain[][] map;

  private final Entity[][] entityByCoord;

  private final MapPosition[][] posByCoord;

  private final Influence[][] influenceByCoord;

  public final int width, height;

  /** Represents the whole map as a single image. */
  public final Texture texture;

  public final Empire[] empires;

  public GameMap(Terrain[][] map, Collection<Empire> empires) {
    this.map = map;
    this.empires = empires.toArray(new Empire[0]);
    width = map.length;
    height = map[0].length;

    entityByCoord = new Entity[width][height];
    influenceByCoord = new Influence[width][height];
    posByCoord = new MapPosition[width][height];

    Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        MapPosition pos = posByCoord[x][y] = new MapPosition(x, y);
        influenceByCoord[x][y] = new Influence(pos, map[x][y]);
        pixmap.setColor(map[x][y].getColor());
        pixmap.drawPixel(x, y);
      }
    }

    texture = new Texture(pixmap);
    pixmap.dispose();
  }

  public Entity getEntityAt(int x, int y) {
    if (isOnMap(x, y))
      return entityByCoord[x][y];
    else
      return null;
  }

  public Entity getEntityAt(MapPosition pos) {
    return getEntityAt(pos.x, pos.y);
  }

  public boolean hasEntity(MapPosition pos) {
    return getEntityAt(pos) != null;
  }

  public Terrain getTerrainAt(MapPosition pos) {
    return getTerrainAt(pos.x, pos.y);
  }

  public Terrain getTerrainAt(int x, int y) {
    if (isOnMap(x, y))
      return map[x][y];
    else
      throw new IllegalStateException("(" + x + ", " + y + ") is outside map boundaries.");
  }

  public Influence getInfluenceAt(MapPosition pos) {
    return getInfluenceAt(pos.x, pos.y);
  }

  public Influence getInfluenceAt(int x, int y) {
    if (isOnMap(x, y))
      return influenceByCoord[x][y];
    else
      throw new IllegalStateException("(" + x + ", " + y + ") is outside map boundaries.");
  }

  public boolean isOnMap(MapPosition p) {
    return isOnMap(p.x, p.y);
  }

  public boolean isOnMap(int x, int y) {
    return x >= 0 && x < posByCoord.length && y >= 0 && y < posByCoord[0].length;
  }

  public MapPosition getPositionAt(int x, int y) {
    if (isOnMap(x, y))
      return posByCoord[x][y];
    else
      throw new IllegalStateException("(" + x + ", " + y + ") is outside map boundaries.");
  }

  public void setEntity(Entity e, int x, int y) {
    entityByCoord[x][y] = e;
  }

  public void setEntity(Entity e, MapPosition p) {
    setEntity(e, p.x, p.y);
  }

  public void moveEntity(Entity e, MapPosition from, MapPosition to) {
    entityByCoord[from.x][from.y] = null;
    entityByCoord[to.x][to.y] = e;
  }

  public Array<MapPosition> getNeighbors(int x, int y, int n) {
    Array<MapPosition> coordinates = new Array<MapPosition>();
    int min;
    int myrow;
    for (int row = y - n; row < y + n + 1; row++) {
// Path: core/src/com/galvarez/ttw/model/data/Empire.java
// public final class Empire extends Component {
// 
//   private static final AtomicInteger COUNTER = new AtomicInteger(0);
// 
//   public final int id;
// 
//   public final Color color;
// 
//   public final Color backColor;
// 
//   public final Culture culture;
// 
//   private final boolean computer;
// 
//   public Empire(Color color, Culture culture, boolean computer) {
//     this.id = COUNTER.getAndIncrement();
//     this.color = color;
//     this.backColor = Colors.contrast(color);
//     this.culture = culture;
//     this.computer = computer;
//   }
// 
//   public boolean isComputerControlled() {
//     return computer;
//   }
// 
//   public Color getColor() {
//     return color;
//   }
// 
//   public Culture getCulture() {
//     return culture;
//   }
// 
//   public String newCityName() {
//     return culture.newCityName();
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (obj == this)
//       return true;
//     else if (obj instanceof Empire)
//       return id == ((Empire) obj).id;
//     else
//       return false;
//   }
// 
//   @Override
//   public int hashCode() {
//     return id;
//   }
// 
//   @Override
//   public String toString() {
//     return culture.name + "(ia=" + computer + ")";
//   }
// 
// }
// 
// Path: core/src/com/galvarez/ttw/utils/MyMath.java
// public class MyMath {
// 	public static int min(int a, int b) {
// 		if (a < b) return a;
// 		return b;
// 	}
// 	
// 	public static int min(int a, int b, int c) {
// 		if (min(a,b) < c) return min(a,b);
// 		return c;
// 	}
// 	
// 	public static int max(int a, int b) {
// 		if (a > b) return a;
// 		return b;
// 	}
// 	
// 	public static int pow(int a, int b) {
// 		if (b > 1) return a*pow(a,b-1);
// 		else return a;
// 	}
// }


// Path: core/src/com/galvarez/ttw/model/map/GameMap.java
import java.util.Collection;
import com.artemis.Entity;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
import com.galvarez.ttw.model.data.Empire;
import com.galvarez.ttw.utils.MyMath;

package com.galvarez.ttw.model.map;



public final class GameMap {

  public final Terrain[][] map;

  private final Entity[][] entityByCoord;

  private final MapPosition[][] posByCoord;

  private final Influence[][] influenceByCoord;

  public final int width, height;

  /** Represents the whole map as a single image. */
  public final Texture texture;

  public final Empire[] empires;

  public GameMap(Terrain[][] map, Collection<Empire> empires) {
    this.map = map;
    this.empires = empires.toArray(new Empire[0]);
    width = map.length;
    height = map[0].length;

    entityByCoord = new Entity[width][height];
    influenceByCoord = new Influence[width][height];
    posByCoord = new MapPosition[width][height];

    Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        MapPosition pos = posByCoord[x][y] = new MapPosition(x, y);
        influenceByCoord[x][y] = new Influence(pos, map[x][y]);
        pixmap.setColor(map[x][y].getColor());
        pixmap.drawPixel(x, y);
      }
    }

    texture = new Texture(pixmap);
    pixmap.dispose();
  }

  public Entity getEntityAt(int x, int y) {
    if (isOnMap(x, y))
      return entityByCoord[x][y];
    else
      return null;
  }

  public Entity getEntityAt(MapPosition pos) {
    return getEntityAt(pos.x, pos.y);
  }

  public boolean hasEntity(MapPosition pos) {
    return getEntityAt(pos) != null;
  }

  public Terrain getTerrainAt(MapPosition pos) {
    return getTerrainAt(pos.x, pos.y);
  }

  public Terrain getTerrainAt(int x, int y) {
    if (isOnMap(x, y))
      return map[x][y];
    else
      throw new IllegalStateException("(" + x + ", " + y + ") is outside map boundaries.");
  }

  public Influence getInfluenceAt(MapPosition pos) {
    return getInfluenceAt(pos.x, pos.y);
  }

  public Influence getInfluenceAt(int x, int y) {
    if (isOnMap(x, y))
      return influenceByCoord[x][y];
    else
      throw new IllegalStateException("(" + x + ", " + y + ") is outside map boundaries.");
  }

  public boolean isOnMap(MapPosition p) {
    return isOnMap(p.x, p.y);
  }

  public boolean isOnMap(int x, int y) {
    return x >= 0 && x < posByCoord.length && y >= 0 && y < posByCoord[0].length;
  }

  public MapPosition getPositionAt(int x, int y) {
    if (isOnMap(x, y))
      return posByCoord[x][y];
    else
      throw new IllegalStateException("(" + x + ", " + y + ") is outside map boundaries.");
  }

  public void setEntity(Entity e, int x, int y) {
    entityByCoord[x][y] = e;
  }

  public void setEntity(Entity e, MapPosition p) {
    setEntity(e, p.x, p.y);
  }

  public void moveEntity(Entity e, MapPosition from, MapPosition to) {
    entityByCoord[from.x][from.y] = null;
    entityByCoord[to.x][to.y] = e;
  }

  public Array<MapPosition> getNeighbors(int x, int y, int n) {
    Array<MapPosition> coordinates = new Array<MapPosition>();
    int min;
    int myrow;
    for (int row = y - n; row < y + n + 1; row++) {
      min = MyMath.min(2 * (row - y + n), n, -2 * (row - y - n) + 1);