diff --git a/.idea/misc.xml b/.idea/misc.xml
index b37905cbee66b9e11bfc56f34e4576f2109fe859..2e4f09532a98163d74355d8086d519b2ff1de9a7 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,15 +11,10 @@
       </list>
     </option>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
   <component name="ProjectType">
     <option name="id" value="jpab" />
   </component>
-  <component name="SwUserDefinedSpecifications">
-    <option name="specTypeByUrl">
-      <map />
-    </option>
-  </component>
 </project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f99378b8c9207485fbfb01e82c8b4ffd38c84e37..28e3de1e62dd55223da8bee198c9132cc761bdfe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,6 +7,19 @@
     <groupId>org.IRIT</groupId>
     <artifactId>SMA-SEIR</artifactId>
     <version>0.1</version>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>18</source>
+                    <target>18</target>
+                    <compilerArgs>--enable-preview</compilerArgs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
     <properties>
         <maven.compiler.source>17</maven.compiler.source>
diff --git a/src/main/java/agents/Agent.java b/src/main/java/agents/Agent.java
index 56c1ada9e0d1ac205ab52a890a8f41ae670965b1..c4b9c12ddbcf33182028b28f270a63ec16e3b278 100644
--- a/src/main/java/agents/Agent.java
+++ b/src/main/java/agents/Agent.java
@@ -1,8 +1,9 @@
 package agents;
 
-import behaviors.Wakeable;
+import behaviors.Cyclic;
 
