package model; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; import util.Matrix; import util.Position; import util.PositionUtil; public class FireFighterScenario extends EntityScenario implements Board<Square> { private Matrix<Square> matrix; private int step; private int initialFireCount; private int initialFireFightersCount; private int intialCloudCount; private int initialMoutainCount; public FireFighterScenario(int columns, int rows, int initialFireCount, int initialFireFightersCount, int initialCloudCount, int initialMoutainCount) { this.matrix = new Matrix<Square>(columns, rows); this.initialFireCount = initialFireCount; this.initialFireFightersCount = initialFireFightersCount; this.intialCloudCount = initialCloudCount; this.initialMoutainCount = initialMoutainCount; initScenario(matrix); placeInitialActors(initialFireCount, initialFireFightersCount, initialCloudCount, initialMoutainCount); this.step = 0; } private void placeInitialActors(int initialFireCount, int initialFireFightersCount, int initialCloudCount, int initialMoutainCount) { int fireCount = 0; int fireFighterCount = 0; int cloudCount = 0; int moutainCount = 0; int chance = 5; // Chance initiale en pourcentage Random random = new Random(); List<Position> positions = new ArrayList<>(); for (int x = 0; x < matrix.getRows(); x++) { for (int y = 0; y < matrix.getColumns(); y++) { positions.add(new Position(x, y)); } } setSquare(new Square(new Position(0,0), new MotorizedFireFighter(new Position(0,0), this))); while (fireCount < initialFireCount || fireFighterCount < initialFireFightersCount || cloudCount < intialCloudCount) { Collections.shuffle(positions); // Mélange les positions pour un parcours aléatoire for (Position pos : positions) { if (getStates(pos).isEmpty()) { if (fireCount < initialFireCount && random.nextInt(100) < chance) { setSquare(new Square(pos, new Fire(pos, this, 1))); fireCount++; if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount && moutainCount == initialMoutainCount) { return; } continue; } if (fireFighterCount < initialFireFightersCount && random.nextInt(100) < chance) { setSquare(new Square(pos, new FireFighter(pos, this, 1))); fireFighterCount++; if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount && moutainCount == initialMoutainCount) { return; } } if (cloudCount < intialCloudCount && random.nextInt(100) < chance) { setSquare(new Square(pos, new Cloud(pos, this, 1))); cloudCount++; if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount && moutainCount == initialMoutainCount) { return; } } if (moutainCount < initialMoutainCount && random.nextInt(100) < chance) { setSquare(new Square(pos, new Mountain(pos, 1))); moutainCount++; if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount && moutainCount == initialMoutainCount) { return; } } } } // Augmente la chance de placement après chaque parcours complet chance = Math.min(chance + 5, 100); // Ne dépasse pas 100% } } 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 (!(getStates(position).isEmpty())) { return; } if (doesPositionExist(position)) { matrix.get(position.x(), position.y()).addEntity(entity); } } public void addEntityAtSquare(Entity entity, Position position, boolean replaceStates) { if (!(getStates(position).isEmpty()) && !replaceStates) { return; } 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 List<Position> updateToNextGeneration() { ArrayList<Position> changedPositions = new ArrayList<>(); Iterator<Square> iterator = matrix.iterator(); while (iterator.hasNext()) { Square s = iterator.next(); if (s.isEmpty()) continue; if (s.getMaxAge() == 0) { s.incrementAllAges(); continue; } if (s.getMaxAge() == step + 1) { continue; } List<Entity> entities = new ArrayList<>(s.getEntities()); for (Entity e : entities) { e.incrementAge(); changedPositions.addAll(e.nextTurn(this)); } } this.step = this.step + 1; // matrix.displayMatrix(); return changedPositions; } 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); placeInitialActors(initialFireCount, initialFireFightersCount, intialCloudCount, initialMoutainCount); } 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(); } }