package model; import java.util.List; import java.util.Map; import java.util.Random; import app.SimulatorApplication; import model.firefighterscenario.Fire; import model.firefighterscenario.Mountain; import model.firefighterscenario.Road; import model.firefighterscenario.Rockery; import util.Matrix; import util.PathGenerator; import util.Position; import util.PositionUtil; public class Scenario implements Board<Square>{ private Matrix<Square> matrix; protected int step; protected int turnsToSpawnAirTanker; private Map<EntityFactory, Integer> initialMap; public Scenario(int columns, int rows, Map<EntityFactory, Integer> initialMap) { this.matrix = new Matrix<Square>(columns, rows); initScenario(matrix); this.turnsToSpawnAirTanker = SimulatorApplication.TURNS_FOR_SPAWNING_AIRTANKER; this.step = 0; this.initialMap = initialMap; placeInitialEntities(initialMap); } public void initScenario(Matrix<Square> matrix){ for(int x = 0; x < matrix.getRows(); x++){ for(int y = 0; y < matrix.getColumns(); y++){ Square s = new Square(new Position(x, y), new EmptySquare(new Position(x,y))); matrix.set(x,y, s); } } } protected Matrix<Square> getMatrix(){ return this.matrix; } public void placeInitialEntities(Map<EntityFactory, Integer> initialMap) { EntitySpawner spawner = new EntitySpawner(this); spawner.spawnEntities(initialMap); generateRoads(); } public Square getStates(Position position) { if (position.x() > matrix.size() || position.y() > matrix.size()) { throw new IllegalArgumentException( "The position x:" + position.x() + " y:" + position.y() + " is out of the board."); } return matrix.get(position.x(), position.y()); } public void setSquare(Square square) { Position position = square.getPosition(); if (!(getStates(position).isEmpty())) { return; } if (doesPositionExist(position)) { matrix.set(position.x(), position.y(), square); } } public void setSquare(Square square, boolean replaceStates) { Position position = square.getPosition(); if (!(getStates(position).isEmpty()) && !replaceStates) { return; } matrix.set(position.x(), position.y(), square); } public void addEntityAtSquare(Entity entity, Position position) { if (doesPositionExist(position)) { matrix.get(position.x(), position.y()).addEntity(entity); } } public int rowCount() { return matrix.getRows(); } public int columnCount() { return matrix.getColumns(); } @Override public void clearCaseFrom(Entity entity, Position position) { matrix.get(position.x(), position.y()).getEntities().removeIf(element -> element.equals(entity)); } public Position getNearestEntity(Position fromPos, Class<?> entityType) { int rows = matrix.getRows(); int cols = matrix.getColumns(); Position nearestPosition = fromPos; // Définir la distance maximale possible int maxDistance = rows + cols; // Parcourir les distances croissantes à partir de 1 for (int distance = 1; distance < maxDistance; distance++) { List<Position> positionsAtDistance = PositionUtil.getPositionsAtManhattanDistance(fromPos, distance, rows, cols); for (Position currentPos : positionsAtDistance) { Square currentSquare = matrix.get(currentPos.x(), currentPos.y()); for (Entity currentEntity : currentSquare.getEntities()) { if (entityType.isInstance(currentEntity)) { // Dès qu'une entité est trouvée à cette distance, elle est la plus proche // possible return currentPos; } } } } return nearestPosition; // Retourne null si aucune entité n'est trouvée } public void reset() { step = 0; matrix.clear(); initScenario(matrix); placeInitialEntities(initialMap); } public int stepNumber() { return this.step; } @Override public boolean doesPositionExist(Position position) { return matrix.validateIndex(position); } @Override public int getStepNumber() { return step; } @Override public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType) { return getStates(squarePos).getEntities().stream().anyMatch(entityType::isInstance); } @Override public boolean isPositionEmpty(Position position) { return getStates(position).isEmpty(); } @Override public boolean isPositionFree(Position position, int priority) { List<Entity> entities = matrix.get(position.x(), position.y()).getEntities(); for (Entity e : entities) { if (e.getPriority() == priority) { return false; } } return true; } private void generateRoads() { if(columnCount() < 10 || rowCount() < 10){ return; } Random random = new Random(); // Get board dimensions int rowCount = rowCount(); // Number of rows (vertical axis) int columnCount = columnCount(); // Number of columns (horizontal axis) // Decide randomly whether to set x or y to 0 boolean setXToZero = random.nextBoolean(); int x = 0; int y = 0; if (setXToZero) { // x is set to 0, y is random within column bounds x = 0; y = random.nextInt(columnCount); } else { // y is set to 0, x is random within row bounds x = random.nextInt(rowCount); y = 0; } Position startPosition = new Position(x, y); PathGenerator pathGenerator = new PathGenerator(this, startPosition, 4, columnCount()); // Call generateEntitiesInLine to place the roads List<Position> snake = pathGenerator.generate(); for(Position p : snake){ List<Entity> entitiesAtSquare = List.copyOf(getStates(p).getEntities()); for(Entity e: entitiesAtSquare){ if(e instanceof Mountain || e instanceof Rockery || e instanceof Fire){ clearCaseFrom(e, e.getPosition()); } } addEntityAtSquare(new Road(p), p); } } }