diff --git a/scenariovirus.txt b/scenariovirus.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d43e533bb6bbb2ca17d9d80a418b2e6f13b7b03b
--- /dev/null
+++ b/scenariovirus.txt
@@ -0,0 +1,15 @@
+Patients : 
+- Interactions et mouvement : Se déplacent et interagissent socialement, augmentant ainsi les chances de transmission du virus. Certains peuvent être asymptomatiques.
+- Réaction en cas de maladie : S'ils se rendent compte qu'ils sont malades, ils cherchent un docteur pour se faire soigner. Sinon, ils continuent leur vie normalement, pouvant transmettre le virus sans le savoir.
+
+
+Virus : 
+- Mouvement et infection : Entité unique sur le plateau qui se déplace aléatoirement, infectant les patients lorsqu'il passe à proximité.
+- Le virus infecte les patients lorsqu'il passe à proximité.
+- Évolue tous les 30 tours pour donner un nouveau variant, lorsqu'un nouveau variant est détecté, les médecins mettent plus de temps à le soigner au début
+
+
+Docteurs : 
+- Traitement des patients : Traitent les patients malades qui se trouvent dans des cases adjacentes à leur position.
+- Statique : Ne se déplacent pas entre les tours, ce qui nécessite que les patients viennent à eux pour être soignés.
+
diff --git a/src/main/java/app/SimulatorApplication.java b/src/main/java/app/SimulatorApplication.java
index 86abb8525b4a41c5a54cea60981c01025d5ae3f8..10fa4af1b221ac2dd223eb45bd7fbe5a8b97fa48 100644
--- a/src/main/java/app/SimulatorApplication.java
+++ b/src/main/java/app/SimulatorApplication.java
@@ -13,15 +13,20 @@ 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;
+  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 = 8;
+  public static final int INITIAL_FIREFIGHTER_COUNT = 12;
+  public static final int INITIAL_MOTORIZED_FIREFIGHTER_COUNT = 8;
+  public static final int INITIAL_CLOUD_COUNT = 8;
+  public static final int INITIAL_MOUNTAIN_COUNT= 6;
+  public static final int TURNS_FOR_SPAWNING_AIRTANKER = 10;
 
   private Stage primaryStage;
   private Parent view;
