diff --git a/src/main/java/app/SimulatorApplication.java b/src/main/java/app/SimulatorApplication.java index 0e3d3359f2042e1a03608d7b0d26fd01ef9bd7d4..076797034356054523760c0b7cca79e2446b762a 100644 --- a/src/main/java/app/SimulatorApplication.java +++ b/src/main/java/app/SimulatorApplication.java @@ -13,14 +13,16 @@ import javafx.stage.Stage; public class SimulatorApplication extends javafx.application.Application { private static final String VIEW_RESOURCE_PATH = "/view/view.fxml"; private static final String APP_NAME = "Firefighter simulator"; - private static final int ROW_COUNT = 20; - private static final int COLUMN_COUNT = 20; - private static final int BOX_WIDTH = 25; - private static final int BOX_HEIGHT = 25; - public static final int INITIAL_FIRE_COUNT = 3; - public static final int INITIAL_FIREFIGHTER_COUNT = 6; - public static final int INITIAL_CLOUD_COUNT = 6; - public static final int INITIAL_MOUNTAIN_COUNT= 30; + private static final int ROW_COUNT = 40; + private static final int COLUMN_COUNT = 40; + private static final int BOX_WIDTH = 15; + private static final int BOX_HEIGHT = 15; + public static final int INITIAL_FIRE_COUNT = 4; + public static final int INITIAL_FIREFIGHTER_COUNT = 18; + public static final int INITIAL_MOTORIZED_FIREFIGHTER_COUNT = 5; + public static final int INITIAL_CLOUD_COUNT = 9; + public static final int INITIAL_MOUNTAIN_COUNT= 18; + public static final int TURNS_FOR_SPAWNING_AIRTANKER = 8; private Stage primaryStage; private Parent view; @@ -47,7 +49,7 @@ public class SimulatorApplication extends javafx.application.Application { view = loader.load(); Controller controller = loader.getController(); controller.initialize(BOX_WIDTH, BOX_HEIGHT, COLUMN_COUNT, ROW_COUNT, - INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT, INITIAL_CLOUD_COUNT, INITIAL_MOUNTAIN_COUNT); + INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT, INITIAL_MOTORIZED_FIREFIGHTER_COUNT, INITIAL_CLOUD_COUNT, INITIAL_MOUNTAIN_COUNT, TURNS_FOR_SPAWNING_AIRTANKER); } private void showScene() { diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 577ca8297d2ffe2d263bb10fdcf88a74a17bcd09..ae28563066b8de289df950dac99fb61a437c3379 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -3,9 +3,9 @@ package controller; import static java.util.Objects.*; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; - - +import java.util.Map; import javafx.animation.Animation; import javafx.animation.KeyFrame; @@ -20,7 +20,13 @@ import javafx.scene.control.ToggleGroup; import javafx.util.Duration; import javafx.util.Pair; import model.Board; +import model.Cloud; +import model.EntityFactory; +import model.Fire; +import model.FireFighter; import model.FireFighterScenario; +import model.MotorizedFireFighter; +import model.Mountain; import model.Square; import util.Position; import view.Grid; @@ -119,9 +125,19 @@ public class Controller { } public void initialize(int squareWidth, int squareHeight, int columnCount, - int rowCount, int initialFireCount, int initialFirefighterCount, int initialcloudCount, int initialmountaincount) { + int rowCount, int initialFireCount, int initialFirefighterCount, int initialMotorizedFirefightersCount, int initialcloudCount, int initialmountaincount, int turnsForSpawningAirTanker) { grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight); - this.setModel(new FireFighterScenario(columnCount, rowCount, initialFireCount, initialFirefighterCount, initialcloudCount, initialmountaincount)); + Board<Square> model = new FireFighterScenario(columnCount, rowCount); + Map<EntityFactory, Integer> entityCounts = new HashMap<>(); + + entityCounts.put((pos, b) -> new Fire(pos), initialFireCount); + entityCounts.put((pos, b) -> new FireFighter(pos, b), initialFirefighterCount); + entityCounts.put((pos, b) -> new MotorizedFireFighter(pos, b), initialMotorizedFirefightersCount); + entityCounts.put((pos, b) -> new Cloud(pos, b), initialcloudCount); + entityCounts.put((pos, b) -> new Mountain(pos), initialmountaincount); + + model.placeInitialEntities(entityCounts); + this.setModel(model); repaintGrid(); } diff --git a/src/main/java/model/AirTanker.java b/src/main/java/model/AirTanker.java index b723a7b5ba41ddb26205c8050b55053dd708aa10..4f4bfc1df8894ef120025037df971826b6a31e50 100644 --- a/src/main/java/model/AirTanker.java +++ b/src/main/java/model/AirTanker.java @@ -16,8 +16,8 @@ public class AirTanker implements Entity{ private Position position; private int priority = 3; - public AirTanker(Position position, Board<Square> b) { - this.age = 0; + public AirTanker(Position position, Board<Square> b, int age) { + this.age = age; this.position = position; determineDirection(b); extinguish(position,b); @@ -41,7 +41,6 @@ public class AirTanker implements Entity{ } else if (position.y() == rowCount - 1) { direction = Direction.NORTH; // Move north if on bottom edge } else { - System.out.println("not on a edge"); // Not on an edge; default to moving east or choose a random direction direction = Direction.EAST; } @@ -49,14 +48,12 @@ public class AirTanker implements Entity{ @Override public List<Position> nextTurn(Board<Square> b) { - List<Position> positions = new ArrayList<>(); // Move in the determined direction Position nextPos = getNextPosition(position, direction, b); if (nextPos == null || !b.doesPositionExist(nextPos)) { // Reached the edge; remove AirTanker from the board - System.out.println("end of airtanker mission"); b.clearCaseFrom(this, position); positions.add(position); return positions; @@ -71,10 +68,6 @@ public class AirTanker implements Entity{ b.addEntityAtSquare(this, nextPos); positions.add(nextPos); // New position - - // Increment age if needed - this.age++; - return positions; } } @@ -110,7 +103,6 @@ public class AirTanker implements Entity{ break; // Only handling cardinal directions } Position newPos = new Position(x, y); - System.out.println("trying to move to : " + newPos.toString()); if (b.doesPositionExist(newPos)) { return newPos; } else { diff --git a/src/main/java/model/Board.java b/src/main/java/model/Board.java index 1768662163cfe1cf207b57a534f51aee105b8f7f..6d51304610a1f242df6974939c6a4b92a5841c52 100644 --- a/src/main/java/model/Board.java +++ b/src/main/java/model/Board.java @@ -1,6 +1,7 @@ package model; import java.util.List; +import java.util.Map; import util.Position; @@ -77,12 +78,12 @@ public interface Board<S> { public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType); public void addEntityAtSquare(Entity entity, Position position); - + public void placeInitialEntities(Map<EntityFactory, Integer> entityCounts); //Return if the position is completely free public boolean isPositionEmpty(Position position); //Return if the position is available for the specified priority public boolean isPositionFree(Position position, int priority); - + } diff --git a/src/main/java/model/EntityFactory.java b/src/main/java/model/EntityFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..8d7249c90e63612199f1d40835910e92e2fc62e7 --- /dev/null +++ b/src/main/java/model/EntityFactory.java @@ -0,0 +1,7 @@ +package model; + +import util.Position; + +public interface EntityFactory { + Entity create(Position position, Board<Square> board); +} diff --git a/src/main/java/model/EntitySpawner.java b/src/main/java/model/EntitySpawner.java new file mode 100644 index 0000000000000000000000000000000000000000..475625f36ee2ac40cb629dfc0906adb01371aca7 --- /dev/null +++ b/src/main/java/model/EntitySpawner.java @@ -0,0 +1,71 @@ +package model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import util.Position; + +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; + } +} diff --git a/src/main/java/model/FireFighterScenario.java b/src/main/java/model/FireFighterScenario.java index bce13d353a6b7b5bc13f93b9cac25f00d577ed5b..f48e74465b29f6110b07ab257f54772f1ae299d6 100644 --- a/src/main/java/model/FireFighterScenario.java +++ b/src/main/java/model/FireFighterScenario.java @@ -1,9 +1,9 @@ package model; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Random; import util.Matrix; @@ -15,80 +15,20 @@ 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; + private Map<EntityFactory, Integer> initialMap; - public FireFighterScenario(int columns, int rows, int initialFireCount, int initialFireFightersCount, int initialCloudCount, int initialMoutainCount) { + public FireFighterScenario(int columns, int rows) { 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, 0))); - 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; - } - } - } - } +public void placeInitialEntities(Map<EntityFactory, Integer> entityCounts) { + EntitySpawner spawner = new EntitySpawner(this); + spawner.spawnEntities(entityCounts); + this.initialMap = entityCounts; +} - // 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()) { @@ -199,7 +139,7 @@ private void spawnAirTanker(List<Position> changedPositions) { System.out.println("Position: " + position.toString()); // Create a new AirTanker - AirTanker airTanker = new AirTanker(position, this); + AirTanker airTanker = new AirTanker(position, this, getStepNumber()); System.out.println(" direction : " + airTanker.getDirection()); // Add the AirTanker to the board addEntityAtSquare(airTanker, position); @@ -240,7 +180,7 @@ private void spawnAirTanker(List<Position> changedPositions) { step = 0; matrix.clear(); initScenario(matrix); - placeInitialActors(initialFireCount, initialFireFightersCount, intialCloudCount, initialMoutainCount); + placeInitialEntities(initialMap); } public int stepNumber() { diff --git a/src/main/java/model/Mountain.java b/src/main/java/model/Mountain.java index 02f7fd637f5e3736c8feb048ba5d9e4cc4a4500b..4315c6fa6f354b7f4d224f94ebb62485cc45148c 100644 --- a/src/main/java/model/Mountain.java +++ b/src/main/java/model/Mountain.java @@ -23,7 +23,6 @@ public class Mountain implements Entity{ @Override public List<Position> nextTurn(Board<Square> board) { - List<Entity> states = board.getStates(position).getEntities(); return List.of(); }