From 031d3d94ec45bad69ba1c65645e223d65e2fea66 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Fri, 18 Apr 2025 23:51:42 +0200 Subject: [PATCH] pretty convincing --- app/src/main/java/chess/SwingMain.java | 5 +- app/src/main/java/chess/ai/AlphaBetaAI.java | 9 +- app/src/main/java/chess/ai/HungryAI.java | 2 +- app/src/main/java/chess/ai/PieceCost.java | 12 +- app/src/main/java/chess/ai/PiecePosCost.java | 128 +++++++++++++++++++ app/src/main/java/chess/pgn/PgnExport.java | 2 +- 6 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/chess/ai/PiecePosCost.java diff --git a/app/src/main/java/chess/SwingMain.java b/app/src/main/java/chess/SwingMain.java index 531997c..51d5065 100644 --- a/app/src/main/java/chess/SwingMain.java +++ b/app/src/main/java/chess/SwingMain.java @@ -1,5 +1,6 @@ package chess; +import chess.ai.AI; import chess.ai.AlphaBetaAI; import chess.ai.DumbAI; import chess.ai.HungryAI; @@ -19,10 +20,10 @@ public class SwingMain { Window window = new Window(commandExecutor, false); commandExecutor.addListener(window); - DumbAI ai = new DumbAI(commandExecutor, Color.White); + AI ai = new AlphaBetaAI(commandExecutor, Color.White, 3); commandExecutor.addListener(ai); - AlphaBetaAI ai2 = new AlphaBetaAI(commandExecutor, Color.Black, 3); + AI ai2 = new AlphaBetaAI(commandExecutor, Color.Black, 3); commandExecutor.addListener(ai2); // Window window2 = new Window(ai2.getSimulation(), false); diff --git a/app/src/main/java/chess/ai/AlphaBetaAI.java b/app/src/main/java/chess/ai/AlphaBetaAI.java index 37e8022..e8ce957 100644 --- a/app/src/main/java/chess/ai/AlphaBetaAI.java +++ b/app/src/main/java/chess/ai/AlphaBetaAI.java @@ -17,11 +17,13 @@ import chess.model.Color; import chess.model.Coordinate; import chess.model.Game; import chess.model.Move; +import chess.model.Piece; public class AlphaBetaAI extends AI { private final int searchDepth; private final PieceCost pieceCost; + private final PiecePosCost piecePosCost; private final CommandExecutor simulation; private final Game gameSimulation; @@ -32,6 +34,7 @@ public class AlphaBetaAI extends AI { super(commandExecutor, color); this.searchDepth = searchDepth; this.pieceCost = new PieceCost(color); + this.piecePosCost = new PiecePosCost(color); this.gameSimulation = new Game(); this.simulation = new CommandExecutor(this.gameSimulation, new EmptyGameDispatcher()); } @@ -45,7 +48,9 @@ public class AlphaBetaAI extends AI { int result = 0; for (int i = 0; i < Coordinate.VALUE_MAX; i++) { for (int j = 0; j < Coordinate.VALUE_MAX; j++) { - result += pieceCost.getCost(board.pieceAt(new Coordinate(i, j))); + Coordinate coordinate = new Coordinate(i, j); + Piece piece = board.pieceAt(coordinate); + result += pieceCost.getCost(piece) + piecePosCost.getEvaluation(piece, coordinate); } } if (this.gameSimulation.getPlayerTurn() != color) @@ -60,7 +65,7 @@ public class AlphaBetaAI extends AI { } else { if (this.gameSimulation.getBoard().isKingInCheck(currentTurn)) return GREAT_MOVE; - return getBoardEvaluation() - PieceCost.PAWN; + return getBoardEvaluation() + PieceCost.PAWN; } } diff --git a/app/src/main/java/chess/ai/HungryAI.java b/app/src/main/java/chess/ai/HungryAI.java index 7c1cb54..ed2303c 100644 --- a/app/src/main/java/chess/ai/HungryAI.java +++ b/app/src/main/java/chess/ai/HungryAI.java @@ -26,7 +26,7 @@ public class HungryAI extends AI { private int getMoveCost(Move move) { Piece piece = pieceAt(move.getDeadPieceCoords()); - return pieceCost.getCost(piece); + return -pieceCost.getCost(piece); } private List getBestMoves() { diff --git a/app/src/main/java/chess/ai/PieceCost.java b/app/src/main/java/chess/ai/PieceCost.java index d94e4e0..385be77 100644 --- a/app/src/main/java/chess/ai/PieceCost.java +++ b/app/src/main/java/chess/ai/PieceCost.java @@ -14,12 +14,12 @@ public class PieceCost implements PieceVisitor { private final Color player; - public static final int BISHOP = 3; - public static final int KING = 90; - public static final int KNIGHT = 3; - public static final int PAWN = 1; - public static final int QUEEN = 9; - public static final int ROOK = 5; + public static final int BISHOP = 30; + public static final int KING = 900; + public static final int KNIGHT = 30; + public static final int PAWN = 10; + public static final int QUEEN = 90; + public static final int ROOK = 50; public PieceCost(Color color) { this.player = color; diff --git a/app/src/main/java/chess/ai/PiecePosCost.java b/app/src/main/java/chess/ai/PiecePosCost.java new file mode 100644 index 0000000..be1478e --- /dev/null +++ b/app/src/main/java/chess/ai/PiecePosCost.java @@ -0,0 +1,128 @@ +package chess.ai; + +import java.util.Arrays; +import java.util.List; + +import chess.model.Color; +import chess.model.Coordinate; +import chess.model.Piece; +import chess.model.PieceVisitor; +import chess.model.pieces.Bishop; +import chess.model.pieces.King; +import chess.model.pieces.Knight; +import chess.model.pieces.Pawn; +import chess.model.pieces.Queen; +import chess.model.pieces.Rook; + +public class PiecePosCost implements PieceVisitor> { + + private final Color color; + + private static final List BISHOP = Arrays.asList( + -2, -1, -1, -1, -1, -1, -1, -2, -1, + 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 1, 1, 0, 0, -1, + -1, 0, 0, 1, 1, 0, 0, -1, + -1, 0, 0, 1, 1, 0, 0, -1, + -1, 1, 1, 1, 1, 1, 1, -1, + -1, 0, 0, 0, 0, 0, 0, -1, + -2, -1, -1, -1, -1, -1, -1, -2); + + private static final List KING = Arrays.asList( + -3, -4, -4, -5, -5, -4, -4, -3, + -3, -4, -4, -5, -5, -4, -4, -3, + -3, -4, -4, -5, -5, -4, -4, -3, + -3, -4, -4, -5, -5, -4, -4, -3, + -2, -3, -3, -4, -4, -3, -3, -2, + -1, -2, -2, -2, -2, -2, -2, -1, + 2, 2, 0, 0, 0, 0, 2, 2, + 2, 3, 1, 0, 0, 1, 3, 2); + + private static final List KNIGHT = Arrays.asList( + -5, -4, -3, -3, -3, -3, -4, -5, -4, + -2, 0, 0, 0, 0, -2, -4, + -3, 0, 1, 1, 1, 1, 0, -3, + -3, 0, 1, 2, 2, 1, 0, -3, + -3, 0, 1, 2, 2, 1, 0, -3, + -3, 0, 1, 1, 1, 1, 0, -3, + -4, -2, 0, 0, 0, 0, -2, -4, + -5, -4, -3, -3, -3, -3, -4, -5); + + private static final List PAWN = Arrays.asList( + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, + 1, 1, 2, 3, 3, 2, 1, 1, + 0, 0, 1, 2, 2, 1, 0, 0, + 0, 0, 1, 2, 2, 1, 0, 0, + 0, 0, -1, 0, 0, -1, 0, 0, + 0, 1, 1, -2, -2, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0); + + private static final List QUEEN = Arrays.asList( + -2, -1, -1, 0, 0, -1, -1, -2, + -1, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, -1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + -1, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, -1, + -2, -1, -1, 0, 0, -1, -1, -2); + + private static final List ROOK = Arrays.asList( + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + -1, 0, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, 0, -1, + 0, 0, 0, 0, 1, 1, 0, 0, 0); + + public PiecePosCost(Color color) { + this.color = color; + } + + public int getEvaluation(Piece piece, Coordinate coordinate) { + if (piece == null) + return 0; + List positions = visit(piece); + int y = piece.getColor() == Color.Black ? (Coordinate.VALUE_MAX - 1 - coordinate.getY()) : coordinate.getY(); + Coordinate newCoords = new Coordinate(coordinate.getX(), y); + assert newCoords.isValid(); + int result = positions.get(newCoords.toIndex()); + if (piece.getColor() != color) + return -result; + return result; + } + + @Override + public List visitPiece(Bishop bishop) { + return BISHOP; + } + + @Override + public List visitPiece(King king) { + return KING; + } + + @Override + public List visitPiece(Knight knight) { + return KNIGHT; + } + + @Override + public List visitPiece(Pawn pawn) { + return PAWN; + } + + @Override + public List visitPiece(Queen queen) { + return QUEEN; + } + + @Override + public List visitPiece(Rook rook) { + return ROOK; + } + +} diff --git a/app/src/main/java/chess/pgn/PgnExport.java b/app/src/main/java/chess/pgn/PgnExport.java index 22e0cf7..31e57bd 100644 --- a/app/src/main/java/chess/pgn/PgnExport.java +++ b/app/src/main/java/chess/pgn/PgnExport.java @@ -56,7 +56,7 @@ public class PgnExport { } private static String gameEnd(Game game) { - switch (game.checkGameStatus()) { + switch (game.checkGameStatus(game.getPlayerTurn())) { case Draw: case Pat: return "1/2-1/2";