mourning-ember / src / main / java / dev / llan / model / board / Grid.java
Grid.java
Raw
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;
  }
}