Fixes?
This commit is contained in:
parent
bd0fc7edfd
commit
02b49c9437
|
@ -4,21 +4,11 @@
|
||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="41395b4b-3252-492c-a869-5f4dab107186" name="Changes" comment="AI">
|
<list default="true" id="41395b4b-3252-492c-a869-5f4dab107186" name="Changes" comment="Fixes?">
|
||||||
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/IPawn.java" afterDir="false" />
|
|
||||||
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingBoard.java" afterDir="false" />
|
|
||||||
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingPawn.java" afterDir="false" />
|
|
||||||
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingPushed.java" afterDir="false" />
|
|
||||||
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingPusher.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Pawn.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Pawn.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingBoard.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingBoard.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Player.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Player.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Pushed.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Pushed.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Pusher.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Pusher.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<list id="98b8a79f-2f53-42bf-96da-7af322697a0d" name="Changes by acastonguay" comment="" />
|
<list id="98b8a79f-2f53-42bf-96da-7af322697a0d" name="Changes by acastonguay" comment="" />
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
@ -143,7 +133,8 @@
|
||||||
<workItem from="1679365557789" duration="21000" />
|
<workItem from="1679365557789" duration="21000" />
|
||||||
<workItem from="1679424430928" duration="11764000" />
|
<workItem from="1679424430928" duration="11764000" />
|
||||||
<workItem from="1679593788411" duration="10753000" />
|
<workItem from="1679593788411" duration="10753000" />
|
||||||
<workItem from="1679672719638" duration="7700000" />
|
<workItem from="1679672719638" duration="8340000" />
|
||||||
|
<workItem from="1679779362814" duration="5861000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="MiniMax">
|
<task id="LOCAL-00001" summary="MiniMax">
|
||||||
<created>1679263366439</created>
|
<created>1679263366439</created>
|
||||||
|
@ -166,7 +157,14 @@
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1679490100944</updated>
|
<updated>1679490100944</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="4" />
|
<task id="LOCAL-00004" summary="Fixes?">
|
||||||
|
<created>1679682974611</created>
|
||||||
|
<option name="number" value="00004" />
|
||||||
|
<option name="presentableId" value="LOCAL-00004" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1679682974611</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="5" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
@ -176,7 +174,8 @@
|
||||||
<MESSAGE value="MiniMax" />
|
<MESSAGE value="MiniMax" />
|
||||||
<MESSAGE value="Movement logic" />
|
<MESSAGE value="Movement logic" />
|
||||||
<MESSAGE value="Small fixes" />
|
<MESSAGE value="Small fixes" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="Small fixes" />
|
<MESSAGE value="Fixes?" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="Fixes?" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager>
|
<breakpoint-manager>
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class Client {
|
||||||
board.move(previousMove);
|
board.move(previousMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.sleep(500);
|
// Thread.sleep(500);
|
||||||
|
|
||||||
String nextMove = board.runNextMove();
|
String nextMove = board.runNextMove();
|
||||||
System.out.println("Prochain mouvement: " + nextMove);
|
System.out.println("Prochain mouvement: " + nextMove);
|
||||||
|
|
|
@ -1,144 +1,143 @@
|
||||||
package laboratoire4;
|
package laboratoire4;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class MiniMax {
|
public class MiniMax {
|
||||||
private static final int MAX_DEPTH = 1;
|
private static final int MAX_DEPTH = 4;
|
||||||
|
|
||||||
public static MiniMaxResult miniMax(PusherBoard board) {
|
public static MiniMaxResult miniMax(PusherBoard board) {
|
||||||
|
long startMillis = System.currentTimeMillis();
|
||||||
MovingBoard game = new MovingBoard(board.getBoard(), board.getPlayer());
|
MovingBoard game = new MovingBoard(board.getBoard(), board.getPlayer());
|
||||||
return miniMax(game, true, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
Collection<Action> actions = getActions(game, true);
|
||||||
|
|
||||||
|
MiniMaxResult maxResult = null;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MiniMaxResult miniMax(MovingBoard game, boolean max, int depth, int alpha, int beta) {
|
long endMillis = System.currentTimeMillis();
|
||||||
depth += 1;
|
System.out.printf("%d ms\n", (endMillis - startMillis));
|
||||||
|
|
||||||
if (max) {
|
return maxResult;
|
||||||
return max(game, depth, alpha, beta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return min(game, depth, alpha, beta);
|
private static int max(MovingBoard game, int depth, int alpha, int beta) {
|
||||||
|
if (depth >= MAX_DEPTH) {
|
||||||
|
return evaluate(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MiniMaxResult max(MovingBoard game, int depth, int alpha, int beta) {
|
int maxScore = Integer.MIN_VALUE;
|
||||||
int alphaT = Integer.MIN_VALUE;
|
|
||||||
MovingPawn lastPawn = null;
|
|
||||||
Pawn.PawnMovement lastMovement = null;
|
|
||||||
|
|
||||||
for (MovingPawn pawn : game.getMaxPawns()) {
|
for (Action action : getActions(game, true)) {
|
||||||
for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
|
MovingPawn pawn = action.getPawn();
|
||||||
if (!pawn.isMoveValid(game.getBoard(), movement)) {
|
Pawn.PawnMovement movement = action.getMovement();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPawn = pawn;
|
|
||||||
lastMovement = movement;
|
|
||||||
|
|
||||||
game.move(pawn, movement);
|
game.move(pawn, movement);
|
||||||
|
int score = min(game, depth + 1, Math.max(alpha, maxScore), beta);
|
||||||
int score = evaluate(pawn, game, depth);
|
|
||||||
if (depth < MAX_DEPTH) {
|
|
||||||
score = miniMax(game, false, depth, Math.max(alpha, alphaT), beta).getScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
game.revertMove();
|
game.revertMove();
|
||||||
|
|
||||||
if (score > alphaT) {
|
if (score > maxScore) {
|
||||||
alphaT = score;
|
maxScore = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alphaT >= beta) {
|
if (maxScore >= beta) {
|
||||||
return new MiniMaxResult(alphaT, pawn.getRow(), pawn.getCol(), movement);
|
return maxScore;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastPawn == null) {
|
return maxScore;
|
||||||
return new MiniMaxResult(alphaT, 0, 0, null);
|
|
||||||
}
|
|
||||||
return new MiniMaxResult(alphaT, lastPawn.getRow(), lastPawn.getCol(), lastMovement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MiniMaxResult min(MovingBoard game, int depth, int alpha, int beta) {
|
private static int min(MovingBoard game, int depth, int alpha, int beta) {
|
||||||
int betaT = Integer.MAX_VALUE;
|
if (depth >= MAX_DEPTH) {
|
||||||
MovingPawn lastPawn = null;
|
return evaluate(game);
|
||||||
Pawn.PawnMovement lastMovement = null;
|
|
||||||
|
|
||||||
for (MovingPawn pawn : game.getMinPawns()) {
|
|
||||||
for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
|
|
||||||
if (!pawn.isMoveValid(game.getBoard(), movement)) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPawn = pawn;
|
int minScore = Integer.MAX_VALUE;
|
||||||
lastMovement = movement;
|
|
||||||
|
for (Action action : getActions(game, false)) {
|
||||||
|
MovingPawn pawn = action.getPawn();
|
||||||
|
Pawn.PawnMovement movement = action.getMovement();
|
||||||
|
|
||||||
game.move(pawn, movement);
|
game.move(pawn, movement);
|
||||||
|
int score = max(game, depth + 1, alpha, Math.min(beta, minScore)) * -1;
|
||||||
int score = evaluate(pawn, game, depth);
|
|
||||||
if (depth < MAX_DEPTH) {
|
|
||||||
score = miniMax(game, true, depth, alpha, Math.min(betaT, beta)).getScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
game.revertMove();
|
game.revertMove();
|
||||||
|
|
||||||
if (score < betaT) {
|
if (score < minScore) {
|
||||||
betaT = score;
|
minScore = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (betaT <= beta) {
|
if (minScore <= alpha) {
|
||||||
return new MiniMaxResult(betaT, pawn.getRow(), pawn.getCol(), movement);
|
return minScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return minScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<Action> getActions(MovingBoard game, boolean max) {
|
||||||
|
List<Action> actions = new ArrayList<>();
|
||||||
|
Collection<MovingPawn> 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) {
|
Collections.shuffle(actions);
|
||||||
return new MiniMaxResult(betaT, 0, 0, null);
|
return actions;
|
||||||
}
|
|
||||||
return new MiniMaxResult(betaT, lastPawn.getRow(), lastPawn.getCol(), lastMovement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int evaluate(IPawn pawn, MovingBoard game, int depth) {
|
private static int evaluate(MovingBoard board) {
|
||||||
int score = didWin(pawn) + didCapture(pawn, game);
|
return evaluate(board, board.getMaxPawns()) - evaluate(board, board.getMinPawns());
|
||||||
|
}
|
||||||
|
|
||||||
score += pawn.isPusher() ? 0 : 5;
|
private static int evaluate(MovingBoard board, Collection<MovingPawn> pawns) {
|
||||||
|
int score = pawns.size() * 5;
|
||||||
|
|
||||||
|
for (MovingPawn pawn : pawns) {
|
||||||
int row = pawn.getRow();
|
int row = pawn.getRow();
|
||||||
int col = pawn.getCol();
|
int goal = pawn.getPlayer().getGoal();
|
||||||
int nextNextRow = row + pawn.getDirection() * 2;
|
|
||||||
|
|
||||||
// Attire nos pusher vers nos pushed
|
if (row == goal) {
|
||||||
if (pawn.isPusher() && nextNextRow >= 0 && nextNextRow <= 7) {
|
return Integer.MAX_VALUE;
|
||||||
for (Pawn.PawnMovement move : Pawn.PawnMovement.values()) {
|
|
||||||
int nextCol = col + move.getMove();
|
|
||||||
if (nextCol < 0 || nextCol > 7) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPawn nearPawn = game.getBoard()[nextNextRow][nextCol];
|
score += Math.abs(goal - row);
|
||||||
if (nearPawn != null && !nearPawn.isPusher() && nearPawn.getPlayer() == pawn.getPlayer()) {
|
|
||||||
score += 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return score * pawn.getDirection();
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int didWin(IPawn pawn) {
|
static class Action {
|
||||||
if (pawn.getRow() == pawn.getPlayer().getGoal()) {
|
private final MovingPawn pawn;
|
||||||
return 100;
|
private final Pawn.PawnMovement movement;
|
||||||
|
|
||||||
|
public Action(MovingPawn pawn, Pawn.PawnMovement movement) {
|
||||||
|
this.pawn = pawn;
|
||||||
|
this.movement = movement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
public MovingPawn getPawn() {
|
||||||
|
return pawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int didCapture(IPawn pawn, MovingBoard game) {
|
public Pawn.PawnMovement getMovement() {
|
||||||
IPawn capturedPawn = game.getBoard()[pawn.getRow()][pawn.getCol()];
|
return movement;
|
||||||
|
|
||||||
if (capturedPawn != null && capturedPawn.getPlayer() != game.getPlayer()) {
|
|
||||||
return 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MiniMaxResult {
|
static class MiniMaxResult {
|
||||||
|
|
|
@ -49,6 +49,10 @@ public class MovingBoard {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasCaptured() {
|
||||||
|
return removedPawns.peek() != null;
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<MovingPawn> getMaxPawns() {
|
public Collection<MovingPawn> getMaxPawns() {
|
||||||
return getPawns(p -> p.getPlayer() == player);
|
return getPawns(p -> p.getPlayer() == player);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue