From f46e527fbd107e08f690e6f3ad8924edfe64d001 Mon Sep 17 00:00:00 2001
From: Yanis O <oualanyanis01@gmail.com>
Date: Sat, 23 Nov 2024 15:57:43 +0100
Subject: [PATCH] =?UTF-8?q?[Ajout]=20AirTanker=20:=20Canadair=20qui=20?=
 =?UTF-8?q?=C3=A9teins=20les=20feux=20sur=20un=20rayon=20de=203?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/model/AirTanker.java            | 172 +++++++++++++++++
 src/main/java/model/Cloud.java                |  18 +-
 src/main/java/model/Fire.java                 |  89 +++++----
 src/main/java/model/FireFighter.java          | 180 ++++++++++++------
 src/main/java/model/MotorizedFireFighter.java | 110 ++++++++---
 src/main/java/model/Mountain.java             |   9 +-
 src/main/java/util/Direction.java             |   5 +
 src/main/java/util/Matrix.java                |   3 +
 src/main/java/util/PositionUtil.java          |  33 ++++
 9 files changed, 488 insertions(+), 131 deletions(-)
 create mode 100644 src/main/java/model/AirTanker.java
 create mode 100644 src/main/java/util/Direction.java

diff --git a/src/main/java/model/AirTanker.java b/src/main/java/model/AirTanker.java
new file mode 100644
index 0000000..b723a7b
--- /dev/null
+++ b/src/main/java/model/AirTanker.java
@@ -0,0 +1,172 @@
+package model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import javafx.scene.paint.Color;
+import util.Direction;
+import util.Position;
+import util.PositionUtil;
+
+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;
+
+    public AirTanker(Position position, Board<Square> b) {
+        this.age = 0;
+        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 {
+            System.out.println("not on a edge");
+            // 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
+            System.out.println("end of airtanker mission");
+            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
+
+
+            // Increment age if needed
+            this.age++;
+
+            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);
+        System.out.println("trying to move to : " + newPos.toString());
+        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);
+    }
+
+
+}
diff --git a/src/main/java/model/Cloud.java b/src/main/java/model/Cloud.java
index baf7b0a..840195d 100644
--- a/src/main/java/model/Cloud.java
+++ b/src/main/java/model/Cloud.java
@@ -1,19 +1,17 @@
 package model;
 