+
   private void initializePrimaryStage(Stage primaryStage) {
     this.primaryStage = primaryStage;
     this.primaryStage.setTitle(APP_NAME);
@@ -44,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_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 154a1b81d01ae5805d59c55456aa57465a1e6b38..97a8c819e04f4036c399b435a844740cfc98727f 100644
--- a/src/main/java/controller/Controller.java
+++ b/src/main/java/controller/Controller.java
@@ -3,7 +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;
@@ -18,8 +20,18 @@ import javafx.scene.control.ToggleGroup;
 import javafx.util.Duration;
 import javafx.util.Pair;
 import model.Board;
+import model.EmptySquare;
 import model.Entity;
-import model.FireFighterScenario;
+import model.EntityFactory;
+import model.Model;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import model.firefighterscenario.Fire;
+import model.firefighterscenario.FireFighter;
+import model.firefighterscenario.FireFighterScenario;
+import model.firefighterscenario.MotorizedFireFighter;
+import model.firefighterscenario.Mountain;
+import model.firefighterscenario.Rockery;
 import util.Position;
 import view.Grid;
 import view.ViewElement;
@@ -40,7 +52,8 @@ public class Controller {
   @FXML
   private Grid<ViewElement> grid;
   private Timeline timeline;
-  private Board<Entity> board;
+  private Board<Square> board;
+  private Model model;
 
   @FXML
   private void initialize() {
@@ -54,15 +67,16 @@ public class Controller {
     pauseToggleButton.setSelected(true);
   }
 
-  private void setModel(Board<Entity> board) {
-    this.board = requireNonNull(board, "board is null");
+  private void setModel(Model model) {
+    this.board = requireNonNull(model.getBoard(), "board is null");
+    this.model = model;
   }
 
-  private void updateBoard(){
-    List<Position> updatedPositions = board.updateToNextGeneration();
+  private void updateBoard() {
+    List<Position> updatedPositions = model.updateToNextGeneration();
     List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>();
-    for(Position updatedPosition : updatedPositions){
-      Entity squareState = board.getState(updatedPosition);
+    for (Position updatedPosition : updatedPositions) {
+      Square squareState = board.getStates(updatedPosition);
       ViewElement viewElement = getViewElement(squareState);
       updatedSquares.add(new Pair<>(updatedPosition, viewElement));
     }
@@ -70,25 +84,30 @@ public class Controller {
     updateGenerationLabel(board.stepNumber());
   }
 
-  private void repaintGrid(){
+  private void repaintGrid() {
     int columnCount = board.columnCount();
     int rowCount = board.rowCount();
     ViewElement[][] viewElements = new ViewElement[rowCount][columnCount];
-    for(int column = 0; column < columnCount; column++)
-      for(int row = 0; row < rowCount; row++)
-        viewElements[row][column] = getViewElement(board.getState(new Position(row, column)));
+    for (int column = 0; column < columnCount; column++)
+      for (int row = 0; row < rowCount; row++)
+        viewElements[row][column] = getViewElement(board.getStates(new Position(row, column)));
     grid.repaint(viewElements);
     updateGenerationLabel(board.stepNumber());
   }
 
-  private ViewElement getViewElement(Entity entity) {
-      return new ViewElement(entity.getViewColor());
+  private ViewElement getViewElement(Square square) {
+    if (!square.getEntities().isEmpty()) {
+      for (Entity entity : square.getEntities()) {
+        if(entity instanceof EmptySquare)continue;
+          return entity.getViewElement();
+      }
+    }
+    return new ViewElement(square.getViewColor());
   }
 
   private void initializeTimeline() {
     Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS);
-    EventHandler<ActionEvent> eventHandler =
-            event -> updateBoard();
+    EventHandler<ActionEvent> eventHandler = event -> updateBoard();
     KeyFrame keyFrame = new KeyFrame(duration, eventHandler);
     timeline = new Timeline(keyFrame);
     timeline.setCycleCount(Animation.INDEFINITE);
@@ -113,23 +132,47 @@ public class Controller {
   public void restartButtonAction() {
     this.pause();
     board.reset();
+    System.gc();
     pauseToggleButton.setSelected(true);
     repaintGrid();
   }
 
   public void initialize(int squareWidth, int squareHeight, int columnCount,
-                                int rowCount, int initialFireCount, int initialFirefighterCount) {
+      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));
+    
+    Map<EntityFactory, Integer> entityCounts = new HashMap<EntityFactory, Integer>();
+    
+    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);
+    entityCounts.put((pos, b) -> new Rockery(pos), 3);
+    
+    
+    /*
+    entityCounts.put((pos, b) -> new Rock(pos), 10);
+    entityCounts.put((pos, b) -> new Cisor(pos), 10);
+    entityCounts.put((pos, b) -> new Paper(pos), 10);
+    */
+
+    /*
+    entityCounts.put((pos, b) -> new Patient(pos), 70);
+    entityCounts.put((pos, b) -> new Virus(pos), 6);
+    entityCounts.put((pos, b) -> new Doctor(pos), 3);
+    */
+    Model model = new FireFighterScenario(columnCount, rowCount, entityCounts);
+    this.setModel(model);
     repaintGrid();
   }
-
+  
   public void oneStepButtonAction() {
     this.pause();
     updateBoard();
   }
 
-  private void updateGenerationLabel(int value){
+  private void updateGenerationLabel(int value) {
     generationNumberLabel.setText(Integer.toString(value));
   }
 }
\ No newline at end of file
diff --git a/src/main/java/model/Board.java b/src/main/java/model/Board.java
index 1326ce88c7878fd042329c66fe7cdaa66941452f..6fc78ddca79a959bf915ed614020208bd9016cc4 100644
--- a/src/main/java/model/Board.java
+++ b/src/main/java/model/Board.java
@@ -1,11 +1,13 @@
 package model;
 
 import java.util.List;
+import java.util.Map;
 
 import util.Position;
 
 /**
- * This interface represents a generic board for modeling various state-based systems.
+ * This interface represents a generic board for modeling various state-based
+ * systems.
  *
  * @param <S> The type of state represented on the board.
  */
@@ -17,15 +19,15 @@ public interface Board<S> {
    * @param position The position on the board for which to retrieve the state.
    * @return The state at the specified position.
    */
-  S getState(Position position);
+  S getStates(Position position);
 
   /**
    * Set the state of a specific position on the board to the specified state.
    *
-   * @param state The state to set for the given position.
+   * @param state    The state to set for the given position.
    * @param position The position on the board for which to set the state.
    */
-  void setState(S state, Position position);
+  void setSquare(S square);
 
   /**
    * Get the number of rows in the board.
@@ -41,15 +43,6 @@ public interface Board<S> {
    */
   int columnCount();
 
-  /**
-   * Update the board to its next generation or state. This method may modify the
-   * internal state of the board and return a list of positions that have changed
-   * during the update.
-   *
-   * @return A list of positions that have changed during the update.
-   */
-  List<Position> updateToNextGeneration();
-
   /**
    * Reset the board to its initial state.
    */
@@ -63,13 +56,25 @@ public interface Board<S> {
   int stepNumber();
 
   public int getStepNumber();
+
   // Le booléen replaceState permet de forcer le remplacement des cases vides
-  public void setState(Entity state, Position position, boolean replaceStates);
+  public void setSquare(S square, boolean replaceStates);
 
   public boolean doesPositionExist(Position position);
 
-  public void clearCase(Position position);
+  public void clearCaseFrom(Entity entity, Position position);
 
-  public Position getNearestEntity(Position fromPos, Class<?> entityType);
-}
+  public Position getNearestEntity(Position fromPos, Class<?> entityType, List<Entity> exclusionList);
+
+  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/EmptySquare.java b/src/main/java/model/EmptySquare.java
index 113ea0a394870345e6520690e083b03c9bb70a7c..e14e38d7c9164b0f00a3146efd551e1bf7ded8c7 100644
--- a/src/main/java/model/EmptySquare.java
+++ b/src/main/java/model/EmptySquare.java
@@ -4,23 +4,38 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javafx.scene.paint.Color;
+import model.firefighterscenario.Cloud;
 import util.Position;
+import view.ViewElement;
 
-public class EmptySquare implements Entity{
+public class EmptySquare implements Entity {
 
     private Position position;
     private final Color viewColor = Color.WHITE;
     private int age;
-    public EmptySquare(Position p){
+    private final int priotity = -1;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/img.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public EmptySquare(Position p) {
         this.position = p;
         this.age = -999;
     }
-    public EmptySquare(Position p, int age){
+
+    public EmptySquare(Position p, int age) {
         this.position = p;
         this.age = age;
     }
+
     @Override
-    public List<Position> nextTurn(Board<Entity> board) {
+    public List<Position> nextTurn(Board<Square> board) {
         return new ArrayList<Position>();
     }
 
@@ -33,10 +48,11 @@ public class EmptySquare implements Entity{
     public void setPosition(Position p) {
         this.position = p;
     }
-    
-    public Color getViewColor(){
+
+    public Color getViewColor() {
         return this.viewColor;
     }
+
     @Override
     public int getAge() {
         return this.age;
@@ -46,4 +62,19 @@ public class EmptySquare implements Entity{
     public void incrementAge() {
         age = age + 1;
     }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public int getPriority(){
+        return this.priotity;
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
 }
diff --git a/src/main/java/model/Entity.java b/src/main/java/model/Entity.java
index 5569aa5ced37576d3776bd79bb3bb58ba675237b..2b53e3ae3319c167dfee1d7843b73d3fa312c4bf 100644
--- a/src/main/java/model/Entity.java
+++ b/src/main/java/model/Entity.java
@@ -1,9 +1,10 @@
 package model;
-
 import java.util.List;
 
 import javafx.scene.paint.Color;
 import util.Position;
+import view.ViewElement;
+
 
 public interface Entity {
         /**
@@ -12,10 +13,13 @@ public interface Entity {
      * @param b Le plateau de jeu contenant des entités.
      * @return Une liste de positions affectées durant le tour (que la vue doit mettre à jour).
      */
-    public List<Position> nextTurn(Board<Entity> board);
+    public List<Position> nextTurn(Board<Square> board);
     public Position getPosition();
     public void setPosition(Position p);
     public int getAge();
+    public void setAge(int age);
     public void incrementAge();
     public Color getViewColor();
+    public int getPriority();
+    public ViewElement getViewElement();
 }
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/EntityNotFoundException.java b/src/main/java/model/EntityNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..9902ad982952d8d34e0ceb55266b8782b9901a98
--- /dev/null
+++ b/src/main/java/model/EntityNotFoundException.java
@@ -0,0 +1,7 @@
+package model;
+
+class EntityNotFoundException extends Exception {
+    public EntityNotFoundException(String message) {
+        super(message);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/model/EntityScenario.java b/src/main/java/model/EntityScenario.java
deleted file mode 100644
index 094862a46b940eeefeacb5d0582d5c5a6d250fc8..0000000000000000000000000000000000000000
--- a/src/main/java/model/EntityScenario.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package model;
-
-import util.Matrix;
-import util.Position;
-
-public abstract class EntityScenario implements Scenario{
-    public void initScenario(Matrix<Entity> matrix){
-        for(int x = 0; x < matrix.getRows(); x++){
-            for(int y = 0; y < matrix.getColumns(); y++){
-                matrix.set(x,y, new EmptySquare(new Position(x, y)));
-            }
-        }
-    }
-}
diff --git a/src/main/java/model/EntitySpawner.java b/src/main/java/model/EntitySpawner.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd6fa6e39196e6ffd798760bc8546e96887694f2
--- /dev/null
+++ b/src/main/java/model/EntitySpawner.java
@@ -0,0 +1,262 @@
+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;
+        }
+    }
+    
+
+    
+    
+    
+
+    
+    
+
+    
+}
diff --git a/src/main/java/model/Fire.java b/src/main/java/model/Fire.java
deleted file mode 100644
index 019137ed7268f5d7ff88db50ca42d89afdda1fb2..0000000000000000000000000000000000000000
--- a/src/main/java/model/Fire.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package model;
-import java.util.ArrayList;
-import java.util.List;
-
-import javafx.scene.paint.Color;
-import util.Position;
-import util.PositionUtil;
-
-public class Fire implements Entity{
-    Board<Entity> b;
-    private Position position;
-    private final Color viewColor = Color.RED;
-    private int age;
-    public Fire(Position position, Board<Entity> b){
-        this.b = b;
-        this.position = position;
-        this.age = 0;
-    }
-    public Fire(Position position, Board<Entity> b, int age){
-        this.b = b;
-        this.position = position;
-        this.age = age;
-    }
-
-    @Override
-    public List<Position> nextTurn(Board<Entity> board) {
-        if(board.getStepNumber() % 2 == 0)return new ArrayList<Position>();
-        List<Position> positions = PositionUtil.generateAdjacentPositions(position, board);
-        for(Position p : positions){
-            if(b.getState(p) instanceof EmptySquare){
-                if(b.getState(p).getAge() < b.getStepNumber()){
-                    board.setState(new Fire(p, board), p);
-                }
-            }
-            if(!b.doesPositionExist(p)){
-                positions.remove(p);
-            }
-        }
-        return positions;
-    }
-    
-
-
-    
-    @Override
-    public void setPosition(Position p) {
-        this.position = p;
-    }
-    @Override
-    public Position getPosition() {
-        return this.position;
-    }
-
-    public Color getViewColor(){
-        return this.viewColor;
-    }
-
-    @Override
-    public int getAge() {
-        return this.age;
-    }
-
-    @Override
-    public void incrementAge() {
-        this.age = age + 1 ;
-    }
-}
diff --git a/src/main/java/model/FireFighter.java b/src/main/java/model/FireFighter.java
deleted file mode 100644
index e9f2afb2c450b85727fea9a8fba26778a4439fea..0000000000000000000000000000000000000000
--- a/src/main/java/model/FireFighter.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package model;
-import java.util.ArrayList;
-import java.util.List;
-
-import javafx.scene.paint.Color;
-import util.Position;
-import util.PositionUtil;
-
-public class FireFighter implements Entity{
-    private int age;
-    private Position position;
-    private final Color viewColor = Color.BLUE;
-
-
-    public FireFighter(Position position, Board<Entity> b){
-        this.position = position;
-        this.age = 0;
-    }
-    public FireFighter(Position position, Board<Entity> b, int age){
-        this.position = position;
-        this.age = age;
-    }
-    
-    public List<Position> nextTurn(Board<Entity> b) {
-        List<Position> positions = new ArrayList<>();
-    
-        // Générer les positions adjacentes
-        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b);
-    
-        // Vérifier s'il y a du feu dans une des positions adjacentes
-        boolean hasFire = adjacentPositions.stream()
-                                           .anyMatch(p -> b.getState(p) instanceof Fire);
-    
-        if (hasFire) {
-            // Si du feu est trouvé, on éteint les feux adjacents
-            positions.addAll(extinguish(adjacentPositions, b));
-        } else {
-            // Chercher la position du feu le plus proche
-            Position nearestFirePos = b.getNearestEntity(position, Fire.class);
-    
-            if (nearestFirePos != null && !nearestFirePos.equals(position)) {
-                // Trouver la meilleure position pour se rapprocher du feu
-                Position nextPos = getNextPositionTowards(position, nearestFirePos, b);
-    
-                if (nextPos != null) {
-                    // Mettre à jour la position du pompier
-                    b.clearCase(position); // Vider l'ancienne case
-                    positions.add(new Position(position.x(), position.y()));
-                    this.position = nextPos;
-                    b.setState(this, nextPos); // Mettre à jour la nouvelle case
-                    positions.add(nextPos);
-                    adjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b);
-                    positions.addAll(extinguish(adjacentPositions, b));
-                } 
-                // Aucun déplacement possible = le pompier reste sur place
-            }
-        }
-    
-        return positions;
-    }
-    
-    private List<Position> extinguish(List<Position> adjacentPositions, Board<Entity> b) {
-        List<Position> extinguishedPositions = new ArrayList<>();
-        for (Position p : adjacentPositions) {
-            if (b.getState(p) instanceof Fire) {
-                b.clearCase(p);
-                extinguishedPositions.add(p); // Ajouter la position où le feu a été éteint
-            }
-        }
-        return extinguishedPositions;
-    }
-    
-    private Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Entity> b) {
-        // Générer les 8 positions adjacentes possibles
-        List<Position> possibleMoves = PositionUtil.generateAllAdjacentPositions(currentPos, b);
-    
-        // Filtrer les positions qui sont libres
-        possibleMoves.removeIf(p -> !(b.getState(p) instanceof EmptySquare));
-    
-        // Si aucune position libre n'est disponible, retourner null
-        if (possibleMoves.isEmpty()) {
-            return null;
-        }
-    
-        // Calculer la distance actuelle vers la cible
-        int currentDistance = PositionUtil.getManhattanDistance(currentPos, targetPos);
-    
-        // Choisir la position libre qui réduit le plus la distance vers le feu
-        Position bestMove = null;
-        int minDistance = currentDistance;
-        for (Position move : possibleMoves) {
-            int distance = PositionUtil.getManhattanDistance(move, targetPos);
-            if (distance < minDistance) {
-                minDistance = distance;
-                bestMove = move;
-            }
-        }
-    
-        // Si aucun déplacement ne réduit la distance, annuler le déplacement
-        if (bestMove == null) {
-            return null;
-        }
-        return bestMove;
-    }
-    
-    
-    
-
-    @Override
-    public void setPosition(Position p) {
-        this.position = p;
-    }
-
-    @Override
-    public Position getPosition() {
-        return this.position;
-    }
-    public Color getViewColor(){
-        return this.viewColor;
-    }
-
-    @Override
-    public int getAge() {
-        return this.age;
-    }
-    @Override
-    public void incrementAge() {
-        this.age = age + 1 ;
-    }
-
-    
-}
diff --git a/src/main/java/model/FireFighterScenario.java b/src/main/java/model/FireFighterScenario.java
deleted file mode 100644
index ff4d8d870836c8a5a5b7dfd772adf1319f22662e..0000000000000000000000000000000000000000
--- a/src/main/java/model/FireFighterScenario.java
+++ /dev/null
@@ -1,175 +0,0 @@
-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<Entity> {
-
-  private Matrix<Entity> matrix;
-  private int step;
-
-  private int initialFireCount;
-  private int initialFireFightersCount;
-  public FireFighterScenario(int columns, int rows, int initialFireCount, int initialFireFightersCount) {
-    this.matrix = new Matrix<Entity>(columns, rows);
-    this.initialFireCount = initialFireCount;
-    this.initialFireFightersCount = initialFireFightersCount;
-    initScenario(matrix);
-    placeInitialActors(initialFireCount, initialFireFightersCount);
-    this.step = 0;
-  }
-
-  private void placeInitialActors(int initialFireCount, int initialFireFightersCount) {
-    int fireCount = 0;
-    int fireFighterCount = 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));
-      }
-    }
-
-    while (fireCount < initialFireCount || fireFighterCount < initialFireFightersCount) {
-      Collections.shuffle(positions); // Mélange les positions pour un parcours aléatoire
-
-      for (Position pos : positions) {
-        if (getState(pos) instanceof EmptySquare) {
-          if (fireCount < initialFireCount && random.nextInt(100) < chance) {
-            setState(new Fire(pos, this, 1), pos);
-            fireCount++;
-            if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount) {
-              return;
-            }
-            continue;
-          }
-
-          if (fireFighterCount < initialFireFightersCount && random.nextInt(100) < chance) {
-            setState(new FireFighter(pos, this, 1), pos);
-            fireFighterCount++;
-            if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount) {
-              return;
-            }
-          }
-        }
-      }
-
-      // Augmente la chance de placement après chaque parcours complet
-      chance = Math.min(chance + 5, 100); // Ne dépasse pas 100%
-    }
-  }
-
-  public Entity getState(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 setState(Entity state, Position position) {
-    if (!(getState(position) instanceof EmptySquare)) {
-      return;
-    }
-    if (doesPositionExist(position)) {
-      matrix.set(position.x(), position.y(), state);
-    }
-  }
-
-  public void setState(Entity state, Position position, boolean replaceStates) {
-    if (!(getState(position) instanceof EmptySquare) && !replaceStates) {
-      return;
-    }
-    matrix.set(position.x(), position.y(), state);
-  }
-
-  public int rowCount() {
-    return matrix.getRows();
-  }
-
-  public int columnCount() {
-    return matrix.getColumns();
-  }
-  @Override
-  public void clearCase(Position position){
-    setState(new EmptySquare(position, step+1), position, true);
-  }
-
-  public List<Position> updateToNextGeneration() {
-    ArrayList<Position> changedPositions = new ArrayList<>();
-    Iterator<Entity> iterator = matrix.iterator();
-    while (iterator.hasNext()) {
-      Entity e = iterator.next();
-      if (e instanceof EmptySquare)
-        continue;
-      if (e.getAge() == 0) {
-        e.incrementAge();
-        continue;
-      }
-      if(e.getAge() == step+1){
-        continue;
-      }
-      List<Position> entityUpdatedPositions = e.nextTurn(this);
-      e.incrementAge();
-      changedPositions.addAll(entityUpdatedPositions);
-    }
-    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) {
-        Entity currentEntity = matrix.get(currentPos.x(), currentPos.y());
-        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);
-  }
-
-  public int stepNumber() {
-    this.step = step + 1;
-    return this.step;
-  }
-
-  @Override
-  public boolean doesPositionExist(Position position) {
-    return matrix.validateIndex(position);
-  }
-
-  @Override
-  public int getStepNumber() {
-    return step;
-  }
-}
diff --git a/src/main/java/model/Model.java b/src/main/java/model/Model.java
new file mode 100644
index 0000000000000000000000000000000000000000..64bd75a7a9d95ae0a82f2fdfc0cc90e7034dec88
--- /dev/null
+++ b/src/main/java/model/Model.java
@@ -0,0 +1,10 @@
+package model;
+
+import java.util.List;
+
+import util.Position;
+
+public interface Model {
+    public List<Position> updateToNextGeneration();
+    public Board<Square> getBoard();
+}
diff --git a/src/main/java/model/Road.java b/src/main/java/model/Road.java
new file mode 100644
index 0000000000000000000000000000000000000000..e208d99a8f20bfbec11d75ae327f055f06472099
--- /dev/null
+++ b/src/main/java/model/Road.java
@@ -0,0 +1,73 @@
+package model;
+
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import model.firefighterscenario.Cloud;
+import util.Position;
+import view.ViewElement;
+
+public class Road implements Entity{
+    private int age;
+    private final int PRIORITY = 0;
+    private final Color VIEW_COLOR = Color.BLACK;
+    private Position position;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/route.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Road(Position position){
+        this.position = position;
+    }
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        return List.of();
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public int getAge() {
+        return age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age = age + 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.VIEW_COLOR;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.PRIORITY;
+    }
+
+    @Override
+    public ViewElement getViewElement(){
+        return new ViewElement(cloudImage);
+    }
+
+}
diff --git a/src/main/java/model/Scenario.java b/src/main/java/model/Scenario.java
index f4dfc48efe42a5c6945132194a404f757996beba..912f7fbb89abb070eab0b2c42cd202b5727c60f2 100644
--- a/src/main/java/model/Scenario.java
+++ b/src/main/java/model/Scenario.java
@@ -1,7 +1,165 @@
 package model;
 
+
+import java.util.List;
+import java.util.Map;
+
+import app.SimulatorApplication;
 import util.Matrix;
+import util.Position;
+import util.PositionUtil;
+
+public class Scenario implements Board<Square>{
+
+  private Matrix<Square> matrix;
+  protected int step;
+  protected int turnsToSpawnAirTanker;
+
+  protected 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);
+    
+  }
+
+  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) {
+    if(!matrix.get(position.x(), position.y()).getEntities().removeIf(element -> element.equals(entity))){
+      for(Entity e : getStates(position).getEntities()){
+        System.out.println(e);
+      }
+    }
+  }
+
+  public Position getNearestEntity(Position fromPos, Class<?> entityType, List<Entity> exclusionList) {
+    int rows = matrix.getRows();
+    int cols = matrix.getColumns();
+    if(exclusionList == null){
+      exclusionList = List.of();
+    }
+    // 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) {
+          if(isPositionEmpty(currentPos))continue;
+            Square currentSquare = matrix.get(currentPos.x(), currentPos.y());
+            for (Entity currentEntity : currentSquare.getEntities()) {
+                if (entityType.isInstance(currentEntity) && exclusionList != null && !exclusionList.contains(currentEntity)) {
+                    // Vérifie si l'entité actuelle n'est pas dans la liste des exclusions
+                    // Dès qu'une entité éligible est trouvée à cette distance, elle est la plus proche possible
+                    return currentPos;
+                }
+            }
+        }
+    }
+    return null; // Retourne null si aucune entité éligible 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;
+  }
 
-public interface Scenario {
-    public void initScenario(Matrix<Entity> matrix);
 }
diff --git a/src/main/java/model/Square.java b/src/main/java/model/Square.java
new file mode 100644
index 0000000000000000000000000000000000000000..50c9a839cefa34a4bea0da061346f9e44e8bfeeb
--- /dev/null
+++ b/src/main/java/model/Square.java
@@ -0,0 +1,93 @@
+package model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import util.Position;
+
+public class Square {
+    private List<Entity> entities;
+    private Position position;
+    public Square(Position position){
+        this.entities = new ArrayList<Entity>();
+        this.position = position;
+    }
+    public Square(Position position, Entity entity){
+        this.entities = new ArrayList<Entity>();
+        this.entities.add(entity);
+        this.position = position;
+    }
+
+    public List<Entity> getEntities(){
+        return this.entities;
+    }
+
+    public Position getPosition(){
+        return this.position;
+    }
+
+    public void addEntity(Entity entity){
+        entities.add(entity);
+    }
+
+    public void removeEntity(Entity entity){
+        entities.remove(entity);
+    }
+
+    public void setEntities(List<Entity> entities){
+        this.entities = entities;
+    }
+
+    public boolean isEmpty(){
+        return entities.isEmpty() ||(entities.size() == 1 && entities.get(0) instanceof EmptySquare);
+    }
+
+    public int getMinimalAge(){
+        int minimalAge = 0;
+        for(Entity e : entities){
+            if(e.getAge() < minimalAge){
+                minimalAge = e.getAge();
+            }
+        }
+        return minimalAge;
+    }
+
+    public int getMaxAge(){
+        int maxAge = 0;
+        for(Entity e : entities){
+            if(e.getAge() > maxAge){
+                maxAge = e.getAge();
+            }
+        }
+        return maxAge;
+    }
+
+    public void incrementAllAges(){
+        for(Entity e : entities){
+            e.incrementAge();
+        }
+    }
+
+    public Color getViewColor() {
+        if (entities.isEmpty()) {
+            return Color.WHITE;
+        } else {
+            int maxPriority = -1; // Assuming priorities are non-negative
+            Color c = Color.WHITE;
+            
+            // Iterate over entities to find the one with the highest priority
+            for (Entity e : entities) {
+                // Check for null entities if necessary
+                if (e != null && e.getPriority() > maxPriority) {
+                    maxPriority = e.getPriority();
+                    c = e.getViewColor();
+                }
+            }
+            return c;
+        }
+    }
+    
+    
+    
+}
diff --git a/src/main/java/model/doctorviruspatient/Doctor.java b/src/main/java/model/doctorviruspatient/Doctor.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb2d809abc762d4db9990b7d15f2c90d15e1b390
--- /dev/null
+++ b/src/main/java/model/doctorviruspatient/Doctor.java
@@ -0,0 +1,172 @@
+package model.doctorviruspatient;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Doctor implements Entity {
+    private final int priority = 1;
+    private Position position;
+    private int age;
+    private final Color viewColor = Color.RED;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/virus/docteur.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    // Statique car les médecins partagent les connaissances et les recherches
+    private static List<Integer> knownVirusVariant = new ArrayList<Integer>();
+    private static Map<Integer, Double> currentResearch = new HashMap<>(); // Map<variantId, % de recherche>
+
+    public Doctor(Position p) {
+        this.position = p;
+    }
+
+    public Doctor(Position p, int age) {
+        this.position = p;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        // Mettre à jour les recherches en cours
+        updateCurrentResearch();
+
+        // Interagir avec les positions adjacentes
+        interactWithAdjacentPositions(PositionUtil.generateAllAdjacentPositions(position, board), board);
+        
+        return List.of();
+    }
+
+    /**
+     * Met à jour toutes les recherches en cours en augmentant leur avancement de x%.
+     * Si une recherche atteint ou dépasse 100%, elle est terminée.
+     */
+    private void updateCurrentResearch() {
+        List<Integer> completedResearch = new ArrayList<>();
+        
+        for (Map.Entry<Integer, Double> entry : currentResearch.entrySet()) {
+            int variantId = entry.getKey();
+            double progress = entry.getValue() + 2.0;
+            if (progress >= 100.0) {
+                progress = 100.0;
+                completedResearch.add(variantId);
+            }
+            currentResearch.put(variantId, progress);
+        }
+
+        // Traiter les recherches complétées
+        for (int variantId : completedResearch) {
+            currentResearch.remove(variantId);
+            knownVirusVariant.add(variantId);
+            System.out.println("Recherche terminée pour le variant ID: " + variantId);
+        }
+    }
+
+    private List<Position> interactWithAdjacentPositions(List<Position> adjacentPositions, Board<Square> board) {
+        List<Position> result = new ArrayList<>();
+        for (Position p : adjacentPositions) {
+            if (board.doesSquareContainEntity(p, Patient.class)) {
+                handleEncounterWithPatient(p, board);
+            }
+        }
+        return result;
+    }
+
+    private void handleEncounterWithPatient(Position p, Board<Square> board) {
+        if (board.doesSquareContainEntity(p, Patient.class)) {
+            Patient patient = (Patient) board.getStates(p).getEntities().stream()
+                    .filter(e -> e instanceof Patient)
+                    .findFirst()
+                    .orElse(null);
+            if (patient != null && patient.isInfected()) {
+                Virus virus = patient.getVirus();
+                if (virus != null) {
+                    int variantId = virus.getVariantId();
+                    if (knownVirusVariant.contains(variantId)) {
+                        patient.cure();
+                    } else {
+                        // Si la variante n'est pas connue et pas en cours de recherche, l'ajouter à la recherche
+                        if (!currentResearch.containsKey(variantId)) {
+                            currentResearch.put(variantId, 0.0);
+                            System.out.println("Nouvelle variante détectée! Variant ID: " + variantId + ". Recherche commencée.");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Doctor) {
+            Doctor other = (Doctor) obj;
+            return this.position.equals(other.getPosition());
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(position);
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement (cloudImage);
+    }
+
+
+}
diff --git a/src/main/java/model/doctorviruspatient/DoctorVirusPatientScenario.java b/src/main/java/model/doctorviruspatient/DoctorVirusPatientScenario.java
new file mode 100644
index 0000000000000000000000000000000000000000..16e82608ee3584dc79aee63cc21369615de748dd
--- /dev/null
+++ b/src/main/java/model/doctorviruspatient/DoctorVirusPatientScenario.java
@@ -0,0 +1,60 @@
+package model.doctorviruspatient;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import model.Board;
+import model.Entity;
+import model.EntityFactory;
+import model.Model;
+import model.Scenario;
+import model.Square;
+import util.Position;
+
+
+
+public class DoctorVirusPatientScenario extends Scenario implements Model{
+    public DoctorVirusPatientScenario(int columns, int rows, Map<EntityFactory, Integer> initialMap) {
+        super(columns, rows, initialMap);
+    }
+    
+    public List<Position> updateToNextGeneration() {
+        ArrayList<Position> changedPositions = new ArrayList<>();
+        Iterator<Square> iterator = getMatrix().iterator();
+        while (iterator.hasNext()) {
+          Square s = iterator.next();
+          if (s.isEmpty())
+            continue;
+          if (s.getMaxAge() == 0) {
+            s.incrementAllAges();
+            continue;
+          }
+          if(s.getMaxAge()>stepNumber()+1){
+            continue;
+          }
+          List<Entity> entities = new ArrayList<>(s.getEntities());
+          for (Entity e : entities) {
+            e.incrementAge();
+            changedPositions.addAll(e.nextTurn(this));
+          }
+        }
+        
+        // Increment the step counter
+        this.step = this.step + 1;
+        return changedPositions;
+      }
+
+
+      
+    @Override
+    public Board<Square> getBoard() {
+        return this;
+    }
+
+
+
+
+
+}
diff --git a/src/main/java/model/doctorviruspatient/Patient.java b/src/main/java/model/doctorviruspatient/Patient.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e1387910f29240fffba163eec35593673304747
--- /dev/null
+++ b/src/main/java/model/doctorviruspatient/Patient.java
@@ -0,0 +1,358 @@
+package model.doctorviruspatient;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Random;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import util.PathGenerator;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Patient implements Entity {
+    private final int priority = 1;
+    private Position position;
+    private int age;
+    private final Color viewColor = Color.BLUE;
+    private Virus carriedVirus;
+    private List<Entity> visitedPatients;
+    private static int patientsCount = 0;
+    private int patientID;
+    private Position ennemy;
+    private boolean isAsymptomatic;
+    private boolean wandering;
+
+
+
+    private static javafx.scene.image.Image healthyImage;
+    private static javafx.scene.image.Image infectedImage;
+
+    static {
+        try {
+            healthyImage = new javafx.scene.image.Image(Patient.class.getResource("/view/icons/virus/humain.png").toExternalForm());
+            infectedImage = new javafx.scene.image.Image(Patient.class.getResource("/view/icons/virus/patient.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+
+    // Attributs pour le chemin
+    private List<Position> path;
+    private int pathIndex;
+    private static final int MAX_STEPS_IN_DIRECTION = 5;
+    private static final int MINIMUM_ROAD_LENGTH = 10;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/virus/humain.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Patient(Position p) {
+        this.wandering = true;
+        patientID = patientsCount;
+        patientsCount += 1;
+        this.visitedPatients = new ArrayList<>();
+        this.position = p;
+        Random r = new Random();
+        int randomNumber = r.nextInt(10);
+        this.isAsymptomatic = randomNumber == 1;
+        // Initialiser le chemin
+        this.path = new ArrayList<>();
+        this.pathIndex = 0;
+    }
+
+    public Patient(Position p, int age) {
+        this.wandering = true;
+        patientID = patientsCount;
+        patientsCount += 1;
+        this.visitedPatients = new ArrayList<>();
+        this.position = p;
+        this.age = age;
+        Random r = new Random();
+        int randomNumber = r.nextInt(10);
+        this.isAsymptomatic = randomNumber == 1;
+        // Initialiser le chemin
+        this.path = new ArrayList<>();
+        this.pathIndex = 0;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        if (isInfected() && !isAsymptomatic) {
+            return moveToDoctor(board);
+        }
+        updateWanderingStatus(board);
+
+        if (wandering) {
+            return performWandering(board);
+        }
+
+        resetVisitedPatientsIfNecessary();
+
+        Position target = determineTarget(board);
+
+        if (target == null) {
+            visitedPatients.clear();
+            return List.of();
+        }
+
+        Position nextPos = determineNextPosition(target, board);
+
+        if (nextPos != null && board.doesPositionExist(nextPos)) {
+
+            List<Position> adjacentPositions = PositionUtil.generateAllAdjacentPositions(nextPos, board);
+            List<Position> result = interactWithAdjacentPositions(adjacentPositions, board);
+            result.addAll(moveToPosition(nextPos, board));
+            result.addAll(adjacentPositions);
+            result.add(position);
+            return result;
+        }
+
+        return List.of();
+    }
+
+    private void updateWanderingStatus(Board<Square> board) {
+        if (board.getStepNumber() % 8 == 0) {
+            wandering = false;
+            // Réinitialiser le chemin lorsque le patient arrête d'errer
+            this.path.clear();
+            this.pathIndex = 0;
+        }
+    }
+
+    private List<Position> moveToDoctor(Board<Square> board) {
+        for (Position p : PositionUtil.generateAllAdjacentPositions(position, board)) {
+            if (!board.doesPositionExist(p)) continue;
+            if (board.doesSquareContainEntity(p, Doctor.class)) return List.of();
+        }
+        Position nearestDoctor = board.getNearestEntity(position, Doctor.class, null);
+        Position nextPos = PositionUtil.getNextPositionTowards(position, nearestDoctor, board);
+        if (nextPos == null) return List.of();
+
+        List<Position> changedPositions = new ArrayList<>();
+        changedPositions.addAll(moveToPosition(nextPos, board));
+        return changedPositions;
+    }
+
+    private List<Position> performWandering(Board<Square> board) {
+        if (path == null || path.isEmpty() || pathIndex >= path.size()) {
+            generateNewPath(board);
+            if (path.isEmpty()) {
+                return List.of();
+            }
+        }
+
+        Position nextPosition = path.get(pathIndex);
+
+        if (board.doesPositionExist(nextPosition) && board.isPositionFree(nextPosition, priority)) {
+            List<Position> changedPositions = moveSelfOnBoard(nextPosition, board);
+            pathIndex++;
+            return changedPositions;
+        } else {
+            // Si la position n'est pas libre ou n'existe pas, générer un nouveau chemin
+            generateNewPath(board);
+            return List.of();
+        }
+    }
+
+    private void generateNewPath(Board<Square> board) {
+        PathGenerator pathGenerator = new PathGenerator(board, position, MAX_STEPS_IN_DIRECTION, MINIMUM_ROAD_LENGTH);
+        this.path = pathGenerator.generate();
+        // Supprimer la position actuelle du chemin si elle est présente
+        if (!path.isEmpty() && path.get(0).equals(position)) {
+            path.remove(0);
+        }
+        this.pathIndex = 0;
+    }
+
+    private void resetVisitedPatientsIfNecessary() {
+        if (visitedPatients.size() - 1 >= patientsCount) {
+            visitedPatients.clear();
+        }
+    }
+
+    private Position determineTarget(Board<Square> board) {
+        return board.getNearestEntity(position, Patient.class, getVisitedPatients());
+    }
+
+    private Position determineNextPosition(Position target, Board<Square> board) {
+        int enemyDistance = PositionUtil.getManhattanDistance(target, position);
+
+        if (ennemy != null && enemyDistance < 2) {
+            return PositionUtil.getNextPositionAwayFrom(position, target, board);
+        } else if (target != null) {
+            return PositionUtil.getNextPositionTowards(position, target, board);
+        }
+        return null;
+    }
+
+    private List<Position> moveToPosition(Position nextPos, Board<Square> board) {
+        List<Position> changedPosition = new ArrayList<>();
+        if (!board.isPositionFree(nextPos, priority)) {
+            nextPos = findAlternativePosition(nextPos, board);
+        }
+
+        if (nextPos != null) {
+            changedPosition.addAll(moveSelfOnBoard(nextPos, board));
+        }
+
+        return changedPosition;
+    }
+
+    private Position findAlternativePosition(Position currentPos, Board<Square> board) {
+        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, board);
+        for (Position p : adjacentPositions) {
+            if (ennemy != null) {
+                Position awayPos = PositionUtil.getNextPositionAwayFrom(p, ennemy, board);
+                if (p.equals(awayPos)) {
+                    continue;
+                }
+            }
+            if (board.isPositionFree(p, priority)) {
+                return p;
+            }
+        }
+        return null;
+    }
+
+    private List<Position> moveSelfOnBoard(Position newPosition, Board<Square> board) {
+        if(!board.isPositionFree(newPosition, priority))return List.of();
+        Position oldPosition = new Position(this.position.x(), this.position.y());
+        board.clearCaseFrom(this, oldPosition);
+        board.addEntityAtSquare(this, newPosition);
+        this.position = newPosition;
+        return List.of(oldPosition, this.position);
+    }
+
+    private List<Position> interactWithAdjacentPositions(List<Position> adjacentPositions, Board<Square> board) {
+        List<Position> result = new ArrayList<>();
+        for (Position p : adjacentPositions) {
+            if (board.doesSquareContainEntity(p, Patient.class)) {
+                handleEncounterWithPatient(p, board);
+                if (isInfected()) {
+                    result.addAll(adjacentPositions);
+                }
+            }
+        }
+        return result;
+    }
+
+    private void handleEncounterWithPatient(Position p, Board<Square> board) {
+        this.wandering = true;
+        // Réinitialiser le chemin lorsqu'un patient est rencontré
+        this.path.clear();
+        this.pathIndex = 0;
+        Patient patient = (Patient) board.getStates(p).getEntities().stream()
+                .filter(entity -> entity instanceof Patient)
+                .findFirst()
+                .orElse(null);
+        if (isInfected()) {
+            patient.infect(carriedVirus);
+        }
+        if (patient != null) {
+            this.ennemy = patient.getPosition();
+            visitedPatients.add(patient);
+        }
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return isInfected() ? Color.CYAN : this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    public boolean isInfected() {
+        return this.carriedVirus != null;
+    }
+
+    public void infect(Virus virus) {
+        if (this.carriedVirus != null) return;
+        this.carriedVirus = virus;
+    }
+
+    public Virus getVirus() {
+        return this.carriedVirus;
+    }
+
+    public List<Entity> getVisitedPatients() {
+        return this.visitedPatients;
+    }
+
+    public boolean hasVisited(Patient patient) {
+        return this.getVisitedPatients().contains(patient);
+    }
+
+    public int getPatientId() {
+        return this.patientID;
+    }
+
+    public void cure() {
+        if (this.carriedVirus.tryToKill()) {
+            this.carriedVirus = null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Patient) {
+            Patient other = (Patient) obj;
+            return this.patientID == other.getPatientId();
+        } else {
+            return false;
+        }
+
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(patientID);
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return isInfected() ? new ViewElement(infectedImage) : new ViewElement(healthyImage);
+    }
+
+
+}
diff --git a/src/main/java/model/doctorviruspatient/Virus.java b/src/main/java/model/doctorviruspatient/Virus.java
new file mode 100644
index 0000000000000000000000000000000000000000..632b4258afba963d57cd1fc1d06262ae36f96e0e
--- /dev/null
+++ b/src/main/java/model/doctorviruspatient/Virus.java
@@ -0,0 +1,167 @@
+package model.doctorviruspatient;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import util.PathGenerator;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Virus implements Entity {
+    private final int priority = 2;
+    private Position position;
+    private int age;
+    private final Color viewColor = Color.LIMEGREEN;
+    private List<Position> path;
+    private int pathIndex;
+    private static final int MAX_STEPS_IN_DIRECTION = 5;
+    private static final int MINIMUM_ROAD_LENGTH = 10;
+    private int health;
+    private int variantId;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/virus/virus.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Virus(Position p) {
+        this.variantId = 0;
+        this.health = 50;
+        this.position = p;
+        this.path = new ArrayList<>();
+        this.age = 0;
+        this.pathIndex = 0;
+    }
+
+    public Virus(Position p, int age) {
+        this.health = 8;
+        this.position = p;
+        this.age = age;
+        this.path = new ArrayList<>();
+        this.pathIndex = 0;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        if(board.getStepNumber() % 100 == 0){
+            evolve();
+        }
+        // Génère un nouveau chemin si nécessaire
+        if (path == null || path.isEmpty() || pathIndex >= path.size()) {
+            generateNewPath(board);
+            if (path.isEmpty()) {
+                return List.of();           
+            }
+        }
+        List<Position> adjacentPosition = PositionUtil.generateAllAdjacentPositions(position, board);
+        for(Position p : adjacentPosition){
+            if(board.doesSquareContainEntity(p, Patient.class)){
+                Patient patient = (Patient) board.getStates(p).getEntities().stream().filter(e -> e instanceof Patient).findFirst().get();
+                patient.infect(this);
+            }
+        }
+        // Se déplace vers la prochaine position du chemin
+        Position nextPosition = path.get(pathIndex);
+        if (board.doesPositionExist(nextPosition)) {
+            // Vérifier si la position est libre
+            if (board.isPositionFree(nextPosition, priority)) {
+                Position oldPosition = position;
+                position = nextPosition;
+                board.clearCaseFrom(this, oldPosition);
+                board.addEntityAtSquare(this, position);
+                pathIndex = pathIndex + 1;
+                return List.of(oldPosition, position);
+            } else {
+                // Si la position n'est pas libre, génère un nouveau chemin
+                generateNewPath(board);
+                return List.of(); 
+            }
+        } else {
+            // Si la prochaine position n'existe pas, génère un nouveau chemin
+            generateNewPath(board);
+            return List.of();
+        }
+    }
+
+    private void generateNewPath(Board<Square> board) {
+        PathGenerator pathGenerator = new PathGenerator(board, position, MAX_STEPS_IN_DIRECTION, MINIMUM_ROAD_LENGTH);
+        this.path = pathGenerator.generate();
+        // Supprime la position actuelle du chemin si elle est présente au début
+        if (!path.isEmpty() && path.get(0).equals(position)) {
+            path.remove(0);
+        }
+        this.pathIndex = 0; // Réinitialise l'index du chemin
+    }
+
+    // Les autres méthodes restent inchangées
+    private void evolve(){
+        this.variantId++;
+        Random r = new Random();
+        this.health = r.nextInt(100);
+    }
+
+    public int getVariantId(){
+        return this.variantId;
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    public boolean tryToKill(){
+        if(health <= 0){
+            return true;
+        }
+        health--;
+        return false;
+    }
+
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+
+}
diff --git a/src/main/java/model/firefighterscenario/AirTanker.java b/src/main/java/model/firefighterscenario/AirTanker.java
new file mode 100644
index 0000000000000000000000000000000000000000..130850ac5509eca671da995d13c77c4d07d78cfc
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/AirTanker.java
@@ -0,0 +1,180 @@
+package model.firefighterscenario;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import util.Direction;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class AirTanker implements Entity{
+    private final Color viewColor = Color.GOLD;
+    private Direction direction; // Direction in which the AirTanker moves
+    private int age;
+    private Position position;
+    private int priority = 3;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/avion.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public AirTanker(Position position, Board<Square> b, int age) {
+        this.age = age;
+        this.position = position;
+        determineDirection(b);
+        extinguish(position,b);
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    private void determineDirection(Board<Square> b) {
+        int rowCount = b.rowCount();
+        int columnCount = b.columnCount();
+
+        if (position.x() == 0) {
+            direction = Direction.EAST; // Move east if on left edge
+        } else if (position.x() == columnCount - 1) {
+            direction = Direction.WEST; // Move west if on right edge
+        } else if (position.y() == 0) {
+            direction = Direction.SOUTH; // Move south if on top edge
+        } else if (position.y() == rowCount - 1) {
+            direction = Direction.NORTH; // Move north if on bottom edge
+        } else {
+            // Not on an edge; default to moving east or choose a random direction
+            direction = Direction.EAST;
+        }
+    }
+
+    @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
+            b.clearCaseFrom(this, position);
+            positions.add(position);
+            return positions;
+        } else {
+            // Extinguish fires within a 3-square radius
+
+            positions.addAll(extinguish(position, b));
+            // Move to the next position
+            b.clearCaseFrom(this, position);
+            positions.add(new Position(position.x(), position.y())); // Old position
+            this.position = nextPos;
+            b.addEntityAtSquare(this, nextPos);
+            positions.add(nextPos); // New position
+
+            return positions;
+        }
+    }
+    protected List<Position> extinguish(Position position, Board<Square> b){
+        List<Position> positions = new ArrayList<Position>();
+        List<Position> positionsInRange = PositionUtil.getPositionsInRadius(position, 3, b);
+        for (Position p : positionsInRange) {
+            if (b.doesSquareContainEntity(p, Fire.class)) {
+                b.getStates(p).getEntities().removeIf(e -> e instanceof Fire);
+                positions.add(p); // Add position where fire was extinguished
+            }
+        }
+        return positions;
+    }
+    private Position getNextPosition(Position currentPosition, Direction direction, Board<Square> b) {
+        int x = currentPosition.x();
+        int y = currentPosition.y();
+
+        switch (direction) {
+            case NORTH:
+                y -= 1;
+                break;
+            case SOUTH:
+                y += 1;
+                break;
+            case EAST:
+                x += 1;
+                break;
+            case WEST:
+                x -= 1;
+                break;
+            default:
+                break; // Only handling cardinal directions
+        }
+        Position newPos = new Position(x, y);
+        if (b.doesPositionExist(newPos)) {
+            return newPos;
+        } else {
+            return null; // Reached the edge
+        }
+    }
+
+    public Direction getDirection(){
+        return this.direction;
+    }
+
+        @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age++;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true; // Check if same object
+        if (obj == null || getClass() != obj.getClass()) return false; // Check for null and class match
+        AirTanker airTanker = (AirTanker) obj; // Cast to Fire
+        return age == airTanker.age && position.equals(airTanker.position); // Compare age and position
+    }
+    
+    
+    @Override
+    public int hashCode() {
+        return Objects.hash(position, age);
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+}
diff --git a/src/main/java/model/firefighterscenario/Cloud.java b/src/main/java/model/firefighterscenario/Cloud.java
new file mode 100644
index 0000000000000000000000000000000000000000..99caef1fe965b3093cf7f4b04bb520d18193ab85
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/Cloud.java
@@ -0,0 +1,126 @@
+package model.firefighterscenario;
+
+import java.util.List;
+import java.util.Random;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.EmptySquare;
+import model.Entity;
+import model.Square;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Cloud implements Entity{
+    private int age;
+    private Position position;
+    private final Color viewColor = Color.GRAY;
+    private final int priority = 2;
+
+    private static javafx.scene.image.Image cloudImage;
+    
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/nuage.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    public Cloud(Position position, Board<Square> b){
+        this.age = 0;
+        this.position = position;
+
+    }
+
+    public Cloud(Position position, Board<Square> b, int age){
+        this.age = age;
+        this.position = position;
+
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> b) {
+        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b);
+        adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Cloud.class));
+        adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class));
+
+        // Filtrer pour obtenir uniquement les positions qui ne contiennent pas de pompier
+        adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, FireFighter.class));
+
+        // Choisir une position aléatoire parmi les mouvements possibles
+        if(adjacentPositions.size() < 0){
+            return List.of();
+        }
+        Position next_position = adjacentPositions.get(new Random().nextInt(adjacentPositions.size()));
+
+        // Si la nouvelle position contient un feu, éteindre le feu
+        if (b.getStates(next_position).getEntities().stream().anyMatch(element -> element instanceof Fire) ){
+            extinguish(next_position, b);
+        }
+        
+        Position old_position = this.position;
+        this.position = next_position;
+        b.addEntityAtSquare(this, next_position);
+        b.clearCaseFrom(this, old_position);
+
+        return List.of(old_position, this.position);
+    }
+
+
+    private Position extinguish(Position p, Board<Square> b) {
+        b.getStates(p).getEntities().removeIf(element -> element instanceof Fire);
+            List<Entity> entities = b.getStates(p).getEntities();
+            for (Entity e : entities) {
+                if (e instanceof EmptySquare) {
+                    e.setAge(b.stepNumber() + 1);
+                }
+            }
+
+        return p;
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public int getAge() {
+        return age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age =age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority(){ 
+        return this.priority;
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+
+
+
+}
diff --git a/src/main/java/model/firefighterscenario/Fire.java b/src/main/java/model/firefighterscenario/Fire.java
new file mode 100644
index 0000000000000000000000000000000000000000..05f4b9874df8e830646f680d08b8c4696ff96b61
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/Fire.java
@@ -0,0 +1,151 @@
+package model.firefighterscenario;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Road;
+import model.Square;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+
+public class Fire implements Entity {
+    private Position position;
+    private final Color viewColor = Color.RED;
+    private int age;
+    private final int priority = 1;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/flamme.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Fire(Position position) {
+        this.position = position;
+        this.age = 0;
+    }
+
+    public Fire(Position position, int age) {
+        this.position = position;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        List<Position> newFirePositions = new ArrayList<>();
+        if(board.getStepNumber() <= 1){
+            return newFirePositions;
+        }
+        // Fire propagates every 2 turns
+        if (age % 2 != 0) {
+            return newFirePositions; // No propagation this turn
+        }
+
+        // Generate adjacent positions
+        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, board);
+        
+        for (Position p : adjacentPositions) {
+            // Skip if position does not exist
+            if (!board.doesPositionExist(p)) {
+                continue;
+            }
+
+            // Skip if the position contains a Mountain
+            if (board.doesSquareContainEntity(p, Mountain.class)) {
+                continue;
+            }
+
+            // Skip if the position already contains a Fire
+            if (board.doesSquareContainEntity(p, Fire.class)) {
+                continue;
+            }
+
+            // Skip if the position contains a Cloud (if clouds prevent fire spread)
+            if (board.doesSquareContainEntity(p, Road.class)) {
+                continue;
+            }
+            if (board.doesSquareContainEntity(p, Rockery.class)) {
+                Optional<Entity> e = board.getStates(p).getEntities().stream().findFirst();
+                if(e != null && e.isPresent() && e.get() instanceof Rockery){
+                    Rockery rockery = (Rockery) e.get();
+                    if(rockery.getBurn() < 4){
+                        rockery.incrementBurn();
+                        continue;
+                    }
+                    
+                }
+            }
+
+            // Add new Fire to the board
+            board.addEntityAtSquare(new Fire(p), p);
+            newFirePositions.add(p); // Keep track of new fires for updates
+        }
+
+        return newFirePositions;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age++;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true; // Check if same object
+        if (obj == null || getClass() != obj.getClass()) return false; // Check for null and class match
+        Fire fire = (Fire) obj; // Cast to Fire
+        return age == fire.age && position.equals(fire.position); // Compare age and position
+    }
+    
+    
+    @Override
+    public int hashCode() {
+        return Objects.hash(position, age);
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+
+}
diff --git a/src/main/java/model/firefighterscenario/FireFighter.java b/src/main/java/model/firefighterscenario/FireFighter.java
new file mode 100644
index 0000000000000000000000000000000000000000..7403803f0ea2731ded1113656b0c62b6ffd5cd00
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/FireFighter.java
@@ -0,0 +1,242 @@
+package model.firefighterscenario;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.EmptySquare;
+import model.Entity;
+import model.Square;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+
+
+public class FireFighter implements Entity {
+    private int age;
+    private Position position;
+    private final Color viewColor = Color.BLUE;
+    private final int priority = 1;
+    protected List<Position> lastThreePosition;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/sapeur-pompier.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public FireFighter(Position position, Board<Square> b) {
+        this.position = position;
+        this.age = 0;
+        this.lastThreePosition = new ArrayList<Position>();
+    }
+
+    public FireFighter(Position position, Board<Square> b, int age) {
+        this.position = position;
+        this.age = age;
+        this.lastThreePosition = new ArrayList<Position>();
+    }
+
+    public List<Position> nextTurn(Board<Square> b) {
+        List<Position> positions = new ArrayList<>();
+    
+        // Generate adjacent positions, excluding mountains
+        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b);
+        adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+    
+        // Check if there is fire in any adjacent positions
+        boolean hasFire = adjacentPositions.stream()
+                .anyMatch(p -> b.doesSquareContainEntity(p, Fire.class));
+    
+        boolean isStuck = isStuck();
+    
+        if (hasFire) {
+            // Extinguish fires in adjacent positions
+            positions.addAll(extinguish(adjacentPositions, b));
+            if (isStuck) {
+                // If stuck, attempt to move and then extinguish fires
+                positions.addAll(moveAndExtinguish(b));
+            }
+        } else {
+            // No fire adjacent; move and attempt to extinguish fires
+            positions.addAll(moveAndExtinguish(b));
+        }
+    
+        // Update last three positions
+        updateLastPositions();
+    
+        return positions;
+    }
+    
+    protected boolean isStuck() {
+        if (lastThreePosition.size() < 3) {
+            return false;
+        }
+        Position first = lastThreePosition.get(lastThreePosition.size() - 1);
+        return lastThreePosition.stream().allMatch(pos -> pos.equals(first));
+    }
+    
+    private void updateLastPositions() {
+        if (lastThreePosition.size() >= 3) {
+            lastThreePosition.remove(0);
+        }
+        lastThreePosition.add(this.position);
+    }
+    
+
+    protected List<Position> extinguish(List<Position> adjacentPositions, Board<Square> b) {
+        List<Position> extinguishedPositions = new ArrayList<>();
+        for (Position p : adjacentPositions) {
+            if (b.doesSquareContainEntity(p, Fire.class)) {
+                if(b.doesSquareContainEntity(p, Rockery.class)){
+                    Rockery rockery = (Rockery) b.getStates(p).getEntities().stream()
+                    .filter(Rockery.class::isInstance)
+                    .findFirst().get();
+                    rockery.resetBurn();
+                }
+                b.getStates(p).getEntities().removeIf(element -> element instanceof Fire);
+                // Update age for EmptyEntity if needed
+                b.getStates(p).getEntities().forEach(e -> {
+                    if (e instanceof EmptySquare) {
+                        e.setAge(b.stepNumber() + 1);
+                    }
+                });
+                extinguishedPositions.add(p); // Add position where fire was extinguished
+            }
+        }
+        return extinguishedPositions;
+    }
+    
+
+    protected List<Position> moveAndExtinguish(Board<Square> b) {
+        List<Position> positions = new ArrayList<>();
+    
+        // Find the nearest fire
+        Position nearestFirePos;
+        try {
+            nearestFirePos = b.getNearestEntity(position, Fire.class, null);
+        } catch (Exception e) {
+            return List.of();
+        }
+        if (nearestFirePos != null) {
+            // Get the next position towards the fire
+            Position nextPos = getNextPositionTowards(position, nearestFirePos, b);
+            if (nextPos != null && !nextPos.equals(position)) {
+                // Move the firefighter
+                b.clearCaseFrom(this, position); // Clear old position
+                positions.add(new Position(position.x(), position.y())); // Add old position
+                this.position = nextPos;
+                b.addEntityAtSquare(this, nextPos); // Add to new position
+                positions.add(nextPos); // Add new position
+    
+                // After moving, attempt to extinguish fires adjacent to new position
+                List<Position> newAdjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b);
+                newAdjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+                positions.addAll(extinguish(newAdjacentPositions, b));
+            }
+        }
+        return positions;
+    }
+    
+    protected Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Square> b) {
+        // Generate adjacent positions
+        List<Position> possibleMoves = PositionUtil.generateAllAdjacentPositions(currentPos, b);
+    
+        // Filter out positions that are not empty or contain obstacles
+        possibleMoves.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+    
+        // If no possible moves, return null
+        if (possibleMoves.isEmpty()) {
+            return null;
+        }
+    
+        // Calculate the current distance to the target
+        int currentDistance = PositionUtil.getManhattanDistance(currentPos, targetPos);
+    
+        // Initialize variables to find the best moves
+        int minDistance = Integer.MAX_VALUE;
+        List<Position> bestMoves = new ArrayList<>();
+    
+        for (Position move : possibleMoves) {
+            int distance = PositionUtil.getManhattanDistance(move, targetPos);
+    
+            // Skip positions occupied by other firefighters
+            if (b.doesSquareContainEntity(move, FireFighter.class)) {
+                continue;
+            }
+    
+            // Find positions that minimize the distance
+            if (distance < minDistance) {
+                minDistance = distance;
+                bestMoves.clear();
+                bestMoves.add(move);
+            } else if (distance == minDistance) {
+                bestMoves.add(move);
+            }
+        }
+    
+        // If no better move is found, consider moves that maintain the same distance
+        if (bestMoves.isEmpty()) {
+            minDistance = currentDistance;
+            for (Position move : possibleMoves) {
+                int distance = PositionUtil.getManhattanDistance(move, targetPos);
+                if (distance == minDistance) {
+                    bestMoves.add(move);
+                }
+            }
+        }
+    
+        // If still no move is found, stay in the current position
+        if (bestMoves.isEmpty()) {
+            return currentPos;
+        }
+    
+        // Select a move from the best moves (e.g., randomly or based on additional criteria)
+        Random r = new Random();
+        
+        Position nextMove = bestMoves.get(r.nextInt(bestMoves.size()));
+    
+        return nextMove;
+    }
+    
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age = age + 1;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+    public int getPriority(){ return this.priority;}
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+}
diff --git a/src/main/java/model/firefighterscenario/FireFighterScenario.java b/src/main/java/model/firefighterscenario/FireFighterScenario.java
new file mode 100644
index 0000000000000000000000000000000000000000..05167eaa47d815d2d26e8384bd36cdb59495160d
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/FireFighterScenario.java
@@ -0,0 +1,151 @@
+package model.firefighterscenario;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import model.Board;
+import model.Entity;
+import model.EntityFactory;
+import model.Model;
+import model.Road;
+import model.Scenario;
+import model.Square;
+import util.PathGenerator;
+import util.Position;
+
+public class FireFighterScenario extends Scenario implements Model{
+  public FireFighterScenario(int columns, int rows, Map<EntityFactory, Integer> initialMap) {
+    super(columns, rows, initialMap);
+    generateRoads();
+  }
+
+  public List<Position> updateToNextGeneration() {
+    ArrayList<Position> changedPositions = new ArrayList<>();
+    Iterator<Square> iterator = getMatrix().iterator();
+    List<Entity> updatedEntities = new ArrayList<Entity>();
+    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) {
+        if(updatedEntities.contains(e))continue;
+        if (e.getAge() >= stepNumber() - 1) {
+          continue;
+        }
+        e.incrementAge();
+        updatedEntities.add(e);
+        changedPositions.addAll(e.nextTurn(this));
+      }
+    }
+
+    // Increment the step counter
+    this.step = this.step + 1;
+
+    // Check if it's time to spawn an AirTanker
+    if (this.step % this.turnsToSpawnAirTanker == 0) {
+      // Spawn an AirTanker at a random edge position
+      spawnAirTanker(changedPositions);
+    }
+
+    return changedPositions;
+  }
+
+  // Helper method to spawn an AirTanker
+  private void spawnAirTanker(List<Position> changedPositions) {
+    Random rand = new Random();
+    int edge = rand.nextInt(4); // 0: top, 1: bottom, 2: left, 3: right
+    Position position = null;
+
+    if (edge == 0) { // Top edge (x == 0)
+      int y = rand.nextInt(columnCount() - 1);
+      position = new Position(0, y);
+    } else if (edge == 1) { // Bottom edge (x == rowCount() - 1)
+      int y = rand.nextInt(columnCount());
+      position = new Position(rowCount() - 1, y);
+    } else if (edge == 2) { // Left edge (y == 0)
+      int x = rand.nextInt(rowCount() - 1);
+      position = new Position(x, 0);
+    } else if (edge == 3) { // Right edge (y == columnCount() - 1)
+      int x = rand.nextInt(rowCount() - 1);
+      position = new Position(x, columnCount() - 1);
+    } else {
+      // This else block is technically not necessary because edge will always be
+      // between 0 and 3
+      throw new IllegalStateException("Unexpected edge value: " + edge);
+    }
+
+    // Create a new AirTanker
+    AirTanker airTanker = new AirTanker(position, this, getStepNumber());
+    // Add the AirTanker to the board
+    addEntityAtSquare(airTanker, position);
+
+    // Record the changed position
+    changedPositions.add(position);
+  }
+
+  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);
+    }
+}
+
+  @Override
+  public Board<Square> getBoard() {
+    return this;
+  }
+
+  public void reset() {
+    step = 0;
+    super.getMatrix().clear();
+    initScenario(super.getMatrix());
+    placeInitialEntities(initialMap);
+    generateRoads();
+  }
+
+}
diff --git a/src/main/java/model/firefighterscenario/MotorizedFireFighter.java b/src/main/java/model/firefighterscenario/MotorizedFireFighter.java
new file mode 100644
index 0000000000000000000000000000000000000000..904a3387a1b86b46d03ddea6b7d48eb6c5fc5da5
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/MotorizedFireFighter.java
@@ -0,0 +1,132 @@
+package model.firefighterscenario;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Square;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class MotorizedFireFighter extends FireFighter {
+    private final Color viewColor = Color.CYAN;
+    private static javafx.scene.image.Image cloudImage;
+
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/camion.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public MotorizedFireFighter(Position position, Board<Square> b) {
+        super(position, b);
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> b) {
+        List<Position> positions = new ArrayList<>();
+
+        // Generate adjacent positions excluding mountains
+        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(getPosition(), b);
+        adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+
+        // Check if there is fire in any adjacent positions
+        boolean hasFire = adjacentPositions.stream()
+                .anyMatch(p -> b.doesSquareContainEntity(p, Fire.class));
+
+        boolean isStuck = isStuck();
+
+        if (hasFire) {
+            // Extinguish fires in adjacent positions
+            positions.addAll(extinguish(adjacentPositions, b));
+
+            if (isStuck) {
+                // If stuck, attempt to move and extinguish after moving
+                positions.addAll(moveAndExtinguish(b));
+            }
+        } else {
+            // No fire adjacent; move and attempt to extinguish fires
+            positions.addAll(moveAndExtinguish(b));
+        }
+
+        // Update last positions for stuck detection
+        updateLastPositions();
+
+        return positions;
+    }
+
+    @Override
+    protected List<Position> moveAndExtinguish(Board<Square> b) {
+        List<Position> positions = new ArrayList<>();
+
+        // Find the nearest fire
+        Position nearestFirePos;
+        try {
+            nearestFirePos = b.getNearestEntity(getPosition(), Fire.class, null);
+        } catch (Exception e) {
+            return List.of();
+        }
+        if (nearestFirePos != null) {
+            // Get the next position after moving up to two steps towards the fire
+            Position nextPos = getNextPositionTowards(getPosition(), nearestFirePos, b, 2);
+
+            if (nextPos != null && !nextPos.equals(getPosition())) {
+                // Move the firefighter
+                b.clearCaseFrom(this, getPosition()); // Clear old position
+                positions.add(new Position(getPosition().x(), getPosition().y())); // Add old position
+                setPosition(nextPos);
+                b.addEntityAtSquare(this, nextPos); // Add to new position
+                positions.add(nextPos); // Add new position
+
+                // After moving, attempt to extinguish fires adjacent to new position
+                List<Position> newAdjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b);
+                newAdjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+                positions.addAll(extinguish(newAdjacentPositions, b));
+            }
+        }
+
+        return positions;
+    }
+
+    // Overloaded method to handle multiple steps
+    protected Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Square> b, int steps) {
+        Position nextPos = currentPos;
+
+        for (int i = 0; i < steps; i++) {
+            Position stepPos = super.getNextPositionTowards(nextPos, targetPos, b);
+
+            if (stepPos == null || stepPos.equals(nextPos)) {
+                // Can't move further
+                break;
+            }
+
+            nextPos = stepPos;
+        }
+
+        return nextPos;
+    }
+
+    // Override to ensure correct color
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    // Ensure the last positions are updated correctly
+    protected void updateLastPositions() {
+        if (lastThreePosition.size() >= 3) {
+            lastThreePosition.remove(0);
+        }
+        lastThreePosition.add(this.getPosition());
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/model/firefighterscenario/Mountain.java b/src/main/java/model/firefighterscenario/Mountain.java
new file mode 100644
index 0000000000000000000000000000000000000000..f8bd49c0f4a94c4c3f2deb1db85fc82670ec3f15
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/Mountain.java
@@ -0,0 +1,82 @@
+package model.firefighterscenario;
+
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import util.Position;
+import view.ViewElement;
+
+public class Mountain implements Entity{
+    private final int priority = 0;
+    Position position;
+    private int age;
+    private final Color viewColor = Color.CHOCOLATE;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/montagne.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Mountain(Position p ){
+        this.position = p;
+    }
+
+
+    public Mountain(Position p ,  int age){
+        this.position = p;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        return List.of();
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+}
diff --git a/src/main/java/model/firefighterscenario/Rockery.java b/src/main/java/model/firefighterscenario/Rockery.java
new file mode 100644
index 0000000000000000000000000000000000000000..26b0856a4089a35b61e36e4032292ea5a1c5b08f
--- /dev/null
+++ b/src/main/java/model/firefighterscenario/Rockery.java
@@ -0,0 +1,97 @@
+package model.firefighterscenario;
+
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import util.Position;
+import view.ViewElement;
+
+public class Rockery implements Entity{
+    private final int priority = 0;
+    Position position;
+    private int age;
+    private int burn;
+    private final Color viewColor = Color.LIMEGREEN;
+    private static javafx.scene.image.Image cloudImage;
+
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/rochers.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Rockery(Position p ){
+        this.position = p;
+        this.burn = 0;
+    }
+
+
+    public Rockery(Position p , int age){
+        System.out.println("age : " + age);
+        this.position = p;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        return List.of();
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+    public int getBurn(){
+        return this.burn;
+    }
+    public void incrementBurn(){
+        this.burn = burn + 1;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+
+    public void resetBurn() {
+        this.burn = 0;
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+}
diff --git a/src/main/java/model/rockpapercisor/Cisor.java b/src/main/java/model/rockpapercisor/Cisor.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ab152ea50dc664b7054bb91c221051570bd675d
--- /dev/null
+++ b/src/main/java/model/rockpapercisor/Cisor.java
@@ -0,0 +1,141 @@
+package model.rockpapercisor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Cisor implements Entity {
+    private final int priority = 0;
+    Position position;
+    private int age;
+    private final Color viewColor = Color.RED;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/pfc/cis.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Cisor(Position p) {
+        this.position = p;
+    }
+
+    public Cisor(Position p, int age) {
+        this.position = p;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        Position target = null;
+        target = board.getNearestEntity(position, Paper.class, null);
+
+        Position ennemy = null;
+
+        ennemy = board.getNearestEntity(position, Rock.class, null);
+        if(ennemy == null && target == null){
+            return List.of();
+        }
+        Position nextPos = null;
+        // Vérifier la proximité d'un ennemi avant de choisir la direction.
+        if (ennemy != null && PositionUtil.getManhattanDistance(position, ennemy) < 5) {
+            nextPos = PositionUtil.getNextPositionAwayFrom(position, ennemy, board);
+        } else if(target != null){
+            nextPos = PositionUtil.getNextPositionTowards(position, target, board);
+        }
+
+        if (nextPos != null && board.doesPositionExist(nextPos)) {
+            board.addEntityAtSquare(this, nextPos);
+            board.clearCaseFrom(this, position);
+            Position oldPosition = new Position(position.x(), position.y());
+            this.position = nextPos;
+            if (board.doesSquareContainEntity(nextPos, Paper.class)) {
+                List<Entity> entities = board.getStates(nextPos).getEntities();
+                entities.removeIf(p -> p instanceof Paper);
+            }
+
+            List<Position> result = new ArrayList<>();
+            if (target != null)
+                result.add(target);
+            if (oldPosition != null)
+                result.add(oldPosition);
+            if (position != null)
+                result.add(position);
+            if (ennemy != null)
+                result.add(ennemy);
+            return result;
+
+        }
+        return List.of();
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        Cisor cisor = (Cisor) obj;
+        return age == cisor.age &&
+                Objects.equals(position, cisor.position);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(position, age);
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+
+}
diff --git a/src/main/java/model/rockpapercisor/Paper.java b/src/main/java/model/rockpapercisor/Paper.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f972a30e2e18fcf11ab89700ae7798cc19aa01e
--- /dev/null
+++ b/src/main/java/model/rockpapercisor/Paper.java
@@ -0,0 +1,123 @@
+package model.rockpapercisor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Paper implements Entity {
+    private final int priority = 0;
+    Position position;
+    private int age;
+    private final Color viewColor = Color.GRAY;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/pfc/paper.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Paper(Position p) {
+        this.position = p;
+    }
+
+    public Paper(Position p, int age) {
+        this.position = p;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        Position target = null;
+        target = board.getNearestEntity(position, Rock.class, null);
+
+        Position ennemy = null;
+        ennemy = board.getNearestEntity(position, Cisor.class, null);
+        if(ennemy == null && target == null){
+            return List.of();
+        }
+        Position nextPos = null;
+        // Vérifier la proximité d'un ennemi avant de choisir la direction.
+        if (ennemy != null && PositionUtil.getManhattanDistance(position, ennemy) < 5) {
+            nextPos = PositionUtil.getNextPositionAwayFrom(position, ennemy, board);
+        } else if(target != null){
+            nextPos = PositionUtil.getNextPositionTowards(position, target, board);
+        }
+
+        if (nextPos != null && board.doesPositionExist(nextPos)) {
+            board.addEntityAtSquare(this, nextPos);
+            board.clearCaseFrom(this, position);
+            Position oldPosition = new Position(position.x(), position.y());
+            this.position = nextPos;
+            if (board.doesSquareContainEntity(nextPos, Rock.class)) {
+                List<Entity> entities = board.getStates(nextPos).getEntities();
+                entities.removeIf(p -> p instanceof Rock);
+            }
+
+            List<Position> result = new ArrayList<>();
+            if (target != null)
+                result.add(target);
+            if (oldPosition != null)
+                result.add(oldPosition);
+            if (position != null)
+                result.add(position);
+            if (ennemy != null)
+                result.add(ennemy);
+            return result;
+
+        }
+        return List.of();
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    @Override
+    public ViewElement getViewElement() {
+        return new ViewElement(cloudImage);
+    }
+
+}
diff --git a/src/main/java/model/rockpapercisor/Rock.java b/src/main/java/model/rockpapercisor/Rock.java
new file mode 100644
index 0000000000000000000000000000000000000000..459c0e6895594f1f2b296f31483c487c5939d18f
--- /dev/null
+++ b/src/main/java/model/rockpapercisor/Rock.java
@@ -0,0 +1,124 @@
+package model.rockpapercisor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.scene.paint.Color;
+import model.Board;
+import model.Entity;
+import model.Square;
+import model.firefighterscenario.Cloud;
+import util.Position;
+import util.PositionUtil;
+import view.ViewElement;
+
+public class Rock implements Entity {
+    private final int priority = 0;
+    Position position;
+    private int age;
+    private final Color viewColor = Color.CHOCOLATE;
+    private static javafx.scene.image.Image cloudImage;
+
+    static {
+        try {
+            cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/pfc/rock.png").toExternalForm());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Rock(Position p) {
+        this.position = p;
+    }
+
+    public Rock(Position p, int age) {
+        this.position = p;
+        this.age = age;
+    }
+
+    @Override
+    public List<Position> nextTurn(Board<Square> board) {
+        Position target = null;
+        target = board.getNearestEntity(position, Cisor.class, null);
+
+        Position ennemy = null;
+        ennemy = board.getNearestEntity(position, Paper.class, null);
+
+        if(ennemy == null && target == null){
+            return List.of();
+        }
+        Position nextPos = null;
+        // Vérifier la proximité d'un ennemi avant de choisir la direction.
+        if (ennemy != null && PositionUtil.getManhattanDistance(position, ennemy) < 5) {
+            nextPos = PositionUtil.getNextPositionAwayFrom(position, ennemy, board);
+        } else if(target != null){
+            nextPos = PositionUtil.getNextPositionTowards(position, target, board);
+        }
+
+        if (nextPos != null && board.doesPositionExist(nextPos)) {
+            board.addEntityAtSquare(this, nextPos);
+            board.clearCaseFrom(this, position);
+            Position oldPosition = new Position(position.x(), position.y());
+            this.position = nextPos;
+            if (board.doesSquareContainEntity(nextPos, Cisor.class)) {
+                List<Entity> entities = board.getStates(nextPos).getEntities();
+                entities.removeIf(p -> p instanceof Cisor);
+            }
+
+            List<Position> result = new ArrayList<>();
+            if (target != null)
+                result.add(target);
+            if (oldPosition != null)
+                result.add(oldPosition);
+            if (position != null)
+                result.add(position);
+            if (ennemy != null)
+                result.add(ennemy);
+            return result;
+
+        }
+        return List.of();
+    }
+
+    @Override
+    public Position getPosition() {
+        return this.position;
+    }
+
+    @Override
+    public void setPosition(Position p) {
+        this.position = p;
+
+    }
+
+    @Override
+    public int getAge() {
+        return this.age;
+    }
+
+    @Override
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public void incrementAge() {
+        this.age += 1;
+    }
+
+    @Override
+    public Color getViewColor() {
+        return this.viewColor;
+    }
+
+    @Override
+    public int getPriority() {
+        return this.priority;
+    }
+
+    @Override
+    public ViewElement getViewElement(){
+        return new ViewElement(cloudImage);
+    }
+
+}
diff --git a/src/main/java/model/rockpapercisor/RockPaperCisorScenario.java b/src/main/java/model/rockpapercisor/RockPaperCisorScenario.java
new file mode 100644
index 0000000000000000000000000000000000000000..40207fddbd23605e56252ac9113341c9b7df4217
--- /dev/null
+++ b/src/main/java/model/rockpapercisor/RockPaperCisorScenario.java
@@ -0,0 +1,55 @@
+package model.rockpapercisor;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import model.Board;
+import model.Entity;
+import model.EntityFactory;
+import model.Model;
+import model.Scenario;
+import model.Square;
+import util.Position;
+
+public class RockPaperCisorScenario extends Scenario implements Model{
+    public RockPaperCisorScenario(int columns, int rows, Map<EntityFactory, Integer> initialMap) {
+        super(columns, rows, initialMap);
+    }
+
+    public List<Position> updateToNextGeneration() {
+        ArrayList<Position> changedPositions = new ArrayList<>();
+        Iterator<Square> iterator = getMatrix().iterator();
+        while (iterator.hasNext()) {
+          Square s = iterator.next();
+          if (s.isEmpty())
+            continue;
+          if (s.getMaxAge() == 0) {
+            s.incrementAllAges();
+            continue;
+          }
+          if(s.getMaxAge()>stepNumber()+1){
+            continue;
+          }
+          List<Entity> entities = new ArrayList<>(s.getEntities());
+          for (Entity e : entities) {
+            e.incrementAge();
+            changedPositions.addAll(e.nextTurn(this));
+          }
+        }
+        
+        // Increment the step counter
+        this.step = this.step + 1;
+        return changedPositions;
+      }
+
+    @Override
+    public Board<Square> getBoard() {
+        return this;
+    }
+
+
+
+
+}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 4c36d97709b342e457203c75d081fc5cc1955c0f..1bd3e9a86156ea98b4650fee627b4411b90ff3fd 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -2,7 +2,8 @@ module firefighter {
   requires javafx.controls;
   requires javafx.fxml;
   requires javafx.graphics;
-  opens controller to javafx.fxml;
+    requires java.sql;
+    opens controller to javafx.fxml;
   exports app;
   opens app to javafx.fxml;
 }
diff --git a/src/main/java/util/Direction.java b/src/main/java/util/Direction.java
new file mode 100644
index 0000000000000000000000000000000000000000..471e8e7e31dbf1cbcc9eafdad645455bf4e07252
--- /dev/null
+++ b/src/main/java/util/Direction.java
@@ -0,0 +1,5 @@
+package util;
+
+public enum Direction {
+    NORTH, EAST, WEST, SOUTH
+}
diff --git a/src/main/java/util/DirectionUtils.java b/src/main/java/util/DirectionUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1daaeac1941f5fc6437868f42fa709ba2bc2bf0
--- /dev/null
+++ b/src/main/java/util/DirectionUtils.java
@@ -0,0 +1,109 @@
+package util;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import model.Board;
+import model.Square;
+
+public class DirectionUtils {
+    
+    /**
+     * Obtient l'incrément sur l'axe X pour une direction donnée.
+     *
+     * @param direction La direction.
+     * @return L'incrément sur l'axe X.
+     */
+    public static int getXIncrement(Direction direction) {
+        switch (direction) {
+            case NORTH:
+                return -1;
+            case SOUTH:
+                return 1;
+            default:
+                return 0;
+        }
+    }
+
+    /**
+     * Obtient l'incrément sur l'axe Y pour une direction donnée.
+     *
+     * @param direction La direction.
+     * @return L'incrément sur l'axe Y.
+     */
+    public static int getYIncrement(Direction direction) {
+        switch (direction) {
+            case EAST:
+                return 1;
+            case WEST:
+                return -1;
+            default:
+                return 0;
+        }
+    }
+
+    /**
+     * Obtient la direction opposée.
+     *
+     * @param direction La direction actuelle.
+     * @return La direction opposée.
+     */
+    public static Direction getOpposite(Direction direction) {
+        switch (direction) {
+            case NORTH:
+                return Direction.SOUTH;
+            case SOUTH:
+                return Direction.NORTH;
+            case EAST:
+                return Direction.WEST;
+            case WEST:
+                return Direction.EAST;
+            default:
+                throw new IllegalArgumentException("Direction non supportée : " + direction);
+        }
+    }
+
+    /**
+     * Choisit une direction aléatoire parmi toutes les directions disponibles.
+     *
+     * @param random Instance de Random.
+     * @return Une direction aléatoire.
+     */
+    public static Direction getRandomDirection() {
+        Random r = new Random();
+        Direction[] directions = Direction.values();
+        return directions[r.nextInt(directions.length)];
+    }
+
+    /**
+     * Obtient les directions valides en fonction des exclusions et de la position actuelle.
+     *
+     * @param currentDirection              La direction actuelle.
+     * @param permanentlyExcludedDirections Les directions définitivement exclues.
+     * @param temporarilyExcludedDirections Les directions temporairement exclues.
+     * @param board                         Le plateau de jeu.
+     * @param currentPosition               La position actuelle.
+     * @return Une liste de directions valides.
+     */
+    public static List<Direction> getValidDirections(
+            Direction currentDirection,
+            Set<Direction> permanentlyExcludedDirections,
+            Set<Direction> temporarilyExcludedDirections,
+            Board<Square> board,
+            Position currentPosition
+    ) {
+        return Arrays.stream(Direction.values())
+                .filter(dir -> dir != currentDirection)
+                .filter(dir -> dir != getOpposite(currentDirection))
+                .filter(dir -> !permanentlyExcludedDirections.contains(dir))
+                .filter(dir -> !temporarilyExcludedDirections.contains(dir))
+                .filter(dir -> {
+                    Position nextPos = currentPosition.move(dir);
+                    return board.doesPositionExist(nextPos);
+                })
+                .collect(Collectors.toList());
+    }
+}
diff --git a/src/main/java/util/Matrix.java b/src/main/java/util/Matrix.java
index 6b5000be034cb782b77e941f7114ad37ab49b38d..5ed290f0c31f3134d241fb49e3d716fb3bd0f874 100644
--- a/src/main/java/util/Matrix.java
+++ b/src/main/java/util/Matrix.java
@@ -1,9 +1,15 @@
 package util;
 
+
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
+import model.Square;
+import model.doctorviruspatient.Patient;
+import model.firefighterscenario.Fire;
+import model.firefighterscenario.FireFighter;
+
 public class Matrix<E> implements Iterable<E> {
     private ArrayList<ArrayList<E>> matrix;
     private final int rows;
@@ -59,7 +65,7 @@ public class Matrix<E> implements Iterable<E> {
         return this.rows;
     }
 
-    /*
+    
     public void displayMatrix() {
         System.out.print("  ");
         for (int j = 0; j < columns; j++) {
@@ -71,11 +77,18 @@ public class Matrix<E> implements Iterable<E> {
             System.out.print("| ");
             for (int j = 0; j < columns; j++) {
                 if (matrix.get(i).get(j) != null) {
-                    if(matrix.get(i).get(j) instanceof Fire){
+                    Square s = (Square) matrix.get(i).get(j);
+                    if(s.getEntities().stream().anyMatch(p -> p instanceof Fire)){
                         System.out.print(" F | ");
                     }   
-                    else if(matrix.get(i).get(j) instanceof FireFighter){
+                    else if(s.getEntities().stream().anyMatch(p -> p instanceof FireFighter)){
                         System.out.print(" ff | ");
+                    }
+                    else if(s.getEntities().stream().anyMatch(p -> p instanceof Patient)){
+                        System.out.print(" P | ");
+                    }
+                    else if(s.getEntities().stream().anyMatch(p -> p instanceof model.doctorviruspatient.Virus)){
+                        System.out.print(" V | ");
                     }else{
                         System.out.print("  | ");
                     }
@@ -92,7 +105,7 @@ public class Matrix<E> implements Iterable<E> {
             System.out.println();
         }
     }
-    */
+    
 
     private void validateIndex(int x, int y) {
         if (x < 0 || x >= rows || y < 0 || y >= columns) {
diff --git a/src/main/java/util/PathGenerator.java b/src/main/java/util/PathGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..148116237eb0cc1ac4c04c91d23be3b5cb836543
--- /dev/null
+++ b/src/main/java/util/PathGenerator.java
@@ -0,0 +1,191 @@
+package util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import model.Board;
+
+public class PathGenerator {
+    private Board<?> board;
+    private final Random random = new Random();
+    private final int maxStepsInDirection;
+    private final int minimumRoadLength;
+    private final Set<Direction> initialExcludedDirections = new HashSet<>();
+    private final Position anchor;
+
+    private Position currentPosition;
+    private Direction currentDirection;
+    private Direction excludedDirection = null;
+    private Direction lastDirection = null;
+    private int stepsInCurrentDirection = 0;
+    private int roadLength = 1;
+    private final List<Position> path = new ArrayList<>();
+
+    /**
+     * Constructeur de PathGenerator.
+     *
+     * @param board               Le plateau de jeu.
+     * @param anchor              La position de départ.
+     * @param maxStepsInDirection Nombre maximal de pas dans une direction avant de changer.
+     * @param minimumRoadLength   Longueur minimale du chemin.
+     */
+    public PathGenerator(Board<?> board, Position anchor, int maxStepsInDirection, int minimumRoadLength) {
+        this.board = board;
+        this.anchor = anchor;
+        this.maxStepsInDirection = maxStepsInDirection;
+        this.minimumRoadLength = minimumRoadLength;
+        initializePath();
+    }
+
+    /**
+     * Génère le chemin en respectant les contraintes.
+     *
+     * @return Liste des positions formant le chemin.
+     */
+    public List<Position> generate() {
+        while (true) {
+            if (canMoveInCurrentDirection()) {
+                moveInCurrentDirection();
+                if (shouldChangeDirection()) {
+                    if (!changeDirection(false)) break;
+                }
+            } else {
+                if (!handleObstacle()) break;
+            }
+        }
+        return roadLength >= minimumRoadLength ? path : regeneratePath();
+    }
+    public void setBoard(Board<?> board){
+        this.board = board;
+    }
+    /** Initialise le chemin avec l'ancre et choisit la première direction. */
+    private void initializePath() {
+        path.clear();
+        roadLength = 1;
+        stepsInCurrentDirection = 0;
+        currentPosition = anchor;
+        path.add(anchor);
+        currentDirection = DirectionUtils.getRandomDirection();
+        initialExcludedDirections.clear();
+        initialExcludedDirections.add(currentDirection);
+        lastDirection = currentDirection;
+        excludedDirection = null;
+    }
+
+    /** Vérifie si le mouvement dans la direction actuelle est possible. */
+    private boolean canMoveInCurrentDirection() {
+        Position nextPosition = currentPosition.move(currentDirection);
+        return board.doesPositionExist(nextPosition);
+    }
+
+    /** Effectue le mouvement dans la direction actuelle. */
+    private void moveInCurrentDirection() {
+        currentPosition = currentPosition.move(currentDirection);
+        path.add(currentPosition);
+        roadLength++;
+        stepsInCurrentDirection++;
+        excludedDirection = DirectionUtils.getOpposite(currentDirection);
+    }
+
+    /** Détermine si un changement de direction est nécessaire. */
+    private boolean shouldChangeDirection() {
+        return stepsInCurrentDirection >= maxStepsInDirection;
+    }
+
+    /**
+     * Change la direction actuelle.
+     *
+     * @param mustContinue Si true, la nouvelle direction doit permettre de continuer le chemin.
+     * @return true si la direction a été changée avec succès, sinon false.
+     */
+    private boolean changeDirection(boolean mustContinue) {
+        Direction newDirection = chooseNewDirection(mustContinue);
+        if (newDirection == null) return false;
+        updateDirection(newDirection);
+        return true;
+    }
+
+    /** Gère le cas où le mouvement n'est pas possible (obstacle ou bord du plateau). */
+    private boolean handleObstacle() {
+        if (roadLength < minimumRoadLength) {
+            return changeDirection(true);
+        }
+        return false;
+    }
+
+    /** Réinitialise et génère à nouveau le chemin. */
+    private List<Position> regeneratePath() {
+        initializePath();
+        return generate();
+    }
+
+    /** Met à jour la direction actuelle et les compteurs associés. */
+    private void updateDirection(Direction newDirection) {
+        currentDirection = newDirection;
+        stepsInCurrentDirection = 0;
+        lastDirection = newDirection;
+        excludedDirection = DirectionUtils.getOpposite(newDirection);
+    }
+
+    /**
+     * Choisit une nouvelle direction valide en tenant compte des exclusions.
+     *
+     * @param mustContinue Si true, la direction doit permettre de continuer le chemin.
+     * @return La nouvelle direction choisie ou null si aucune n'est valide.
+     */
+    private Direction chooseNewDirection(boolean mustContinue) {
+        Set<Direction> exclusions = new HashSet<>(initialExcludedDirections);
+        Collections.addAll(exclusions, excludedDirection, lastDirection);
+        List<Direction> validDirections = getValidDirections(exclusions, currentPosition);
+
+        if (mustContinue) {
+            validDirections = filterDirectionsToContinue(validDirections, currentPosition);
+        }
+
+        return validDirections.isEmpty() ? null : validDirections.get(random.nextInt(validDirections.size()));
+    }
+
+    /**
+     * Obtient les directions valides à partir de la position actuelle.
+     *
+     * @param exclusions       Les directions à exclure.
+     * @param currentPosition  La position actuelle.
+     * @return Liste des directions valides.
+     */
+    private List<Direction> getValidDirections(Set<Direction> exclusions, Position currentPosition) {
+        List<Direction> validDirections = new ArrayList<>();
+        for (Direction dir : Direction.values()) {
+            if (!exclusions.contains(dir)) {
+                Position nextPos = currentPosition.move(dir);
+                if (board.doesPositionExist(nextPos)) {
+                    validDirections.add(dir);
+                }
+            }
+        }
+        return validDirections;
+    }
+
+    /**
+     * Filtre les directions pour s'assurer qu'elles permettent de continuer le chemin.
+     *
+     * @param directions      Liste des directions valides.
+     * @param currentPosition La position actuelle.
+     * @return Liste des directions permettant de continuer.
+     */
+    private List<Direction> filterDirectionsToContinue(List<Direction> directions, Position currentPosition) {
+        List<Direction> filtered = new ArrayList<>();
+        for (Direction dir : directions) {
+            Position nextPos = currentPosition.move(dir);
+            Set<Direction> futureExclusions = new HashSet<>(initialExcludedDirections);
+            futureExclusions.add(DirectionUtils.getOpposite(dir));
+            if (!getValidDirections(futureExclusions, nextPos).isEmpty()) {
+                filtered.add(dir);
+            }
+        }
+        return filtered;
+    }
+}
diff --git a/src/main/java/util/Position.java b/src/main/java/util/Position.java
index 389b8214dbc56af0914084e8fa7e68cd3c1b2e72..d6407fadb846754bdfb63ef8b4a5966dd78f25e1 100644
--- a/src/main/java/util/Position.java
+++ b/src/main/java/util/Position.java
@@ -1,5 +1,10 @@
 package util;
 
 public record Position(int x, int y) {
-
+        // Méthode pour déplacer la position dans une direction donnée
+        public Position move(Direction direction) {
+            int newX = this.x + DirectionUtils.getXIncrement(direction);
+            int newY = this.y + DirectionUtils.getYIncrement(direction);
+            return new Position(newX, newY);
+        }
 }
diff --git a/src/main/java/util/PositionUtil.java b/src/main/java/util/PositionUtil.java
index 48f5436d9856cd14eb84baf631f8391e8b26bdfe..096c290d4560c1edbf0d73da67370422515e64da 100644
--- a/src/main/java/util/PositionUtil.java
+++ b/src/main/java/util/PositionUtil.java
@@ -2,11 +2,14 @@ package util;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Random;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import model.Board;
-import model.Entity;
+import model.Square;
+import model.firefighterscenario.FireFighter;
+import model.firefighterscenario.Mountain;
 
 public class PositionUtil {
     /**
@@ -61,7 +64,7 @@ public class PositionUtil {
      *                 si une position existe.
      * @return une liste des positions adjacentes valides.
      */
-    public static List<Position> generateAdjacentPositions(Position position, Board<Entity> board) {
+    public static List<Position> generateAdjacentPositions(Position position, Board<Square> board) {
         int x = position.x();
         int y = position.y();
 
@@ -74,9 +77,19 @@ public class PositionUtil {
                 .collect(Collectors.toList());
     }
 
+    public static List<Position> generateAdjacentPositions(Position position, Board<Square> board, int distance) {
+
+        List<Position> positions = new ArrayList<Position>();
+        for(int i = 0; i < 4; i++){
+
+        }
+        return positions;
+    }
+
+
     // Méthode pour générer toutes les positions adjacentes (y compris les
     // diagonales)
-    public static List<Position> generateAllAdjacentPositions(Position position, Board<Entity> board) {
+    public static List<Position> generateAllAdjacentPositions(Position position, Board<Square> board) {
         int x = position.x();
         int y = position.y();
 
@@ -110,4 +123,202 @@ public class PositionUtil {
         return Math.abs(p1.x() - p2.x()) + Math.abs(p1.y() - p2.y());
     }
 
+        /**
+     * Generates all positions within a specified radius from a center position.
+     * It uses Manhattan distance by default.
+     *
+     * @param center The center position.
+     * @param radius The radius (distance) from the center position.
+     * @param board  The board to consider boundaries.
+     * @return A list of positions within the radius.
+     */
+    public static List<Position> getPositionsInRadius(Position center, int radius, Board<Square> board) {
+        List<Position> positions = new ArrayList<>();
+
+        int startX = center.x() - radius;
+        int endX = center.x() + radius;
+        int startY = center.y() - radius;
+        int endY = center.y() + radius;
+
+        for (int x = startX; x <= endX; x++) {
+            for (int y = startY; y <= endY; y++) {
+                Position pos = new Position(x, y);
+                if (board.doesPositionExist(pos)) {
+                    // Calculate Manhattan distance from the center
+                    int distance = Math.abs(center.x() - x) + Math.abs(center.y() - y);
+                    if (distance <= radius) {
+                        positions.add(pos);
+                    }
+                }
+            }
+        }
+
+        return positions;
+    }
+
+
+    public static Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Square> b) {
+        // Generate adjacent positions
+        List<Position> possibleMoves = PositionUtil.generateAllAdjacentPositions(currentPos, b);
+    
+        // Filter out positions that are not empty or contain obstacles
+        possibleMoves.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+    
+        // If no possible moves, return null
+        if (possibleMoves.isEmpty()) {
+            return null;
+        }
+    
+        // Calculate the current distance to the target
+        int currentDistance = PositionUtil.getManhattanDistance(currentPos, targetPos);
+    
+        // Initialize variables to find the best moves
+        int minDistance = Integer.MAX_VALUE;
+        List<Position> bestMoves = new ArrayList<>();
+    
+        for (Position move : possibleMoves) {
+            int distance = PositionUtil.getManhattanDistance(move, targetPos);
+    
+            // Skip positions occupied by other firefighters
+            if (b.doesSquareContainEntity(move, FireFighter.class)) {
+                continue;
+            }
+    
+            // Find positions that minimize the distance
+            if (distance < minDistance) {
+                minDistance = distance;
+                bestMoves.clear();
+                bestMoves.add(move);
+            } else if (distance == minDistance) {
+                bestMoves.add(move);
+            }
+        }
+    
+        // If no better move is found, consider moves that maintain the same distance
+        if (bestMoves.isEmpty()) {
+            minDistance = currentDistance;
+            for (Position move : possibleMoves) {
+                int distance = PositionUtil.getManhattanDistance(move, targetPos);
+                if (distance == minDistance) {
+                    bestMoves.add(move);
+                }
+            }
+        }
+    
+        // If still no move is found, stay in the current position
+        if (bestMoves.isEmpty()) {
+            return currentPos;
+        }
+    
+        // Select a move from the best moves (e.g., randomly or based on additional criteria)
+        Random r = new Random();
+        
+        Position nextMove = bestMoves.get(r.nextInt(bestMoves.size()));
+    
+        return nextMove;
+    }
+
+    public static Position getNextPositionAwayFrom(Position currentPos, Position targetPos, Board<Square> b) {
+        // Générer les positions adjacentes
+        List<Position> possibleMoves = PositionUtil.generateAllAdjacentPositions(currentPos, b);
+    
+        // Filtrer les positions qui ne sont pas vides ou contiennent des obstacles
+        possibleMoves.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
+    
+        // Si aucune possibilité de déplacement, retourner null
+        if (possibleMoves.isEmpty()) {
+            return null;
+        }
+    
+        // Calculer la distance actuelle par rapport à la cible
+        int currentDistance = PositionUtil.getManhattanDistance(currentPos, targetPos);
+    
+        // Initialiser les variables pour trouver les meilleurs déplacements
+        int maxDistance = Integer.MIN_VALUE;
+        List<Position> bestMoves = new ArrayList<>();
+    
+        for (Position move : possibleMoves) {
+            int distance = PositionUtil.getManhattanDistance(move, targetPos);
+    
+            // Ignorer les positions occupées par d'autres entités, comme les pompiers
+            if (b.doesSquareContainEntity(move, FireFighter.class)) {
+                continue;
+            }
+    
+            // Trouver les positions qui maximisent la distance
+            if (distance > maxDistance) {
+                maxDistance = distance;
+                bestMoves.clear();
+                bestMoves.add(move);
+            } else if (distance == maxDistance) {
+                bestMoves.add(move);
+            }
+        }
+    
+        // Si aucun meilleur déplacement n'est trouvé, considérer les mouvements qui maintiennent la même distance
+        if (bestMoves.isEmpty()) {
+            maxDistance = currentDistance;
+            for (Position move : possibleMoves) {
+                int distance = PositionUtil.getManhattanDistance(move, targetPos);
+                if (distance == maxDistance) {
+                    bestMoves.add(move);
+                }
+            }
+        }
+    
+        // Si toujours aucun mouvement n'est trouvé, rester à la position actuelle
+        if (bestMoves.isEmpty()) {
+            return currentPos;
+        }
+    
+        // Sélectionner un mouvement parmi les meilleurs mouvements (par exemple aléatoirement ou selon des critères supplémentaires)
+        Random r = new Random();
+    
+        Position nextMove = bestMoves.get(r.nextInt(bestMoves.size()));
+    
+        return nextMove;
+    }
+    public static Direction getOppositeDirection(Direction direction) {
+        switch (direction) {
+            case NORTH: return Direction.SOUTH;
+            case SOUTH: return Direction.NORTH;
+            case EAST:  return Direction.WEST;
+            case WEST:  return Direction.EAST;
+            default:    throw new IllegalArgumentException("Direction non supportée : " + direction);
+        }
+    }
+
+    /**
+ * Détermine la direction principale (NORTH, SOUTH, EAST, WEST) de toPos par rapport à fromPos.
+ *
+ * @param fromPos la position de départ.
+ * @param toPos   la position de destination.
+ * @return la direction principale de toPos par rapport à fromPos.
+ */
+public static Direction getDirectionFromTwoPoints(Position fromPos, Position toPos) {
+    int deltaX = toPos.x() - fromPos.x();
+    int deltaY = toPos.y() - fromPos.y();
+
+    if (deltaX == 0 && deltaY == 0) {
+        return null; // Les positions sont identiques
+    }
+
+    if (Math.abs(deltaX) > Math.abs(deltaY)) {
+        // Mouvement principalement vers l'Est ou l'Ouest
+        if (deltaX > 0) {
+            return Direction.EAST;
+        } else {
+            return Direction.WEST;
+        }
+    } else {
+        // Mouvement principalement vers le Nord ou le Sud
+        if (deltaY > 0) {
+            return Direction.SOUTH;
+        } else {
+            return Direction.NORTH;
+        }
+    }
+}
+
+
 }
\ No newline at end of file
diff --git a/src/main/java/view/FirefighterGrid.java b/src/main/java/view/FirefighterGrid.java
index e5061a3b16c98a44bfa670cb6423dc2b61dbf22f..210b737b11125956c79027096210a7e90d873953 100644
--- a/src/main/java/view/FirefighterGrid.java
+++ b/src/main/java/view/FirefighterGrid.java
@@ -1,16 +1,30 @@
 package view;
-
 import java.util.List;
 
 import javafx.scene.canvas.Canvas;
+import javafx.scene.image.Image;
 import javafx.scene.paint.Color;
 import javafx.util.Pair;
 import util.Position;
 
 public class FirefighterGrid extends Canvas implements Grid<ViewElement> {
 
+    //private void paintElementAtPosition(ViewElement element, Position position) {
+      //  paintBox(position.x(), position.y(), element.getColor());
+    //}
+
+
     private void paintElementAtPosition(ViewElement element, Position position) {
-        paintBox(position.x(), position.y(), element.getColor());
+        // Efface la case pour éviter les superpositions
+        clearBox(position.x(), position.y());
+
+        // Vérifie si une image est définie dans l'élément
+        if (element.getImage() != null) {
+            Image image = element.getImage();
+            getGraphicsContext2D().drawImage(image, position.y() * boxWidth, position.x() * boxHeight, boxWidth, boxHeight);
+        } else {
+            paintBox(position.x(), position.y(), element.getColor());
+        }
     }
 
     private int boxWidth;
diff --git a/src/main/java/view/Grid.java b/src/main/java/view/Grid.java
index b95d59f622a86b41f2a41261b8b27aaf2e911dfb..c0754aedc8933a5f2a4b2983d680aa56150a87ef 100644
--- a/src/main/java/view/Grid.java
+++ b/src/main/java/view/Grid.java
@@ -12,44 +12,44 @@ import java.util.List;
  */
 public interface Grid<E> {
 
-  /**
-   * Repaint the grid with a list of elements, each associated with their respective positions.
-   *
-   * @param elements A list of pairs, each containing a position and the element to be displayed at that position.
-   */
-  void repaint(List<Pair<Position, E>> elements);
-
-  /**
-   * Repaint the grid with a two-dimensional array of elements. The array's dimensions should match
-   * the row and column count of the grid.
-   *
-   * @param elements A two-dimensional array of elements to be displayed on the grid.
-   */
-  void repaint(E[][] elements);
-
-  /**
-   * Set the dimensions of the grid to the specified number of columns, number of rows, square width,
-   * and square height.
-   *
-   * @param columnCount The new number of columns in the grid.
-   * @param rowCount The new number of rows in the grid.
-   * @param squareWidth The width of each square within the grid.
-   * @param squareHeight The height of each square within the grid.
-   */
-  void setDimensions(int columnCount, int rowCount, int squareWidth, int squareHeight);
-
-  /**
-   * Get the number of columns in the grid.
-   *
-   * @return The number of columns in the grid.
-   */
-  int columnCount();
-
-  /**
-   * Get the number of rows in the grid.
-   *
-   * @return The number of rows in the grid.
-   */
-  int rowCount();
+    /**
+     * Repaint the grid with a list of elements, each associated with their respective positions.
+     *
+     * @param elements A list of pairs, each containing a position and the element to be displayed at that position.
+     */
+    void repaint(List<Pair<Position, E>> elements);
+
+    /**
+     * Repaint the grid with a two-dimensional array of elements. The array's dimensions should match
+     * the row and column count of the grid.
+     *
+     * @param elements A two-dimensional array of elements to be displayed on the grid.
+     */
+    void repaint(E[][] elements);
+
+    /**
+     * Set the dimensions of the grid to the specified number of columns, number of rows, square width,
+     * and square height.
+     *
+     * @param columnCount  The new number of columns in the grid.
+     * @param rowCount     The new number of rows in the grid.
+     * @param squareWidth  The width of each square within the grid.
+     * @param squareHeight The height of each square within the grid.
+     */
+    void setDimensions(int columnCount, int rowCount, int squareWidth, int squareHeight);
+
+    /**
+     * Get the number of columns in the grid.
+     *
+     * @return The number of columns in the grid.
+     */
+    int columnCount();
+
+    /**
+     * Get the number of rows in the grid.
+     *
+     * @return The number of rows in the grid.
+     */
+    int rowCount();
 }
 
diff --git a/src/main/java/view/ViewElement.java b/src/main/java/view/ViewElement.java
index 5043644547213f648760eba9e4bb0693411e527b..3059a474eba08dc25e8e0e9cb8a186344a5c85c1 100644
--- a/src/main/java/view/ViewElement.java
+++ b/src/main/java/view/ViewElement.java
@@ -1,15 +1,29 @@
 package view;
 
+import javafx.scene.image.Image;
 import javafx.scene.paint.Color;
 
 public class ViewElement {
     private final Color color;
+    private final Image image;
 
+    // Constructeur avec couleur uniquement
     public ViewElement(Color color) {
         this.color = color;
+        this.image = null;
+    }
+
+    // Constructeur avec image
+    public ViewElement(Image image) {
+        this.color = null;
+        this.image = image;
     }
 
     public Color getColor() {
         return color;
     }
+
+    public Image getImage() {
+        return image;
+    }
 }
diff --git a/src/main/resources/view/icons/fire/avion.png b/src/main/resources/view/icons/fire/avion.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a5d9a690230ddb0a55e5f4050faf69af578341b
Binary files /dev/null and b/src/main/resources/view/icons/fire/avion.png differ
diff --git a/src/main/resources/view/icons/fire/camion.png b/src/main/resources/view/icons/fire/camion.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3a361c84dc686238486079ae477cf346214528f
Binary files /dev/null and b/src/main/resources/view/icons/fire/camion.png differ
diff --git a/src/main/resources/view/icons/fire/flamme.png b/src/main/resources/view/icons/fire/flamme.png
new file mode 100644
index 0000000000000000000000000000000000000000..0784e111e8761e9c2bacc9102eecc62b97bbf58b
Binary files /dev/null and b/src/main/resources/view/icons/fire/flamme.png differ
diff --git a/src/main/resources/view/icons/fire/img.png b/src/main/resources/view/icons/fire/img.png
new file mode 100644
index 0000000000000000000000000000000000000000..f765539c06aafd59b0c2fc1a09fc389f9996410c
Binary files /dev/null and b/src/main/resources/view/icons/fire/img.png differ
diff --git a/src/main/resources/view/icons/fire/montagne.png b/src/main/resources/view/icons/fire/montagne.png
new file mode 100644
index 0000000000000000000000000000000000000000..cf970e54796b833d6e28678344d48b48bf02f2ad
Binary files /dev/null and b/src/main/resources/view/icons/fire/montagne.png differ
diff --git a/src/main/resources/view/icons/fire/nuage.png b/src/main/resources/view/icons/fire/nuage.png
new file mode 100644
index 0000000000000000000000000000000000000000..308714e9a1c1acafcf230fef7f7e4a79ccc0e49d
Binary files /dev/null and b/src/main/resources/view/icons/fire/nuage.png differ
diff --git a/src/main/resources/view/icons/fire/rochers.png b/src/main/resources/view/icons/fire/rochers.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c43a47397f45827363ed17e2bdbf1e651a3c864
Binary files /dev/null and b/src/main/resources/view/icons/fire/rochers.png differ
diff --git a/src/main/resources/view/icons/fire/route.png b/src/main/resources/view/icons/fire/route.png
new file mode 100644
index 0000000000000000000000000000000000000000..fb3ba6dc051837260312bc0d168c2a9952788a32
Binary files /dev/null and b/src/main/resources/view/icons/fire/route.png differ
diff --git a/src/main/resources/view/icons/fire/sapeur-pompier.png b/src/main/resources/view/icons/fire/sapeur-pompier.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2e592c7475ce7f1b4747300ee9e8f4f1fd1d345
Binary files /dev/null and b/src/main/resources/view/icons/fire/sapeur-pompier.png differ
diff --git a/src/main/resources/view/icons/pfc/cis.png b/src/main/resources/view/icons/pfc/cis.png
new file mode 100644
index 0000000000000000000000000000000000000000..646b9f7b984a658b64051266f3aaf4b26fa13b21
Binary files /dev/null and b/src/main/resources/view/icons/pfc/cis.png differ
diff --git a/src/main/resources/view/icons/pfc/paper.png b/src/main/resources/view/icons/pfc/paper.png
new file mode 100644
index 0000000000000000000000000000000000000000..4c3f80c1ccdd8709ac1240f2bc9d36705500efc3
Binary files /dev/null and b/src/main/resources/view/icons/pfc/paper.png differ
diff --git a/src/main/resources/view/icons/pfc/rock.png b/src/main/resources/view/icons/pfc/rock.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e0bc082f7231fad12300e0cabf87a988e4aa33e
Binary files /dev/null and b/src/main/resources/view/icons/pfc/rock.png differ
diff --git a/src/main/resources/view/icons/virus/docteur.png b/src/main/resources/view/icons/virus/docteur.png
new file mode 100644
index 0000000000000000000000000000000000000000..902a90c30e5eea76c075246b2573f4480704ed64
Binary files /dev/null and b/src/main/resources/view/icons/virus/docteur.png differ
diff --git a/src/main/resources/view/icons/virus/humain.png b/src/main/resources/view/icons/virus/humain.png
new file mode 100644
index 0000000000000000000000000000000000000000..d88de16c2b701a823f7bceccc5629562cab05a56
Binary files /dev/null and b/src/main/resources/view/icons/virus/humain.png differ
diff --git a/src/main/resources/view/icons/virus/patient.png b/src/main/resources/view/icons/virus/patient.png
new file mode 100644
index 0000000000000000000000000000000000000000..9aa4113c8fd5ad39ee4592877058c27e2d2e52e0
Binary files /dev/null and b/src/main/resources/view/icons/virus/patient.png differ
diff --git a/src/main/resources/view/icons/virus/virus.png b/src/main/resources/view/icons/virus/virus.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4d6b7c5e10766a9fe5ce085a1da41486ce22716
Binary files /dev/null and b/src/main/resources/view/icons/virus/virus.png differ