mourning-ember / src / main / java / dev / llan / model / pieces / enemies / BaseEnemy.java
BaseEnemy.java
Raw
package dev.llan.model.pieces.enemies;

import dev.llan.model.board.GameMap;
import dev.llan.model.board.Grid;
import dev.llan.model.board.Point;
import dev.llan.model.board.pathfinding.Path;
import dev.llan.model.cards.Card;
import dev.llan.model.pieces.BaseEntity;
import dev.llan.model.pieces.attributes.stats.BaseStatsBuilder;
import dev.llan.model.pieces.attributes.stats.Stats;
import dev.llan.model.pieces.player.Player;
import dev.llan.model.state.combat.CombatManager;
import dev.llan.model.state.combat.actions.Action;
import dev.llan.model.state.combat.actions.CardUse;
import dev.llan.model.state.combat.actions.Move;
import dev.llan.model.state.combat.actions.Wait;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;

public abstract class BaseEnemy extends BaseEntity implements Enemy {
  private boolean inCombat;

  protected BaseEnemy(
      String name, String resourcePath, Point startingPos, Grid grid, BaseStatsBuilder builder) {
    super(name, resourcePath, startingPos, grid, builder);
    this.inCombat = false;
  }

  protected BaseEnemy(
      String name, String resourcePath, Point startingPos, Grid grid, Stats clonedStats) {
    super(name, resourcePath, startingPos, grid, clonedStats);
    this.inCombat = false;
  }

  @Override
  public void setInCombat() {
    inCombat = true;
  }

  @Override
  public boolean inCombat() {
    return inCombat;
  }

  @Override
  public void notifyNearbyEnemies(List<Enemy> others, Set<Enemy> notified) {
    List<Enemy> withinRadius = this.getNearbyEnemies(others);
    for (Enemy other : withinRadius) {
      if (!notified.contains(other) && !other.inCombat()) {
        notified.add(other);
        other.notifyNearbyEnemies(others, notified);
      }
    }
  }

  private List<Enemy> getNearbyEnemies(List<Enemy> others) {
    List<Enemy> within = new ArrayList<>();
    for (Enemy other : others) {
      double distance = Point.getDistance(this.getPosition(), other.getPosition());
      if (distance < this.getStats().getNotificationRadius()) {
        within.add(other);
      }
    }
    return within;
  }

  @Override
  public boolean withinRadius(Point playerPos) {
    double distance = Point.getDistance(playerPos, this.getPosition());

    return distance < this.getStats().getScoutingRadius();
  }

  @Override
  public List<Action> generateActions(GameMap map, Player player, CombatManager.CombatPhase phase) {
    if (phase != CombatManager.CombatPhase.WAIT) {
      return List.of(new Wait(this));
    }
    List<Action> actions = new ArrayList<>();
    activePath = generateActivePath(player.getPosition());
    if (activePath.isPresent()) {
      actions.add(new Move(this, activePath.get()));
    }
    if(!hasAttacked){
      actions.add(new CardUse(this, player, this.selectCard()));
    }

    return actions;
  }

  @Override
  public Optional<Path> generateActivePath(Point playerPos) {
    List<Point> points = playerPos.findClosestVacant(grid);

    if (points.size() > 0) {
      Point minPoint = points.getFirst();
      double minDistance = Point.getDistance(getPosition(), minPoint);
      for (int i = 1; i < points.size(); i++) {
        Point currentPoint = points.get(i);
        double currentDistance = Point.getDistance(getPosition(), currentPoint);
        if (currentDistance < minDistance) {
          minDistance = currentDistance;
          minPoint = currentPoint;
        }
      }
      return pathFinder.findPath(getPosition(), minPoint);
    }
    return Optional.empty();
  }

  protected abstract Card selectCard();

  protected void cloneAttributes(BaseEnemy original) {
    this.activePath = original.cloneActivePath();
    this.clonedEffects = original.cloneEffects();

    // NOT DEEP COPIES
    this.collection = original.collection;
    this.modifiers = original.modifiers;
    this.effects = original.effects;
  }


  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder("BaseEnemy{");
    sb.append("name=").append(this.getName());
    sb.append(", position=").append(this.getPosition());
    sb.append(", inCombat=").append(inCombat);
    sb.append(", stats=").append(stats);
    sb.append('}');
    return sb.toString();
  }
}