-import javafx.geometry.Pos;
+import java.util.List;
+import java.util.Random;
+
 import javafx.scene.paint.Color;
 import util.Position;
 import util.PositionUtil;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
 public class Cloud implements Entity{
     private int age;
     private Position position;
-    private final Color viewColor = Color.GREEN;
-    private final int priority = 3;
+    private final Color viewColor = Color.GRAY;
+    private final int priority = 2;
 
 
 
@@ -59,7 +57,7 @@ public class Cloud implements Entity{
         b.getStates(p).getEntities().removeIf(element -> element instanceof Fire);
             List<Entity> entities = b.getStates(p).getEntities();
             for (Entity e : entities) {
-                if (e instanceof EmptyEntity) {
+                if (e instanceof EmptySquare) {
                     e.setAge(b.stepNumber() + 1);
                 }
             }
@@ -99,7 +97,9 @@ public class Cloud implements Entity{
     }
 
     @Override
-    public int getPriority(){ return this.priority;}
+    public int getPriority(){ 
+        return this.priority;
+    }
 
 
 }
diff --git a/src/main/java/model/Fire.java b/src/main/java/model/Fire.java
index c3814b3..8ad742e 100644
--- a/src/main/java/model/Fire.java
+++ b/src/main/java/model/Fire.java
@@ -2,6 +2,7 @@ package model;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 import javafx.scene.paint.Color;
 import util.Position;
@@ -9,46 +10,62 @@ import util.PositionUtil;
 
 
 public class Fire implements Entity {
-    Board<Square> b;
     private Position position;
     private final Color viewColor = Color.RED;
     private int age;
-    private final int priority = 0;
+    private final int priority = 1;
 
-    public Fire(Position position, Board<Square> b) {
-        this.b = b;
+    public Fire(Position position) {
         this.position = position;
         this.age = 0;
     }
 
-    public Fire(Position position, Board<Square> b, int age) {
-        this.b = b;
+    public Fire(Position position, int age) {
         this.position = position;
         this.age = age;
     }
 
     @Override
     public List<Position> nextTurn(Board<Square> board) {
-        if (board.getStepNumber() % 2 == 0)
-            return new ArrayList<Position>();
-        if (age == 0) {
-            age = age + 1;
-            return new ArrayList<Position>();
+        List<Position> newFirePositions = new ArrayList<>();
+        if(board.getStepNumber() <= 1){
+            return newFirePositions;
         }
-        List<Position> positions = PositionUtil.generateAdjacentPositions(position, board);
-        positions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class));
-        for (Position p : positions) {
-            if (b.getStates(p).isEmpty() && !b.getStates(p).getEntities().contains(Cloud.class)) {
-                if (b.getStates(p).getMaxAge() < b.getStepNumber()
-                        && PositionUtil.getManhattanDistance(position, p) == 1) {
-                    board.addEntityAtSquare(new Fire(p, board), p);
-                }
+        // 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;
             }
-            if (!b.doesPositionExist(p)) {
-                positions.remove(p);
+
+            // 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, Cloud.class)) {
+                continue;
             }
+
+            // Add new Fire to the board
+            board.addEntityAtSquare(new Fire(p), p);
+            newFirePositions.add(p); // Keep track of new fires for updates
         }
-        return positions;
+
+        return newFirePositions;
     }
 
     @Override
@@ -61,6 +78,7 @@ public class Fire implements Entity {
         return this.position;
     }
 
+    @Override
     public Color getViewColor() {
         return this.viewColor;
     }
@@ -72,7 +90,7 @@ public class Fire implements Entity {
 
     @Override
     public void incrementAge() {
-        this.age = age + 1;
+        this.age++;
     }
 
     @Override
@@ -81,27 +99,22 @@ public class Fire implements Entity {
     }
 
     @Override
-    public int getPriority(){ return this.priority;}
+    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;
-        Fire fire = (Fire) obj;
-        return age == fire.age &&
-               priority == fire.priority &&
-               (position == null ? fire.position == null : position.equals(fire.position)) &&
-               (b == null ? fire.b == null : b.equals(fire.b)) &&
-               (viewColor == null ? fire.viewColor == null : viewColor.equals(fire.viewColor));
+        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() {
-        int result = (b == null ? 0 : b.hashCode());
-        result = 31 * result + (position == null ? 0 : position.hashCode());
-        result = 31 * result + (viewColor == null ? 0 : viewColor.hashCode());
-        result = 31 * result + age;
-        result = 31 * result + priority;
-        return result;
+        return Objects.hash(position, age);
     }
+
 }
diff --git a/src/main/java/model/FireFighter.java b/src/main/java/model/FireFighter.java
index bd7ffb6..bc070cb 100644
--- a/src/main/java/model/FireFighter.java
+++ b/src/main/java/model/FireFighter.java
@@ -1,7 +1,11 @@
 package model;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
 import javafx.scene.paint.Color;
-import util.*;
+import util.Position;
+import util.PositionUtil;
 
 
 
@@ -10,103 +14,171 @@ public class FireFighter implements Entity {
     private Position position;
     private final Color viewColor = Color.BLUE;
     private final int priority = 1;
+    protected List<Position> lastThreePosition;
 
     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<>();
-
-        // Générer les positions adjacentes
+    
+        // Generate adjacent positions, excluding mountains
         List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b);
-        adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class));
-
-        // Vérifier s'il y a du feu dans une des positions adjacentes
+        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) {
-            // Si du feu est trouvé, on éteint les feux adjacents
+            // Extinguish fires in adjacent positions
             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.clearCaseFrom(this, position); // Vider l'ancienne case
-                    positions.add(new Position(position.x(), position.y()));
-                    this.position = nextPos;
-                    b.addEntityAtSquare(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
+            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) {
-            extinguishedPositions.addAll(adjacentPositions);
-            b.getStates(p).getEntities().removeIf(element -> element instanceof Fire);
-            List<Entity> entities = b.getStates(p).getEntities();
-            for (Entity e : entities) {
-                if (e instanceof EmptyEntity) {
-                    e.setAge(b.stepNumber() + 1);
-                }
+            if (b.doesSquareContainEntity(p, Fire.class)) {
+                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
             }
-            extinguishedPositions.add(p); // Ajouter la position où le feu a été éteint
-
         }
         return extinguishedPositions;
     }
+    
 
+    protected List<Position> moveAndExtinguish(Board<Square> b) {
+        List<Position> positions = new ArrayList<>();
+    
+        // Find the nearest fire
+        Position nearestFirePos = b.getNearestEntity(position, Fire.class);
+        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) {
-        // Générer les 8 positions adjacentes possibles
+        // Generate adjacent positions
         List<Position> possibleMoves = PositionUtil.generateAllAdjacentPositions(currentPos, b);
-
-        // Filtrer les positions qui sont libres
-        possibleMoves.removeIf(p -> !(b.isPositionEmpty(p)));
-
-        // Si aucune position libre n'est disponible, retourner null
+    
+        // Filter out positions that are not empty or contain obstacles
+        possibleMoves.removeIf(p -> !b.isPositionEmpty(p) || b.doesSquareContainEntity(p, Mountain.class));
+    
+        // If no possible moves, return null
         if (possibleMoves.isEmpty()) {
             return null;
         }
-
-        // Calculer la distance actuelle vers la cible
+    
+        // Calculate the current distance to the target
         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;
+    
+        // 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;
-                bestMove = move;
+                bestMoves.clear();
+                bestMoves.add(move);
+            } else if (distance == minDistance) {
+                bestMoves.add(move);
             }
         }
-
-        // Si aucun déplacement ne réduit la distance, annuler le déplacement
-        if (bestMove == null) {
-            return null;
+    
+        // 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;
         }
-        return bestMove;
+    
+        // 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) {
diff --git a/src/main/java/model/MotorizedFireFighter.java b/src/main/java/model/MotorizedFireFighter.java
index 4ad3f74..146fb38 100644
--- a/src/main/java/model/MotorizedFireFighter.java
+++ b/src/main/java/model/MotorizedFireFighter.java
@@ -1,52 +1,110 @@
 package model;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+
 import javafx.scene.paint.Color;
-import util.*;
+import util.Position;
+import util.PositionUtil;
 
 public class MotorizedFireFighter extends FireFighter {
     private final Color viewColor = Color.CYAN;
-    public MotorizedFireFighter(Position position, Board<Square> b){
+
+    public MotorizedFireFighter(Position position, Board<Square> b) {
         super(position, b);
     }
+
+    @Override
     public List<Position> nextTurn(Board<Square> b) {
         List<Position> positions = new ArrayList<>();
 
-        // Générer les positions adjacentes
+        // Generate adjacent positions excluding mountains
         List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(getPosition(), b);
-        adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class));
+        adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class));
 
