diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 9b1e07b..bb4456a 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,21 +4,11 @@
-
-
-
-
-
-
-
+
-
-
-
-
-
+
@@ -143,7 +133,8 @@
-
+
+
1679263366439
@@ -166,7 +157,14 @@
1679490100944
-
+
+ 1679682974611
+
+
+
+ 1679682974611
+
+
@@ -176,7 +174,8 @@
-
+
+
diff --git a/src/main/java/laboratoire4/Client.java b/src/main/java/laboratoire4/Client.java
index d42ce78..b76468a 100644
--- a/src/main/java/laboratoire4/Client.java
+++ b/src/main/java/laboratoire4/Client.java
@@ -76,7 +76,7 @@ public class Client {
board.move(previousMove);
}
- Thread.sleep(500);
+// Thread.sleep(500);
String nextMove = board.runNextMove();
System.out.println("Prochain mouvement: " + nextMove);
diff --git a/src/main/java/laboratoire4/MiniMax.java b/src/main/java/laboratoire4/MiniMax.java
index 5506734..115ae1f 100644
--- a/src/main/java/laboratoire4/MiniMax.java
+++ b/src/main/java/laboratoire4/MiniMax.java
@@ -1,144 +1,143 @@
package laboratoire4;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
public class MiniMax {
- private static final int MAX_DEPTH = 1;
+ private static final int MAX_DEPTH = 4;
public static MiniMaxResult miniMax(PusherBoard board) {
+ long startMillis = System.currentTimeMillis();
MovingBoard game = new MovingBoard(board.getBoard(), board.getPlayer());
- return miniMax(game, true, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
- }
+ Collection actions = getActions(game, true);
- private static MiniMaxResult miniMax(MovingBoard game, boolean max, int depth, int alpha, int beta) {
- depth += 1;
+ MiniMaxResult maxResult = null;
- if (max) {
- return max(game, depth, alpha, beta);
+ for (Action action : actions) {
+ int score = min(game, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
+
+ if (maxResult == null || score > maxResult.getScore()) {
+ MovingPawn pawn = action.getPawn();
+ maxResult = new MiniMaxResult(score, pawn.getRow(), pawn.getCol(), action.getMovement());
+ }
}
- return min(game, depth, alpha, beta);
+ long endMillis = System.currentTimeMillis();
+ System.out.printf("%d ms\n", (endMillis - startMillis));
+
+ return maxResult;
}
- private static MiniMaxResult max(MovingBoard game, int depth, int alpha, int beta) {
- int alphaT = Integer.MIN_VALUE;
- MovingPawn lastPawn = null;
- Pawn.PawnMovement lastMovement = null;
+ private static int max(MovingBoard game, int depth, int alpha, int beta) {
+ if (depth >= MAX_DEPTH) {
+ return evaluate(game);
+ }
- for (MovingPawn pawn : game.getMaxPawns()) {
- for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
- if (!pawn.isMoveValid(game.getBoard(), movement)) {
- continue;
- }
+ int maxScore = Integer.MIN_VALUE;
- lastPawn = pawn;
- lastMovement = movement;
+ for (Action action : getActions(game, true)) {
+ MovingPawn pawn = action.getPawn();
+ Pawn.PawnMovement movement = action.getMovement();
- game.move(pawn, movement);
+ game.move(pawn, movement);
+ int score = min(game, depth + 1, Math.max(alpha, maxScore), beta);
+ game.revertMove();
- int score = evaluate(pawn, game, depth);
- if (depth < MAX_DEPTH) {
- score = miniMax(game, false, depth, Math.max(alpha, alphaT), beta).getScore();
- }
+ if (score > maxScore) {
+ maxScore = score;
+ }
- game.revertMove();
+ if (maxScore >= beta) {
+ return maxScore;
+ }
+ }
- if (score > alphaT) {
- alphaT = score;
- }
+ return maxScore;
+ }
- if (alphaT >= beta) {
- return new MiniMaxResult(alphaT, pawn.getRow(), pawn.getCol(), movement);
+ private static int min(MovingBoard game, int depth, int alpha, int beta) {
+ if (depth >= MAX_DEPTH) {
+ return evaluate(game);
+ }
+
+ int minScore = Integer.MAX_VALUE;
+
+ for (Action action : getActions(game, false)) {
+ MovingPawn pawn = action.getPawn();
+ Pawn.PawnMovement movement = action.getMovement();
+
+ game.move(pawn, movement);
+ int score = max(game, depth + 1, alpha, Math.min(beta, minScore)) * -1;
+ game.revertMove();
+
+ if (score < minScore) {
+ minScore = score;
+ }
+
+ if (minScore <= alpha) {
+ return minScore;
+ }
+ }
+
+ return minScore;
+ }
+
+ private static Collection getActions(MovingBoard game, boolean max) {
+ List actions = new ArrayList<>();
+ Collection pawns = max ? game.getMaxPawns() : game.getMinPawns();
+ Pawn.PawnMovement[] movements = Pawn.PawnMovement.values();
+
+ for (MovingPawn pawn : pawns) {
+ for (Pawn.PawnMovement movement : movements) {
+ if (pawn.isMoveValid(game.getBoard(), movement)) {
+ actions.add(new Action(pawn, movement));
}
}
}
- if (lastPawn == null) {
- return new MiniMaxResult(alphaT, 0, 0, null);
- }
- return new MiniMaxResult(alphaT, lastPawn.getRow(), lastPawn.getCol(), lastMovement);
+ Collections.shuffle(actions);
+ return actions;
}
- private static MiniMaxResult min(MovingBoard game, int depth, int alpha, int beta) {
- int betaT = Integer.MAX_VALUE;
- MovingPawn lastPawn = null;
- Pawn.PawnMovement lastMovement = null;
+ private static int evaluate(MovingBoard board) {
+ return evaluate(board, board.getMaxPawns()) - evaluate(board, board.getMinPawns());
+ }
- for (MovingPawn pawn : game.getMinPawns()) {
- for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
- if (!pawn.isMoveValid(game.getBoard(), movement)) {
- continue;
- }
+ private static int evaluate(MovingBoard board, Collection pawns) {
+ int score = pawns.size() * 5;
- lastPawn = pawn;
- lastMovement = movement;
+ for (MovingPawn pawn : pawns) {
+ int row = pawn.getRow();
+ int goal = pawn.getPlayer().getGoal();
- game.move(pawn, movement);
-
- int score = evaluate(pawn, game, depth);
- if (depth < MAX_DEPTH) {
- score = miniMax(game, true, depth, alpha, Math.min(betaT, beta)).getScore();
- }
-
- game.revertMove();
-
- if (score < betaT) {
- betaT = score;
- }
-
- if (betaT <= beta) {
- return new MiniMaxResult(betaT, pawn.getRow(), pawn.getCol(), movement);
- }
+ if (row == goal) {
+ return Integer.MAX_VALUE;
}
+
+ score += Math.abs(goal - row);
}
- if (lastPawn == null) {
- return new MiniMaxResult(betaT, 0, 0, null);
- }
- return new MiniMaxResult(betaT, lastPawn.getRow(), lastPawn.getCol(), lastMovement);
+ return score;
}
- private static int evaluate(IPawn pawn, MovingBoard game, int depth) {
- int score = didWin(pawn) + didCapture(pawn, game);
+ static class Action {
+ private final MovingPawn pawn;
+ private final Pawn.PawnMovement movement;
- score += pawn.isPusher() ? 0 : 5;
-
- int row = pawn.getRow();
- int col = pawn.getCol();
- int nextNextRow = row + pawn.getDirection() * 2;
-
- // Attire nos pusher vers nos pushed
- if (pawn.isPusher() && nextNextRow >= 0 && nextNextRow <= 7) {
- for (Pawn.PawnMovement move : Pawn.PawnMovement.values()) {
- int nextCol = col + move.getMove();
- if (nextCol < 0 || nextCol > 7) {
- continue;
- }
-
- IPawn nearPawn = game.getBoard()[nextNextRow][nextCol];
- if (nearPawn != null && !nearPawn.isPusher() && nearPawn.getPlayer() == pawn.getPlayer()) {
- score += 5;
- }
- }
+ public Action(MovingPawn pawn, Pawn.PawnMovement movement) {
+ this.pawn = pawn;
+ this.movement = movement;
}
- return score * pawn.getDirection();
- }
-
- private static int didWin(IPawn pawn) {
- if (pawn.getRow() == pawn.getPlayer().getGoal()) {
- return 100;
+ public MovingPawn getPawn() {
+ return pawn;
}
- return 0;
- }
-
- private static int didCapture(IPawn pawn, MovingBoard game) {
- IPawn capturedPawn = game.getBoard()[pawn.getRow()][pawn.getCol()];
-
- if (capturedPawn != null && capturedPawn.getPlayer() != game.getPlayer()) {
- return 500;
+ public Pawn.PawnMovement getMovement() {
+ return movement;
}
-
- return 0;
}
static class MiniMaxResult {
diff --git a/src/main/java/laboratoire4/MovingBoard.java b/src/main/java/laboratoire4/MovingBoard.java
index 4f267ef..739047a 100644
--- a/src/main/java/laboratoire4/MovingBoard.java
+++ b/src/main/java/laboratoire4/MovingBoard.java
@@ -49,6 +49,10 @@ public class MovingBoard {
return player;
}
+ public boolean hasCaptured() {
+ return removedPawns.peek() != null;
+ }
+
public Collection getMaxPawns() {
return getPawns(p -> p.getPlayer() == player);
}