-public interface Agent extends Wakeable {
+public sealed interface Agent
+permits CyclicAgent, ThreePhasedAgent{
 
     String getId();
 }
diff --git a/src/main/java/agents/CyclicAgent.java b/src/main/java/agents/CyclicAgent.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c6649d8ea095d5ac06cd219ea82412bb21003c2
--- /dev/null
+++ b/src/main/java/agents/CyclicAgent.java
@@ -0,0 +1,6 @@
+package agents;
+
+import behaviors.Cyclic;
+
+public non-sealed interface CyclicAgent extends Agent, Cyclic {
+}
diff --git a/src/main/java/agents/FairInfectionRWAgent.java b/src/main/java/agents/FairInfectionRWAgent.java
deleted file mode 100644
index 260525253a5526bf4676b742573dfce8e9a9832e..0000000000000000000000000000000000000000
--- a/src/main/java/agents/FairInfectionRWAgent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package agents;
-
-import environment.SEIRSEnvironment;
-import utils.YamlReader;
-
-import java.awt.*;
-
-public class FairInfectionRWAgent extends RandomWalkingAgent implements SEIRSAgent {
-
-    public FairInfectionRWAgent(Point position, long seed, SEIRSEnvironment environment) {
-        super(position, seed, environment);
-    }
-
-    @Override
-    public boolean isExposed() {
-        boolean isExposed = false;
-        int roll = r.nextInt(10000)+1;
-        if (this.environment.getInfectedNeighbors(position).size() != 0) {
-            if (roll <= YamlReader.getParams().infectionRate()*10000) {
-                isExposed = true;
-            }
-        }
-        return isExposed;
-    }
-}
diff --git a/src/main/java/agents/RandomWalkingAgent3P.java b/src/main/java/agents/RandomWalkingAgent3P.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edbcae221f05cc1e16523883015f7263383d016
--- /dev/null
+++ b/src/main/java/agents/RandomWalkingAgent3P.java
@@ -0,0 +1,37 @@
+package agents;
+
+import agents.seirs.RandomWakingAgent;
+import agents.seirs.ThreePhasedSEIRSAgent;
+import environment.SEIRSEnvironment;
+
+import java.awt.*;
+
+public class RandomWalkingAgent3P extends RandomWakingAgent implements ThreePhasedSEIRSAgent {
+
+    private String id;
+
+    public RandomWalkingAgent3P(Point position, long seed, SEIRSEnvironment environment) {
+        super(position, seed, environment);
+        this.id = String.valueOf(seed);
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public void perceive() {
+        perceiveAuthorizedPositions();
+    }
+
+    @Override
+    public void decide() {
+        decideNextMove();
+    }
+
+    @Override
+    public void act() {
+        move();
+    }
+}
diff --git a/src/main/java/agents/ThreePhasedAgent.java b/src/main/java/agents/ThreePhasedAgent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c4c91bd474fb1f59a56c9f40e98ea2e53147dc3
--- /dev/null
+++ b/src/main/java/agents/ThreePhasedAgent.java
@@ -0,0 +1,7 @@
+package agents;
+
+import behaviors.ThreePhased;
+
+public non-sealed interface ThreePhasedAgent extends Agent, ThreePhased {
+
+}
diff --git a/src/main/java/agents/seirs/CyclicSEIRSAgent.java b/src/main/java/agents/seirs/CyclicSEIRSAgent.java
new file mode 100644
index 0000000000000000000000000000000000000000..135b9f805acd4d660bff23a909a819d5d7e9198c
--- /dev/null
+++ b/src/main/java/agents/seirs/CyclicSEIRSAgent.java
@@ -0,0 +1,11 @@
+package agents.seirs;
+
+import agents.CyclicAgent;
+import agents.states.SEIRSState;
+import behaviors.Infectious;
+import behaviors.Positionable2D;
+
+public interface CyclicSEIRSAgent extends CyclicAgent, SEIRSAgent {
+
+    void wakeUp();
+}
diff --git a/src/main/java/agents/seirs/FairInfectionRWAgent.java b/src/main/java/agents/seirs/FairInfectionRWAgent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2aebf28e8763a562f185ed36e88a1fa2e40236c2
--- /dev/null
+++ b/src/main/java/agents/seirs/FairInfectionRWAgent.java
@@ -0,0 +1,93 @@
+package agents.seirs;
+
+import agents.states.SEIRSState;
+import agents.states.SuceptibleSEIRSState;
+import behaviors.Randomized;
+import environment.SEIRSEnvironment;
+import utils.YamlReader;
+
+import java.awt.*;
+import java.util.List;
+
+public abstract class FairInfectionRWAgent extends Randomized implements SEIRSAgent {
+
+    protected Point position;
+    protected final SEIRSEnvironment environment;
+    protected SEIRSState state;
+
+    protected List<Point> authorizedPositions;
+    protected Point nextPosition;
+    public FairInfectionRWAgent(Point position, long seed, SEIRSEnvironment environment) {
+        super(seed);
+        this.position = position;
+        this.state = new SuceptibleSEIRSState(this);
+        this.environment = environment;
+        r.setSeed(seed);
+    }
+
+    protected void move() {
+        state.onMovement();
+        environment.notifyNewPosition(nextPosition,this);
+        position = nextPosition;
+    }
+
+    protected void perceiveAuthorizedPositions() {
+        authorizedPositions =  environment.perceiveAuthorizedPositions(this);
+    }
+
+    protected void decideNextMove() {
+        int next = r.nextInt(authorizedPositions.size());
+        nextPosition = authorizedPositions.get(next);
+    }
+
+    @Override
+    public void changeState(SEIRSState SEIRSState) { this.state = SEIRSState; }
+
+    @Override
+    public boolean isExposed() {
+        boolean isExposed = false;
+        for (int i = 0 ; i<environment.getInfectedNeighbors(position).size() ; i++) {
+            int roll = r.nextInt(10000)+1;
+            if (roll <= YamlReader.getParams().infectionRate()*10000) {
+                isExposed = true;
+            }
+        }
+        return isExposed;
+    }
+
+    @Override
+    public boolean isInfected() {
+        boolean isSick = false;
+        int roll = r.nextInt(10000)+1;
+        if (roll <= YamlReader.getParams().incubationRate()*10000) {
+            isSick = true;
+        }
+        return isSick;
+    }
+
+    @Override
+    public boolean isRecovered() {
+        boolean isHealed = false;
+        int roll = r.nextInt(10000)+1;
+        if (roll <= YamlReader.getParams().recoveryRate()*10000) {
+            isHealed = true;
+        }
+        return isHealed;
+    }
+
+    @Override
+    public boolean hasLostImmunity() {
+        boolean hasLostImmunity = false;
+        int roll = r.nextInt(10000)+1;
+        if (roll <= YamlReader.getParams().looseImmunityRate()*10000) {
+            hasLostImmunity = true;
+        }
+        return hasLostImmunity;
+    }
+
+    @Override
+    public SEIRSState getState() { return this.state; }
+
+    @Override
+    public Point getPosition() { return position; }
+}
diff --git a/src/main/java/agents/seirs/FairInfectionRWAgent3P.java b/src/main/java/agents/seirs/FairInfectionRWAgent3P.java
new file mode 100644
index 0000000000000000000000000000000000000000..e69c6fd026325cdf7f6a1afc486ee99a3997d5d3
--- /dev/null
+++ b/src/main/java/agents/seirs/FairInfectionRWAgent3P.java
@@ -0,0 +1,36 @@
+package agents.seirs;
+
+import agents.ThreePhasedAgent;
+import environment.SEIRSEnvironment;
+
+import java.awt.*;
+
+public class FairInfectionRWAgent3P extends FairInfectionRWAgent implements ThreePhasedSEIRSAgent {
+
+    private String id;
+
+    public FairInfectionRWAgent3P(Point position, long seed, SEIRSEnvironment environment) {
+        super(position, seed, environment);
+        this.id = String.valueOf(seed);
+    }
+
+    @Override
+    public void perceive() {
+        perceiveAuthorizedPositions();
+    }
+
+    @Override
+    public void decide() {
+        decideNextMove();
+    }
+
+    @Override
+    public void act() {
+        move();
+    }
+
+    @Override
+    public String getId() {
+        return this.id;
+    }
+}
diff --git a/src/main/java/agents/seirs/FairInfectionRWAgentCyclic.java b/src/main/java/agents/seirs/FairInfectionRWAgentCyclic.java
new file mode 100644
index 0000000000000000000000000000000000000000..707f1d7505b3e92758c7b75e166b42ef76e25538
--- /dev/null
+++ b/src/main/java/agents/seirs/FairInfectionRWAgentCyclic.java
@@ -0,0 +1,29 @@
+package agents.seirs;
+
+import environment.SEIRSEnvironment;
+import utils.YamlReader;
+
+import java.awt.*;
+
+public class FairInfectionRWAgentCyclic extends FairInfectionRWAgent implements CyclicSEIRSAgent {
+
+    private String id;
+    public FairInfectionRWAgentCyclic(Point position, long seed, SEIRSEnvironment environment) {
+        super(position, seed, environment);
+        this.id = String.valueOf(seed);
+    }
+
+    @Override
+    public void wakeUp() {
+        perceiveAuthorizedPositions();
+        if (!authorizedPositions.isEmpty()) {
+            decideNextMove();
+            move();
+        }
+    }
+    @Override
+    public String getId() {
+        return this.id;
+    }
+
+}
diff --git a/src/main/java/agents/RandomWalkingAgent.java b/src/main/java/agents/seirs/RandomWakingAgent.java
similarity index 75%
rename from src/main/java/agents/RandomWalkingAgent.java
rename to src/main/java/agents/seirs/RandomWakingAgent.java
index c14ce90a6750ec138bda72a8be950264a203d79d..bccdf5d4a69f0a291829689afeaaf1ad9a9403ef 100644
--- a/src/main/java/agents/RandomWalkingAgent.java
+++ b/src/main/java/agents/seirs/RandomWakingAgent.java
@@ -1,4 +1,4 @@
-package agents;
+package agents.seirs;
 
 import agents.states.SEIRSState;
 import agents.states.SuceptibleSEIRSState;
@@ -6,52 +6,41 @@ import behaviors.Randomized;
 import environment.SEIRSEnvironment;
 import utils.YamlReader;
 
-import java.awt.Point;
+import java.awt.*;
 import java.util.List;
 
-public class RandomWalkingAgent extends Randomized implements SEIRSAgent {
+public abstract class RandomWakingAgent extends Randomized implements SEIRSAgent {
 
     protected Point position;
     protected final SEIRSEnvironment environment;
     protected SEIRSState state;
 
-    private List<Point> authorizedPositions;
-    private Point nextPosition;
-    private final String id;
+    protected List<Point> authorizedPositions;
+    protected Point nextPosition;
 
-    public RandomWalkingAgent(Point position, long seed, SEIRSEnvironment environment) {
+    public RandomWakingAgent(Point position, long seed, SEIRSEnvironment environment) {
         super(seed);
-        this.id = String.valueOf(seed);
         this.position = position;
         this.state = new SuceptibleSEIRSState(this);
         this.environment = environment;
         r.setSeed(seed);
     }
 
-    private void move() {
+    protected void move() {
         state.onMovement();
         environment.notifyNewPosition(nextPosition,this);
         position = nextPosition;
     }
 
-    private void perceiveAuthorizedPositions() {
+    protected void perceiveAuthorizedPositions() {
         authorizedPositions =  environment.perceiveAuthorizedPositions(this);
     }
 
-    private void decideNextMove() {
+    protected void decideNextMove() {
         int next = r.nextInt(authorizedPositions.size());
         nextPosition = authorizedPositions.get(next);
     }
 
-    @Override
-    public void wakeUp() {
-        perceiveAuthorizedPositions();
-        if (!authorizedPositions.isEmpty()) {
-            decideNextMove();
-            move();
-        }
-    }
-
     @Override
     public void changeState(SEIRSState SEIRSState) { this.state = SEIRSState; }
 
@@ -103,9 +92,4 @@ public class RandomWalkingAgent extends Randomized implements SEIRSAgent {
     @Override
     public Point getPosition() { return position; }
 
-    @Override
-    public String getId() {
-        return this.id;
-    }
-
 }
diff --git a/src/main/java/agents/seirs/RandomWalkingAgentCyclic.java b/src/main/java/agents/seirs/RandomWalkingAgentCyclic.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c1874cb898ea5f04b76ab3edbee1d19339d9b89
--- /dev/null
+++ b/src/main/java/agents/seirs/RandomWalkingAgentCyclic.java
@@ -0,0 +1,34 @@
+package agents.seirs;
+
+import agents.states.SEIRSState;
+import agents.states.SuceptibleSEIRSState;
+import behaviors.Randomized;
+import environment.SEIRSEnvironment;
+import utils.YamlReader;
+
+import java.awt.Point;
+import java.util.List;
+
+public class RandomWalkingAgentCyclic extends RandomWakingAgent implements CyclicSEIRSAgent {
+
+    private String id;
+
+    public RandomWalkingAgentCyclic(Point position, long seed, SEIRSEnvironment environment) {
+        super(position, seed, environment);
+        this.id = String.valueOf(seed);
+    }
+
+    @Override
+    public void wakeUp() {
+        perceiveAuthorizedPositions();
+        if (!authorizedPositions.isEmpty()) {
+            decideNextMove();
+            move();
+        }
+    }
+    @Override
+    public String getId() {
+        return this.id;
+    }
+
+}
diff --git a/src/main/java/agents/seirs/SEIRSAgent.java b/src/main/java/agents/seirs/SEIRSAgent.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb8244fbb2b94620fe9631da0e8ec571c403471a
--- /dev/null
+++ b/src/main/java/agents/seirs/SEIRSAgent.java
@@ -0,0 +1,7 @@
+package agents.seirs;
+
+import behaviors.Infectious;
+import behaviors.Positionable2D;
+
+public interface SEIRSAgent extends Positionable2D, Infectious {
+}
diff --git a/src/main/java/agents/seirs/ThreePhasedSEIRSAgent.java b/src/main/java/agents/seirs/ThreePhasedSEIRSAgent.java
new file mode 100644
index 0000000000000000000000000000000000000000..019fa3444c14c18d7bc4dd2340eb96136016b11d
--- /dev/null
+++ b/src/main/java/agents/seirs/ThreePhasedSEIRSAgent.java
@@ -0,0 +1,7 @@
+package agents.seirs;
+
+import agents.ThreePhasedAgent;
+
+public interface ThreePhasedSEIRSAgent extends ThreePhasedAgent,SEIRSAgent {
+
+}
diff --git a/src/main/java/agents/states/ExposedSEIRSState.java b/src/main/java/agents/states/ExposedSEIRSState.java
index c7dbbcccad4c9c9764732ab5a821a308d9469ea2..b24651c0247761252d9589d5ebbc21ce66aad8f2 100644
--- a/src/main/java/agents/states/ExposedSEIRSState.java
+++ b/src/main/java/agents/states/ExposedSEIRSState.java
@@ -1,6 +1,7 @@
 package agents.states;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 
 public class ExposedSEIRSState extends SEIRSState {
 
diff --git a/src/main/java/agents/states/InfectedSEIRSState.java b/src/main/java/agents/states/InfectedSEIRSState.java
index 012d0cb8dfd7cba0cd3a5f337cfa24f80f56563c..d8c18f291b233e4aa8c109cf15ec1341fc9234d7 100644
--- a/src/main/java/agents/states/InfectedSEIRSState.java
+++ b/src/main/java/agents/states/InfectedSEIRSState.java
@@ -1,6 +1,7 @@
 package agents.states;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 
 public class InfectedSEIRSState extends SEIRSState {
 
diff --git a/src/main/java/agents/states/RecoveredSEIRSState.java b/src/main/java/agents/states/RecoveredSEIRSState.java
index 11df581e4c827d540adfef5f1e915318101a281a..0a05430d3368b05fc059ac3cfa3b70597a7fcbbc 100644
--- a/src/main/java/agents/states/RecoveredSEIRSState.java
+++ b/src/main/java/agents/states/RecoveredSEIRSState.java
@@ -1,6 +1,7 @@
 package agents.states;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 
 public class RecoveredSEIRSState extends SEIRSState {
 
diff --git a/src/main/java/agents/states/SEIRSState.java b/src/main/java/agents/states/SEIRSState.java
index 78725a4808b0ff3541a126aee59485e4f61758a2..966453fa1ab5a0aa596474a32a48cb4ac560e163 100644
--- a/src/main/java/agents/states/SEIRSState.java
+++ b/src/main/java/agents/states/SEIRSState.java
@@ -1,6 +1,7 @@
 package agents.states;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 
 public abstract class SEIRSState {
 
@@ -9,7 +10,7 @@ public abstract class SEIRSState {
     public final static String SUCEPTIBLE = "SUCEPTIBLE";
     public final static String RECOVERED = "RECOVERED";
 
-    protected final agents.SEIRSAgent agent;
+    protected final SEIRSAgent agent;
 
     SEIRSState(SEIRSAgent agent) {
         this.agent = agent;
diff --git a/src/main/java/agents/states/SuceptibleSEIRSState.java b/src/main/java/agents/states/SuceptibleSEIRSState.java
index 28a2511c078bfc66dda80ecdeca91da72e036178..87c5335c6ef7ce42db23d6c454eb79de17119887 100644
--- a/src/main/java/agents/states/SuceptibleSEIRSState.java
+++ b/src/main/java/agents/states/SuceptibleSEIRSState.java
@@ -1,6 +1,7 @@
 package agents.states;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 
 public class SuceptibleSEIRSState extends SEIRSState {
 
diff --git a/src/main/java/behaviors/Wakeable.java b/src/main/java/behaviors/Cyclic.java
similarity index 58%
rename from src/main/java/behaviors/Wakeable.java
rename to src/main/java/behaviors/Cyclic.java
index dfb18696f438cbcecbdf1413030aecf10bb1fe07..9b6d789f047a8e75f67cdb66be4336c758dbead9 100644
--- a/src/main/java/behaviors/Wakeable.java
+++ b/src/main/java/behaviors/Cyclic.java
@@ -1,5 +1,5 @@
 package behaviors;
 
-public interface Wakeable {
+public interface Cyclic {
     void wakeUp();
 }
\ No newline at end of file
diff --git a/src/main/java/agents/SEIRSAgent.java b/src/main/java/behaviors/Infectious.java
similarity index 66%
rename from src/main/java/agents/SEIRSAgent.java
rename to src/main/java/behaviors/Infectious.java
index 1a5242fb9e7a87aeb97ff3fc4c3ebe57ad167ac5..e16f7000ab682bef5911e3b4acab11534f3078f8 100644
--- a/src/main/java/agents/SEIRSAgent.java
+++ b/src/main/java/behaviors/Infectious.java
@@ -1,10 +1,8 @@
-package agents;
+package behaviors;
 
 import agents.states.SEIRSState;
-import behaviors.Positionable2D;
-
-public interface SEIRSAgent extends Agent, Positionable2D {
 
+public interface Infectious {
     void changeState(SEIRSState SEIRSState);
     SEIRSState getState();
     boolean isExposed();
diff --git a/src/main/java/behaviors/ThreePhased.java b/src/main/java/behaviors/ThreePhased.java
new file mode 100644
index 0000000000000000000000000000000000000000..c077b09e63b7877f9e2bbd2bc07dbacd54bd4343
--- /dev/null
+++ b/src/main/java/behaviors/ThreePhased.java
@@ -0,0 +1,9 @@
+package behaviors;
+
+public interface ThreePhased {
+
+    void perceive();
+    void decide();
+    void act();
+    
+}
diff --git a/src/main/java/environment/ChunkedSEIRSEnvironment.java b/src/main/java/environment/ChunkedSEIRSEnvironment.java
index e754588c510bf08394ae55fc599747f6881aa4f4..d489eac3482fc4e1bd0d438eee72d14a0aa8e983 100644
--- a/src/main/java/environment/ChunkedSEIRSEnvironment.java
+++ b/src/main/java/environment/ChunkedSEIRSEnvironment.java
@@ -1,6 +1,8 @@
 package environment;
 
-import agents.SEIRSAgent;
+import agents.Agent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 import agents.states.InfectedSEIRSState;
 import agents.states.SEIRSState;
 import behaviors.Positionable2D;
@@ -112,7 +114,7 @@ public class ChunkedSEIRSEnvironment implements SEIRSEnvironment {
             chunks[oldPosition.x/CHUNK_SIZE][oldPosition.y/CHUNK_SIZE].remove((SEIRSAgent) agent);
             chunks[newPosition.x/CHUNK_SIZE][newPosition.y/CHUNK_SIZE].add((SEIRSAgent) agent);
         }
-        executionOrder.add(((SEIRSAgent)agent).getId());
+        executionOrder.add(((Agent)agent).getId());
     }
 
     @Override
@@ -139,8 +141,8 @@ public class ChunkedSEIRSEnvironment implements SEIRSEnvironment {
         map.put(SEIRSState.RECOVERED,0);
         map.put(SEIRSState.SUCEPTIBLE,0);
 
-        for (SEIRSAgent SEIRSAgent : agents) {
-            String state = SEIRSAgent.getState().toString();
+        for (SEIRSAgent agent : agents) {
+            String state = agent.getState().toString();
             map.put(state,map.get(state)+1);
         }
         return map;
diff --git a/src/main/java/environment/SEIRSEnvironment.java b/src/main/java/environment/SEIRSEnvironment.java
index ddd65494ce7a40a8f0d40de8f5b3a17b3cf999ff..7e2a804885d784ac46aed87fea5b3d118c12639e 100644
--- a/src/main/java/environment/SEIRSEnvironment.java
+++ b/src/main/java/environment/SEIRSEnvironment.java
@@ -1,6 +1,7 @@
 package environment;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 
 import java.awt.*;
 import java.util.HashMap;
diff --git a/src/main/java/environment/WrappingChunkedSEIRSEnvironment.java b/src/main/java/environment/WrappingChunkedSEIRSEnvironment.java
index 4cfaa5271aa06c9edbfb3d4374b9c9802839091b..024638e8d46adcaf775118cb6b8005abb5ea79f4 100644
--- a/src/main/java/environment/WrappingChunkedSEIRSEnvironment.java
+++ b/src/main/java/environment/WrappingChunkedSEIRSEnvironment.java
@@ -1,6 +1,7 @@
 package environment;
 
-import agents.SEIRSAgent;
+import agents.seirs.CyclicSEIRSAgent;
+import agents.seirs.SEIRSAgent;
 import behaviors.Positionable2D;
 
 import java.awt.*;
diff --git a/src/main/java/models/Parameters.java b/src/main/java/models/Parameters.java
index 6ff1c2ea0910a6553468e72c3e553eeaa394b35f..5806c241fe26aa964bbf53b52a27a6e083987270 100644
--- a/src/main/java/models/Parameters.java
+++ b/src/main/java/models/Parameters.java
@@ -17,5 +17,6 @@ public record Parameters(
         boolean infectionStacks,
         boolean wrappingWorld,
         boolean playRecord,
-        boolean recordExperiment) {
+        boolean recordExperiment,
+        boolean threePhased) {
 }
diff --git a/src/main/java/scheduler/DeterministScheduler.java b/src/main/java/scheduler/DeterministScheduler.java
index 0c243e9b5651516e7ce06a8e29b800c56d622451..e712d7bb58d242f90f0139f0ae6d33957b0872b6 100644
--- a/src/main/java/scheduler/DeterministScheduler.java
+++ b/src/main/java/scheduler/DeterministScheduler.java
@@ -1,6 +1,8 @@
 package scheduler;
 
-import behaviors.Wakeable;
+import agents.Agent;
+import agents.CyclicAgent;
+import agents.ThreePhasedAgent;
 import utils.YamlReader;
 
 import java.io.BufferedReader;
@@ -8,11 +10,14 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.util.*;
 
+@SuppressWarnings("ConstantConditions")
 public class DeterministScheduler implements Scheduler {
 
-    private Wakeable[] agents;
+    private Agent[] agents;
     private final Queue<String> wakeUpOrder = new LinkedList<>();
 
+    private Boolean isThreePhased;
+
     public DeterministScheduler(String csvFile) {
         readCSV(csvFile);
     }
@@ -28,12 +33,15 @@ public class DeterministScheduler implements Scheduler {
     }
 
     @Override
-    public void init(Wakeable[] agents) {
+    public void init(Agent[] agents) {
+        isThreePhased = switch (agents[0]) {
+            case ThreePhasedAgent ignored -> true;
+            case CyclicAgent ignored -> false;
+        };
         this.agents = agents;
     }
 
-    @Override
-    public void doNextCycle() {
+    private void wakeUpNextCycle(CyclicAgent[] agents) {
         for (int i = 0 ; i<agents.length; i++) {
             try {
                 int next = Integer.parseInt(wakeUpOrder.poll());
@@ -44,4 +52,49 @@ public class DeterministScheduler implements Scheduler {
             }
         }
     }
+
+    private void perceiveNextCycle(ThreePhasedAgent[] agents, List<Integer> nextCycle) {
+        for (Integer i : nextCycle) {
+            agents[i].perceive();
+        }
+    }
+
+    private void decideNextCycle(ThreePhasedAgent[] agents, List<Integer> nextCycle) {
+        for (Integer i : nextCycle) {
+            agents[i].decide();
+        }
+    }
+
+    private void actNextCycle(ThreePhasedAgent[] agents, List<Integer> nextCycle) {
+        for (Integer i : nextCycle) {
+            agents[i].act();
+        }
+    }
+
+    private List<Integer> getNextCycle() {
+        List<Integer> nextCycle = new ArrayList<>();
+        for (int i = 0 ; i<agents.length; i++ ) {
+            try {
+                nextCycle.add(Integer.parseInt(wakeUpOrder.poll()));
+            } catch (EmptyStackException e) {
+                System.err.println("Last record entry was read, simulation cannot continue further.");
+                System.exit(1);
+            }
+        }
+        return nextCycle;
+    }
+
+    @Override
+    public void doNextCycle() {
+        if (isThreePhased) {
+            List<Integer> nextCycle = getNextCycle();
+            ThreePhasedAgent[] agents = (ThreePhasedAgent[])this.agents;
+            perceiveNextCycle(agents,nextCycle);
+            decideNextCycle(agents,nextCycle);
+            actNextCycle(agents,nextCycle);
+        } else {
+            CyclicAgent[] agents = (CyclicAgent[]) this.agents;
+            wakeUpNextCycle(agents);
+        }
+    }
 }
diff --git a/src/main/java/scheduler/FairAsynchronousScheduler.java b/src/main/java/scheduler/FairAsynchronousScheduler.java
index de564d945497d27fe3702b08999b4dfa4c8d18b7..634d564f93cdc24758d251908123ec60de7db342 100644
--- a/src/main/java/scheduler/FairAsynchronousScheduler.java
+++ b/src/main/java/scheduler/FairAsynchronousScheduler.java
@@ -1,6 +1,8 @@
 package scheduler;
 
-import behaviors.Wakeable;
+import agents.Agent;
+import agents.CyclicAgent;
+import agents.ThreePhasedAgent;
 
 import java.util.Arrays;
 import java.util.List;
@@ -12,17 +14,35 @@ import java.util.stream.Collectors;
 public class FairAsynchronousScheduler implements Scheduler {
 
     private final ExecutorService executor = Executors.newSingleThreadExecutor();
-    private Queue<Wakeable> queue;
+    private Queue<Agent> queue;
+
+    private Boolean isThreePhased;
 
     @Override
-    public void init(Wakeable[] agents) {
+    public void init(Agent[] agents) {
         this.queue = new ConcurrentLinkedQueue<>(Arrays.stream(agents).toList());
+        isThreePhased = switch (agents[0]) {
+            case ThreePhasedAgent ignored -> true;
+            case CyclicAgent ignored -> false;
+        };
     }
 
-    @Override
-    public void doNextCycle() {
-        List<Future<Wakeable>> results = queue.parallelStream().map(entity -> executor.submit(() -> {entity.wakeUp(); return entity;})).toList();
-        Function<Future<Wakeable>, Wakeable> futureTreatment = futureEntity -> {
+    private void wakeAll() {
+        List<Future<Agent>> results = queue.parallelStream()
+                .map(entity -> executor.submit(() -> {
+                    ((CyclicAgent)entity).wakeUp(); return entity;})).toList();
+        getFutureAgents(results);
+    }
+
+    private void perceiveAll() {
+        List<Future<Agent>> results = queue.parallelStream()
+                .map(entity -> executor.submit(() -> {
+                    ((ThreePhasedAgent)entity).perceive(); return entity;})).toList();
+        getFutureAgents(results);
+    }
+
+    private void getFutureAgents(List<Future<Agent>> results) {
+        Function<Future<Agent>, Agent> futureTreatment = futureEntity -> {
             try {
                 return futureEntity.get();
             } catch (ExecutionException | InterruptedException e) {
@@ -32,4 +52,29 @@ public class FairAsynchronousScheduler implements Scheduler {
         };
         queue = results.parallelStream().map(futureTreatment).collect(Collectors.toCollection(ConcurrentLinkedQueue::new));
     }
+
+    private void decideAll() {
+        List<Future<Agent>> results = queue.parallelStream()
+                .map(entity -> executor.submit(() -> {
+                    ((ThreePhasedAgent)entity).decide(); return entity;})).toList();
+        getFutureAgents(results);
+    }
+
+    private void actAll() {
+        List<Future<Agent>> results = queue.parallelStream()
+                .map(entity -> executor.submit(() -> {
+                    ((ThreePhasedAgent)entity).act(); return entity;})).toList();
+        getFutureAgents(results);
+    }
+
+    @Override
+    public void doNextCycle() {
+        if (isThreePhased) {
+            perceiveAll();
+            decideAll();
+            actAll();
+        } else {
+            wakeAll();
+        }
+    }
 }
diff --git a/src/main/java/scheduler/FairSynchronousScheduler.java b/src/main/java/scheduler/FairSynchronousScheduler.java
index b99e892d8b33f23f3c5f992b35e92e1f70613652..7c540a2f86c4df0f0c84c35d997d4f43d38e869d 100644
--- a/src/main/java/scheduler/FairSynchronousScheduler.java
+++ b/src/main/java/scheduler/FairSynchronousScheduler.java
@@ -1,15 +1,19 @@
 package scheduler;
 
+import agents.Agent;
+import agents.CyclicAgent;
+import agents.ThreePhasedAgent;
 import behaviors.Randomized;
-import behaviors.Wakeable;
 
 import java.util.*;
 
 public class FairSynchronousScheduler extends Randomized implements Scheduler {
 
-    private Wakeable[] agents;
+    private Agent[] agents;
     private Stack<Integer> executionOrder;
 
+    private Boolean isThreePhased;
+
     public FairSynchronousScheduler(long seed) {
         super(seed);
     }
@@ -21,15 +25,38 @@ public class FairSynchronousScheduler extends Randomized implements Scheduler {
         Collections.shuffle(executionOrder,r);
     }
 
-    private void wakeAgents() {
+    private void wakeAgents(CyclicAgent[] agents) {
         while (!executionOrder.isEmpty()) {
-            agents[(executionOrder.pop())].wakeUp();
+            (agents[(executionOrder.pop())]).wakeUp();
+
+        }
+    }
 
+    private void perceiveAll(ThreePhasedAgent[] agents) {
+        for (Integer next : executionOrder) {
+            agents[next].perceive();
         }
     }
 
+    private void decideAll(ThreePhasedAgent[] agents) {
+        for (Integer next : executionOrder) {
+            agents[next].decide();
+        }
+    }
+
+    private void actAll(ThreePhasedAgent[] agents) {
+        for (Integer next : executionOrder) {
+            agents[next].act();
+        }
+        executionOrder.clear();
+    }
+
     @Override
-    public void init(Wakeable[] agents) {
+    public void init(Agent[] agents) {
+        isThreePhased = switch (agents[0]) {
+            case CyclicAgent ignored -> false;
+            case ThreePhasedAgent ignored -> true;
+        };
         this.agents = agents;
         executionOrder = new Stack<>();
     }
@@ -37,6 +64,14 @@ public class FairSynchronousScheduler extends Randomized implements Scheduler {
     @Override
     public void doNextCycle() {
         generateExecutionOrder();
-        wakeAgents();
+        if (isThreePhased) {
+            ThreePhasedAgent[] agents = (ThreePhasedAgent[])this.agents;
+            perceiveAll(agents);
+            decideAll(agents);
+            actAll(agents);
+        }else {
+            CyclicAgent[] agents = (CyclicAgent[])this.agents;
+            wakeAgents(agents);
+        }
     }
 }
diff --git a/src/main/java/scheduler/Scheduler.java b/src/main/java/scheduler/Scheduler.java
index 670d786367e2f0cedac36c7a94d9feb9d2753754..bb2437f7d4ed4c41f50fbfb6b235c5e924f18525 100644
--- a/src/main/java/scheduler/Scheduler.java
+++ b/src/main/java/scheduler/Scheduler.java
@@ -1,10 +1,10 @@
 package scheduler;
 
-import behaviors.Wakeable;
+import agents.Agent;
 
 public interface Scheduler {
 
-    void init(Wakeable[] agents);
+    void init(Agent[] agents);
     void doNextCycle();
 
 }
diff --git a/src/main/java/sma/SEIRS_SMA.java b/src/main/java/sma/SEIRS_SMA.java
index d6352a8bf78e53fb5af22d12a89dfb81fe6063d1..50afb577fa495a13b51d765b75e9430401e5ebf7 100644
--- a/src/main/java/sma/SEIRS_SMA.java
+++ b/src/main/java/sma/SEIRS_SMA.java
@@ -1,13 +1,13 @@
 package sma;
 
-import agents.FairInfectionRWAgent;
-import agents.SEIRSAgent;
+import agents.Agent;
+import agents.RandomWalkingAgent3P;
+import agents.seirs.*;
 import agents.states.InfectedSEIRSState;
 import behaviors.Randomized;
 import environment.SEIRSEnvironment;
 import environment.WrappingChunkedSEIRSEnvironment;
 import models.Parameters;
-import agents.RandomWalkingAgent;
 import environment.ChunkedSEIRSEnvironment;
 import scheduler.DeterministScheduler;
 import scheduler.FairAsynchronousScheduler;
@@ -34,7 +34,7 @@ import java.util.List;
 public class SEIRS_SMA extends Randomized implements SMA{
 
     private final Parameters parameters;
-    private final SEIRSAgent[] agents;
+    private final Agent[] agents;
     private SEIRSEnvironment environment;
     private Scheduler scheduler;
     private StatisticsCanvas statisticsCanvas;
@@ -47,7 +47,11 @@ public class SEIRS_SMA extends Randomized implements SMA{
         super(params.seed());
         parameters = YamlReader.getParams();
         r.setSeed(parameters.seed());
-        agents = new RandomWalkingAgent[parameters.population()];
+        if (parameters.threePhased()) {
+            agents = new ThreePhasedSEIRSAgent[parameters.population()];
+        }else {
+            agents = new CyclicSEIRSAgent[parameters.population()];
+        }
         initEnvironment();
         initPopulation();
         infectPatientZero();
@@ -59,7 +63,7 @@ public class SEIRS_SMA extends Randomized implements SMA{
 
     private void initGraphics() {
         statisticsCanvas = new StatisticsCanvas(300,parameters.size());
-        display = new DisplaySquaredEnvironment(environment,agents);
+        display = new DisplaySquaredEnvironment(environment,(SEIRSAgent[]) agents);
 
         fb.setSimulationCanvas(display);
         fb.setStatsCanvas(statisticsCanvas);
@@ -99,11 +103,19 @@ public class SEIRS_SMA extends Randomized implements SMA{
     private void initPopulation() {
         for (int i = 0; i<parameters.population();i++) {
             Point position = new Point(r.nextInt(parameters.size()),r.nextInt(parameters.size()));
-            SEIRSAgent agent;
-            if (parameters.infectionStacks()) {
-                agent = new RandomWalkingAgent(position,(parameters.seed()+i),environment);
+            Agent agent;
+            if (parameters.threePhased()){
+                if (parameters.infectionStacks()) {
+                    agent = new RandomWalkingAgent3P(position,(parameters.seed()+i),environment);
+                } else {
+                    agent = new FairInfectionRWAgent3P(position,(parameters.seed()+i),environment);
+                }
             } else {
-                agent = new FairInfectionRWAgent(position,(parameters.seed()+i),environment);
+                if (parameters.infectionStacks()) {
+                    agent = new RandomWalkingAgentCyclic(position,(parameters.seed()+i),environment);
+                } else {
+                    agent = new FairInfectionRWAgentCyclic(position,(parameters.seed()+i),environment);
+                }
             }
             agents[i] = agent;
         }
@@ -112,9 +124,9 @@ public class SEIRS_SMA extends Randomized implements SMA{
     private void infectPatientZero() {
         for (int i=0 ; i< parameters.nbOfPatientZero(); i++) {
             int nextInt = (r.nextInt(parameters.population()));
-            SEIRSAgent agent = agents[nextInt];
+            SEIRSAgent agent = (SEIRSAgent)agents[nextInt];
             while (agent.getState() instanceof InfectedSEIRSState) {
-                agent = agents[(r.nextInt(parameters.population()))];
+                agent = (SEIRSAgent)agents[(r.nextInt(parameters.population()))];
             }
             agent.changeState(new InfectedSEIRSState(agent));
         }
@@ -139,9 +151,9 @@ public class SEIRS_SMA extends Randomized implements SMA{
 
     private void initEnvironment() {
         if (parameters.wrappingWorld()) {
-            environment = new WrappingChunkedSEIRSEnvironment(parameters.size(),agents);
+            environment = new WrappingChunkedSEIRSEnvironment(parameters.size(),(SEIRSAgent[]) agents);
         } else {
-            environment = new ChunkedSEIRSEnvironment(parameters.size(),agents);
+            environment = new ChunkedSEIRSEnvironment(parameters.size(),(SEIRSAgent[]) agents);
         }
     }
 
diff --git a/src/main/java/view/DisplaySquaredEnvironment.java b/src/main/java/view/DisplaySquaredEnvironment.java
index 9979a7582dccba83661daee319cf5d6514546318..39317db0a2418b50f662964c30f7f454813516fb 100644
--- a/src/main/java/view/DisplaySquaredEnvironment.java
+++ b/src/main/java/view/DisplaySquaredEnvironment.java
@@ -1,6 +1,6 @@
 package view;
 
-import agents.SEIRSAgent;
+import agents.seirs.SEIRSAgent;
 import agents.states.SEIRSState;
 import environment.ChunkedSEIRSEnvironment;
 import environment.SEIRSEnvironment;
@@ -10,11 +10,11 @@ import java.awt.*;
 
 public class DisplaySquaredEnvironment extends JPanel {
 
-    private final SEIRSAgent[] SEIRSAgents;
+    private final SEIRSAgent[] CyclicSEIRSAgents;
 
-    public DisplaySquaredEnvironment(SEIRSEnvironment environment, SEIRSAgent[] SEIRSAgents) {
+    public DisplaySquaredEnvironment(SEIRSEnvironment environment, SEIRSAgent[] CyclicSEIRSAgents) {
         this.setDoubleBuffered(true);
-        this.SEIRSAgents = SEIRSAgents;
+        this.CyclicSEIRSAgents = CyclicSEIRSAgents;
         setSize(environment.getSize(),environment.getSize());
         setVisible(true);
     }
@@ -29,10 +29,10 @@ public class DisplaySquaredEnvironment extends JPanel {
     @Override
     public void paint(Graphics g) {
         super.paint(g);
-        for (SEIRSAgent SEIRSAgent : SEIRSAgents) {
-            if (SEIRSAgent != null) {
-                colorAgent(g, SEIRSAgent);
-                drawCenteredCircle(g, SEIRSAgent.getPosition().x, SEIRSAgent.getPosition().y);
+        for (SEIRSAgent agent : CyclicSEIRSAgents) {
+            if (agent != null) {
+                colorAgent(g, agent);
+                drawCenteredCircle(g, agent.getPosition().x, agent.getPosition().y);
             }
         }
     }
diff --git a/src/main/resources/parameters.yaml b/src/main/resources/parameters.yaml
index 59a063d0cf29a1f078d7ada55e8ec591524d3b9d..7e7cfa90d8f5ea7146d02d3af7b0cf1ec5bb9654 100644
--- a/src/main/resources/parameters.yaml
+++ b/src/main/resources/parameters.yaml
@@ -7,10 +7,11 @@ nbOfCycles: 2000
 nbOfPatientZero: 1
 population: 3000
 recordExperiment: false
-playRecord: true
+playRecord: false
 seed: 120
 size: 1000
 wrappingWorld : true
 synchronousMode: false
 timeBetweenCycles: 0
-infectionStacks : false
\ No newline at end of file
+infectionStacks : false
+threePhased : true
\ No newline at end of file