package dev.llan.model.board;
import dev.llan.model.board.Tile.TileType;
import java.util.ArrayList;
import java.util.List;
public class Grid implements Cloneable {
private Tile[][] map;
private int rowSize;
private int colSize;
public Grid(int size) {
this(size, size, true);
}
public Grid(int rowSize, int colSize, boolean init) {
this.rowSize = rowSize;
this.colSize = colSize;
this.map = new Tile[rowSize][colSize];
if (init) {
for (int row = 0; row < rowSize; row++) {
initRow(row);
}
}
}
public void setGrid(Tile[][] newMap) {
this.map = newMap;
}
private void initRow(int row) {
for (int col = 0; col < colSize; col++) {
map[row][col] = new Tile(new Point(row, col), Tile.TileType.VACANT);
}
}
public int getRowSize() {
return rowSize;
}
public int getColSize() {
return colSize;
}
public boolean validPosition(Point position) {
int row = position.getRow();
int col = position.getCol();
if (withinIndices(row, rowSize) && withinIndices(col, colSize)) {
return tileAt(position).getType() == TileType.VACANT;
}
return false;
}
public boolean attackablePosition(Point position) {
int row = position.getRow();
int col = position.getCol();
if (withinIndices(row, rowSize) && withinIndices(col, colSize)) {
return tileAt(position).getType() != TileType.UNMOVABLE;
}
return false;
}
public double getMovementCost(Point neighbor, Point parent) {
Tile neighborTile = tileAt(neighbor);
double baseCost = neighborTile.getTerrainCost();
int dRow = Math.abs(neighbor.getRow() - parent.getRow());
int dCol = Math.abs(neighbor.getCol() - parent.getCol());
return baseCost * Math.sqrt(dRow * dRow + dCol * dCol);
}
private boolean withinIndices(int index, int maxIndex) {
return 0 <= index && index < maxIndex;
}
public Tile tileAt(Point position) {
return map[position.getRow()][position.getCol()];
}
public void updateVisibilities(Point center, double radius) {
this.tileAt(center).setVisible(true);
List<Point> potentialPoints = withinSquare(center, radius);
for (Point point : potentialPoints) {
if (Point.getDistance(center, point) <= radius) {
this.tileAt(point).setVisible(true);
}
}
}
private List<Point> withinSquare(Point center, double radius) {
List<Point> points = new ArrayList<>();
int maxRadius = (int) Math.ceil(radius);
int row = center.getRow();
int col = center.getCol();
for (int dRow = -maxRadius; dRow <= maxRadius; dRow++) {
for (int dCol = -maxRadius; dCol <= maxRadius; dCol++) {
if (dRow == 0 && dCol == 0) continue;
int newRow = row + dRow;
int newCol = col + dCol;
if (withinIndices(newRow, rowSize) && withinIndices(newCol, colSize)) {
Point point = new Point(newRow, newCol);
points.add(point);
}
}
}
return points;
}
@Override
protected Grid clone() {
Grid clone = new Grid(this.rowSize, this.colSize, false);
for (int row = 0; row < this.rowSize; row++) {
for (int col = 0; col < this.colSize; col++) {
clone.map[row][col] = this.map[row][col].clone();
}
}
return clone;
}
}