-        // Vérifier s'il y a du feu dans une des positions adjacentes
+        // 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) {
-            // Si du feu est trouvé, on éteint les feux adjacents
+            // 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 {
-            // Chercher la position du feu le plus proche
-            Position nearestFirePos = b.getNearestEntity(getPosition(), Fire.class);
-
-            if (nearestFirePos != null && !nearestFirePos.equals(getPosition())) {
-                // Trouver la meilleure position pour se rapprocher du feu
-                Position nextPos = getNextPositionTowards(getNextPositionTowards(getPosition(), nearestFirePos, b),nearestFirePos, b);
-                if (nextPos != null) {
-                    // Mettre à jour la position du pompier
-                    b.clearCaseFrom(this, getPosition()); // Vider l'ancienne case
-                    positions.add(new Position(getPosition().x(), getPosition().y()));
-                    setPosition(nextPos);
-                    b.addEntityAtSquare(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
+            // 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 = b.getNearestEntity(getPosition(), Fire.class);
+        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;
     }
-    public Color getViewColor(){
+
+    // 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());
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/model/Mountain.java b/src/main/java/model/Mountain.java
index 4962526..02f7fd6 100644
--- a/src/main/java/model/Mountain.java
+++ b/src/main/java/model/Mountain.java
@@ -1,15 +1,15 @@
 package model;
 
+import java.util.List;
+
 import javafx.scene.paint.Color;
 import util.Position;
 
-import java.util.List;
-
 public class Mountain implements Entity{
-    private final int priority = 3;
+    private final int priority = 0;
     Position position;
     private int age;
-    private final Color viewColor = Color.YELLOW;
+    private final Color viewColor = Color.CHOCOLATE;
 
     public Mountain(Position p ){
         this.position = p;
@@ -23,6 +23,7 @@ public class Mountain implements Entity{
 
     @Override
     public List<Position> nextTurn(Board<Square> board) {
+        List<Entity> states = board.getStates(position).getEntities();
         return List.of();
     }
 
diff --git a/src/main/java/util/Direction.java b/src/main/java/util/Direction.java
new file mode 100644
index 0000000..471e8e7
--- /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/Matrix.java b/src/main/java/util/Matrix.java
index 9fb7703..920d2a4 100644
--- a/src/main/java/util/Matrix.java
+++ b/src/main/java/util/Matrix.java
@@ -82,6 +82,9 @@ public class Matrix<E> implements Iterable<E> {
                     }   
                     else if(s.getEntities().stream().anyMatch(p -> p instanceof FireFighter)){
                         System.out.print(" ff | ");
+                    }
+                    else if(s.getEntities().stream().anyMatch(p -> p instanceof FireFighter)){
+                        System.out.print(" A | ");
                     }else{
                         System.out.print("  | ");
                     }
diff --git a/src/main/java/util/PositionUtil.java b/src/main/java/util/PositionUtil.java
index 4fa6408..278bf9f 100644
--- a/src/main/java/util/PositionUtil.java
+++ b/src/main/java/util/PositionUtil.java
@@ -122,4 +122,37 @@ 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;
+    }
+
 }
\ No newline at end of file
-- 
GitLab