Select Git revision
MotorFirefighter.java
Forked from
LABOUREL Arnaud / Firefighter template
Source project has a limited visibility.
-
Anthony Viola authoredAnthony Viola authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
EntitySpawner.java 10.45 KiB
package model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import util.Direction;
import util.Position;
import util.PositionUtil;
public class EntitySpawner {
private final Board<Square> board;
private final Random random = new Random();
public EntitySpawner(Board<Square> board) {
this.board = board;
}
public void spawnEntities(Map<EntityFactory, Integer> entityCounts) {
Map<EntityFactory, Integer> counts = new HashMap<>();
for (EntityFactory factory : entityCounts.keySet()) {
counts.put(factory, 0);
}
int totalEntitiesToPlace = entityCounts.values().stream().mapToInt(Integer::intValue).sum();
int totalEntitiesPlaced = 0;
int chance = 5;
List<Position> positions = generateAllPositions();
while (totalEntitiesPlaced < totalEntitiesToPlace) {
Collections.shuffle(positions);
for (Position pos : positions) {
if (board.getStates(pos).isEmpty()) {
for (EntityFactory factory : entityCounts.keySet()) {
int desiredCount = entityCounts.get(factory);
int currentCount = counts.get(factory);
if (currentCount < desiredCount && random.nextInt(100) < chance) {
Entity entity = factory.create(pos, board);
board.setSquare(new Square(pos, entity));
counts.put(factory, currentCount + 1);
totalEntitiesPlaced++;
if (totalEntitiesPlaced == totalEntitiesToPlace) {
return;
}
break; // Move to the next position
}
}
}
}
// Increase chance after each full traversal
chance = Math.min(chance + 5, 100);
}
}
private List<Position> generateAllPositions() {
List<Position> positions = new ArrayList<>();
for (int x = 0; x < board.rowCount(); x++) {
for (int y = 0; y < board.columnCount(); y++) {
positions.add(new Position(x, y));
}
}
return positions;
}
public static void generateEntitiesInLine(Board<Square> board, Position anchor, EntityFactory entityFactory) {
int xIncrement = 0;
int yIncrement = 0;
// Determine increments based on which coordinate is zero
if (anchor.x() == 0 && anchor.y() >= 0) {
// Starting from the left edge (x == 0), increment x to move right
xIncrement = 1;
} else if (anchor.y() == 0 && anchor.x() >= 0) {
// Starting from the top edge (y == 0), increment y to move down
yIncrement = 1;
} else {
// If neither x nor y is 0, cannot determine direction
throw new IllegalArgumentException("Anchor position must have x or y equal to 0");
}
int x = anchor.x();
int y = anchor.y();
// Continue until we reach the edge of the board
while (board.doesPositionExist(new Position(x, y))) {
Position pos = new Position(x, y);
// Create a new entity for each position
Entity entity = entityFactory.create(pos, board);
entity.setPosition(pos); // Set the position if not already set in the factory
board.addEntityAtSquare(entity, pos);
x += xIncrement;
y += yIncrement;
}
}
public static List<Position> generateEntitiesInRandomLine(Board<Square> board, Position anchor, int maxStepsInDirection, int minimumRoadLength) {
Random random = new Random();
List<Position> path = new ArrayList<>();
int x = anchor.x();
int y = anchor.y();
// Toutes les directions possibles
List<Direction> allDirections = Arrays.asList(Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
// Choisir une direction initiale aléatoire
Direction initialDirection = allDirections.get(random.nextInt(allDirections.size()));
path.add(new Position(x, y)); // Ajouter la position de l'ancre au chemin
int roadLength = 1;
// Déterminer la direction interdite (opposée à la direction initiale)
Direction forbiddenDirection = PositionUtil.getOppositeDirection(initialDirection);
// Initialiser la direction courante
Direction currentDirection = initialDirection;
int stepsInCurrentDirection = 0;
// Ensemble des directions définitivement exclues (direction initiale)
Set<Direction> permanentlyExcludedDirections = new HashSet<>();
permanentlyExcludedDirections.add(initialDirection);
// Ensemble des directions temporairement exclues (initialement vide)
Set<Direction> temporarilyExcludedDirections = new HashSet<>();
while (true) {
// Calculer la prochaine position dans la direction courante
int nextX = x + getXIncrement(currentDirection);
int nextY = y + getYIncrement(currentDirection);
Position nextPos = new Position(nextX, nextY);
if (board.doesPositionExist(nextPos)) {
// Ajouter la position au chemin
path.add(nextPos);
x = nextX;
y = nextY;
roadLength++;
stepsInCurrentDirection++;
} else {
// La position dans la direction courante est invalide
if (roadLength < minimumRoadLength) {
// Exclure temporairement la direction courante
temporarilyExcludedDirections.add(currentDirection);
// Choisir une nouvelle direction valide
Direction newDirection = chooseNewDirection(allDirections, currentDirection, forbiddenDirection,
permanentlyExcludedDirections, temporarilyExcludedDirections, board, x, y, random);
if (newDirection == null) {
// Aucune direction valide disponible pour atteindre la longueur minimale
break;
}
// Mettre à jour la direction courante
currentDirection = newDirection;
forbiddenDirection = PositionUtil.getOppositeDirection(currentDirection);
stepsInCurrentDirection = 0;
continue; // Recommencer avec la nouvelle direction
} else {
// La longueur minimale est atteinte, arrêter la génération
break;
}
}
// Vérifier s'il est temps de changer de direction
if (stepsInCurrentDirection >= maxStepsInDirection) {
// Choisir une nouvelle direction
Direction newDirection = chooseNewDirection(allDirections, currentDirection, forbiddenDirection,
permanentlyExcludedDirections, temporarilyExcludedDirections, board, x, y, random);
if (newDirection == null) {
// Aucune direction valide disponible
break;
}
// Mettre à jour la direction courante
currentDirection = newDirection;
forbiddenDirection = PositionUtil.getOppositeDirection(currentDirection);
stepsInCurrentDirection = 0;
}
}
return path; // Retourner la liste des positions formant le serpent
}
/**
* Choisit une nouvelle direction valide en tenant compte des exclusions permanentes et temporaires.
*
* @param allDirections Toutes les directions possibles.
* @param currentDirection La direction actuelle.
* @param forbiddenDirection La direction opposée à la direction actuelle (interdite).
* @param permanentlyExcludedDirections Les directions définitivement exclues.
* @param temporarilyExcludedDirections Les directions temporairement exclues.
* @param board Le plateau de jeu.
* @param x La coordonnée X actuelle.
* @param y La coordonnée Y actuelle.
* @param random Une instance de Random pour le choix aléatoire.
* @return La nouvelle direction choisie ou null si aucune direction valide n'est disponible.
*/
private static Direction chooseNewDirection(List<Direction> allDirections, Direction currentDirection, Direction forbiddenDirection,
Set<Direction> permanentlyExcludedDirections, Set<Direction> temporarilyExcludedDirections,
Board<Square> board, int x, int y, Random random) {
// Créer une liste de directions valides en excluant :
// - La direction actuelle
// - La direction interdite (opposée à la direction actuelle)
// - Les directions définitivement exclues
// - Les directions temporairement exclues
List<Direction> validDirections = new ArrayList<>(allDirections);
validDirections.remove(currentDirection);
validDirections.remove(forbiddenDirection);
validDirections.removeAll(permanentlyExcludedDirections);
validDirections.removeAll(temporarilyExcludedDirections);
// Filtrer les directions qui permettent de continuer le chemin
validDirections.removeIf(dir -> !board.doesPositionExist(new Position(x + getXIncrement(dir), y + getYIncrement(dir))));
if (validDirections.isEmpty()) {
// Aucune direction valide disponible
return null;
}
// Choisir une nouvelle direction aléatoirement
return validDirections.get(random.nextInt(validDirections.size()));
}
private static int getXIncrement(Direction direction) {
switch (direction) {
case NORTH: return -1;
case SOUTH: return 1;
default: return 0;
}
}
private static int getYIncrement(Direction direction) {
switch (direction) {
case EAST: return 1;
case WEST: return -1;
default: return 0;
}
}
}